diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f3fda8275..7fb1d79ddf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -198,11 +198,11 @@ jobs: cat "${RUNNER_TEMP}/webui-backend.log" 2>/dev/null || true build-macos: - # Builds the C++ kernel + TTY, the Java GUI, the embedded-Prolog optimizer - # engine and the JPL optimizer server (OptServer), then runs the full test - # suite including the optimizer test. The optimizer test drives SecondoBDB in - # "-pl" mode (embeds libswipl, no JPL); OptServer uses JPL, which is why the - # Install step rebuilds swi-prolog from source with the Java package on. + # Builds the C++ kernel + TTY, the Java GUI and the embedded-Prolog + # optimizer engine, then runs the full test suite including the optimizer + # test. The optimizer test drives SecondoBDB in "-pl" mode, which embeds + # libswipl from the stock swi-prolog bottle -- no JPL, so no custom Prolog + # build is needed. strategy: fail-fast: false matrix: @@ -222,57 +222,11 @@ jobs: - name: Install Homebrew packages run: | brew update - # Build tools + the external components the SDK used to provide. + # Build tools + the external components the SDK used to provide. The + # embedded optimizer links libswipl from the stock swi-prolog bottle; + # no JPL and no custom Prolog build are needed anymore. brew install flex bison berkeley-db gsl jpeg-turbo boost gmp \ - libxml2 readline nlohmann-json - # JPL is built against openjdk@21 -- the SAME major version as the - # Temurin JDK below that compiles OptimizerServer.java. - brew install openjdk@21 - # swi-prolog's own dependencies come from bottles and are cheap; only - # the keg itself is expensive to build, and that one is cached below. - brew install --only-dependencies swi-prolog - # The Cellar path is /opt/homebrew on arm64 and /usr/local on Intel. - echo "SWIPL_CELLAR=$(brew --cellar)/swi-prolog" >> "$GITHUB_ENV" - echo "SWIPL_VERSION=$(brew info --json=v2 swi-prolog | - jq -r '.formulae[0].versions.stable')" >> "$GITHUB_ENV" - - # Building swi-prolog from source takes several minutes, so keep the - # finished keg. - - name: Cache swi-prolog (built with JPL) - id: swipl-cache - uses: actions/cache@v6 - with: - path: ${{ env.SWIPL_CELLAR }} - key: swipl-jpl-${{ matrix.os }}-${{ runner.arch }}-${{ env.SWIPL_VERSION }}-v1 - - - name: Build swi-prolog with JPL - if: steps.swipl-cache.outputs.cache-hit != 'true' - run: | - # The stock swi-prolog bottle is built with -DSWIPL_PACKAGES_JAVA=OFF, - # so it ships no jpl.jar / libjpl.dylib which the JPL optimizer - # server (OptServer) needs. Editing the formula requires the real - # homebrew/core tap rather than the API. - export HOMEBREW_NO_INSTALL_FROM_API=1 - brew tap homebrew/core - formula="$(brew formula swi-prolog)" - echo "Editing formula: $formula" - sed -i '' 's/-DSWIPL_PACKAGES_JAVA=OFF/-DSWIPL_PACKAGES_JAVA=ON/' "$formula" - sed -i '' 's/^ def install/ depends_on "openjdk@21" => :build\n def install/' "$formula" - grep -nE 'SWIPL_PACKAGES_JAVA|openjdk' "$formula" - brew install --build-from-source swi-prolog - - - name: Link cached swi-prolog - if: steps.swipl-cache.outputs.cache-hit == 'true' - run: | - # The cache restores the keg, but not its symlinks into the prefix. - brew link --overwrite swi-prolog - - - name: Verify that JPL is present - run: | - # Guards both the fresh build and a stale/corrupt cache entry. - plbase="$(swipl --dump-runtime-variables | sed -n 's/^PLBASE="\(.*\)";/\1/p')" - ls -l "$plbase/lib/jpl.jar" - find "$plbase" -name 'libjpl.*' -print + libxml2 readline nlohmann-json swi-prolog - name: Install Temurin JDK uses: actions/setup-java@v5 diff --git a/.gitignore b/.gitignore index 5cd34de91d..2a28dba976 100644 --- a/.gitignore +++ b/.gitignore @@ -106,6 +106,7 @@ makefile.algebras /OptParser/scanner.c /Optimizer/libregSecondo.so /Optimizer/libregSecondo.jnilib +/Optimizer/optimizer /Optimizer/opsyntaxg.pl /Optimizer/tmp/ /Optimizer/.secondopltty_history @@ -126,6 +127,7 @@ makefile.algebras /Optimizer/TestOptimizer.log /OptimizerBasic/libregSecondo.so /OptimizerBasic/libregSecondo.jnilib +/Optimizer/temp_nested_list/ /bin/*.jpg /bin/*.dbf diff --git a/CM-Scripts/initdemo.sh b/CM-Scripts/initdemo.sh deleted file mode 100644 index f1e658f2e8..0000000000 --- a/CM-Scripts/initdemo.sh +++ /dev/null @@ -1,28 +0,0 @@ -# -# Preconditions: -# -# - We assume that you have alread installed MSYS -# - Moreover, there must be a java runtime environment JDK 1.4.2 or above -# -# If this is true, adjust the variables ROOT and SWI_HOME_DIR -# afterwards always run -# -# source initdemo.sh - -# Please configure the root path -# C: -> /c -ROOT="/home/Markus/secondo" - -export PATH=$PATH:$ROOT/bin - -# Prolog Settings -export SWI_HOME_DIR="C:\msys\1.0\home\Markus\secondo" - -# SECONDO Settings -export SECONDO_PLATFORM="win32" -export SECONDO_CONFIG="$ROOT/bin/SecondoConfig.ini" - -export JPL_JAR=$ROOT/bin/jpl.jar -export JPL_DLL="true" -export PL_DLL_DIR=$ROOT/bin - diff --git a/CM-Scripts/run-tests.sh b/CM-Scripts/run-tests.sh index bfea6e0ac4..d285c1a87b 100755 --- a/CM-Scripts/run-tests.sh +++ b/CM-Scripts/run-tests.sh @@ -151,16 +151,14 @@ done # # Optimizer tests (skippable via SECONDO_SKIP_OPTIMIZER_TESTS, e.g. when the -# optimizer and the JPL optimizer server were not built). TestOptimizer drives -# the optimizer through the embedded Prolog interface; TestOptServer exercises -# the JPL optimizer server (OptServer) over its socket protocol. +# optimizer was not built). TestOptimizer drives the optimizer through the +# embedded Prolog interface. # if [ "${SECONDO_SKIP_OPTIMIZER_TESTS:-}" == "true" ]; then echo "*** Skipping optimizer tests (SECONDO_SKIP_OPTIMIZER_TESTS=true) ***" else echo "*** Executing optimizer tests ***" runTest ${buildDir}/Optimizer "TestOptimizer" "time TestOptimizer" $timeOutMax - runTest ${buildDir}/Optimizer "TestOptServer" "time TestOptServer" $timeOutMax # Guards against the SecondoPL autoloading regression (must_be/2 spam at # optimizer startup); see Optimizer/TestSecondoPLStartup. runTest ${buildDir}/Optimizer "TestSecondoPLStartup" \ diff --git a/CM-Scripts/secondo-detect.sh b/CM-Scripts/secondo-detect.sh index 2c6261b588..4d64bb819b 100755 --- a/CM-Scripts/secondo-detect.sh +++ b/CM-Scripts/secondo-detect.sh @@ -22,16 +22,6 @@ secondo_realpath() { ( cd "$(dirname "$p")" 2>/dev/null && printf '%s/%s\n' "$(pwd)" "$(basename "$p")" ) } -# Map a Prolog version number (e.g. 90209) to the JPL binding directory that -# OptServer/OptParser/Jpl build (10/30/70/82). Mirrors makefile.optimizer. -secondo_jplver() { - local v=${1:-0} - if [ "$v" -lt 50200 ] 2>/dev/null; then echo 10 - elif [ "$v" -lt 70000 ] 2>/dev/null; then echo 30 - elif [ "$v" -lt 80200 ] 2>/dev/null; then echo 70 - else echo 82; fi -} - secondo_detect() { local os machine cand jc jvmdir opener os=$(uname -s); machine=$(uname -m) @@ -58,34 +48,20 @@ secondo_detect() { export SECONDO_PLATFORM # --- Prolog (single source of truth: the swipl binary itself) ------------ - # `swipl --dump-runtime-variables` reports version AND lib dir together, so - # the JPL binding directory can never drift from the linked libswipl. + # `swipl --dump-runtime-variables` reports the lib/include dirs together, so + # they can never drift from the linked libswipl. The embedded optimizer links + # libswipl in -pl mode; it needs no JPL (that was only the retired OptServer). local swipl=${SECONDO_SWIPL:-$(command -v swipl 2>/dev/null || command -v pl 2>/dev/null)} SECONDO_PL_FOUND=no if [ -n "$swipl" ] && "$swipl" --dump-runtime-variables >/dev/null 2>&1; then # sets PLBASE, PLLIBDIR, PLVERSION, PLARCH, PLSOEXT, ... as shell vars eval "$("$swipl" --dump-runtime-variables)" - : "${PL_VERSION:=$PLVERSION}" : "${SWI_HOME_DIR:=$PLBASE}" : "${PL_LIB_DIR:=$PLLIBDIR}" : "${PL_DLL_DIR:=$PLLIBDIR}" : "${PL_INCLUDE_DIR:=$PLBASE/include}" : "${PL_LIB:=swipl}" - : "${JPL_JAR:=$PLBASE/lib/jpl.jar}" - # The JPL library is libjpl.so on Linux but libjpl.dylib on macOS, while - # swipl reports PLSOEXT=so on BOTH. Probe for the file that is really there - # rather than deriving its name from PLSOEXT. - if [ -z "${JPL_DLL:-}" ]; then - for _jpl in "$PLLIBDIR/libjpl.$PLSOEXT" "$PLLIBDIR/libjpl.dylib" \ - "$PLLIBDIR/libjpl.so"; do - if [ -f "$_jpl" ]; then JPL_DLL=$_jpl; break; fi - done - # Nothing found: keep the conventional name so --check can report it. - : "${JPL_DLL:=$PLLIBDIR/libjpl.$PLSOEXT}" - unset _jpl - fi - export PL_VERSION SWI_HOME_DIR PL_LIB_DIR PL_DLL_DIR PL_INCLUDE_DIR - export PL_LIB JPL_JAR JPL_DLL + export SWI_HOME_DIR PL_LIB_DIR PL_DLL_DIR PL_INCLUDE_DIR PL_LIB SECONDO_PL_FOUND=yes fi @@ -194,7 +170,7 @@ secondo_detect() { [ -n "${LIBRARY_PATH:-}" ] && export LIBRARY_PATH fi - # --- JVM runtime dir (only the optimizer / JPL / JNI need libjvm) --------- + # --- JVM runtime dir (only the JNI-based algebras need libjvm) ----------- # libdb_cxx and libswipl resolve on the default loader path; libjvm never # does, so this is the single directory the runtime linker actually needs. jvmdir="" @@ -246,48 +222,31 @@ secondo_detect() { # Warn about drift/mismatch cases that used to fail silently. # Returns non-zero if anything was flagged. secondo_env_warnings() { - local w=0 live_swipl live_ver + local w=0 if [ "${SECONDO_PL_FOUND:-no}" != yes ]; then echo " ! swipl not found -> optimizer disabled (install swi-prolog, or set SECONDO_SWIPL)"; w=1 fi if [ -z "${J2SDK_ROOT:-}" ] || [ ! -e "${J2SDK_ROOT:-/nonexistent}" ]; then - echo " ! JDK not found -> Java GUI / optimizer server will not build (set J2SDK_ROOT)"; w=1 + echo " ! JDK not found -> Java GUI will not build (set J2SDK_ROOT)"; w=1 fi if [ ! -f "${BERKELEY_DB_DIR:-/nonexistent}/include/db_cxx.h" ]; then echo " ! db_cxx.h not under ${BERKELEY_DB_DIR:-?} (set BERKELEY_DB_DIR)"; w=1 fi - # OptServer/OptTest link against libjpl; without it they fail late, at link - # time. A swipl built without the Java package ships no JPL at all. - if [ "${SECONDO_PL_FOUND:-no}" = yes ] && [ ! -f "${JPL_DLL:-/nonexistent}" ]; then - echo " ! JPL library not found at ${JPL_DLL:-?} -> optimizer server will not link" - echo " (swi-prolog must be built with the Java package, see the macOS install guide)" - w=1 - fi - # exported PL_VERSION vs the swipl actually on PATH now (stale shell / upgrade) - live_swipl=${SECONDO_SWIPL:-$(command -v swipl 2>/dev/null || command -v pl 2>/dev/null)} - if [ -n "$live_swipl" ] && [ -n "${PL_VERSION:-}" ]; then - live_ver=$("$live_swipl" --dump-runtime-variables 2>/dev/null \ - | sed -n 's/^PLVERSION="\([0-9]*\)".*/\1/p') - if [ -n "$live_ver" ] && [ "$live_ver" != "$PL_VERSION" ]; then - echo " ! PL_VERSION=$PL_VERSION but $live_swipl reports $live_ver -> re-source your .secondorc"; w=1 - fi - fi return $w } # One-line summary (+ warnings). This is what the build prints once per run. secondo_env_summary() { - local jplver pl - jplver=$(secondo_jplver "${PL_VERSION:-0}") - if [ "${SECONDO_PL_FOUND:-no}" = yes ]; then pl="${PL_VERSION} -> JPL/${jplver}"; else pl="none"; fi + local pl + if [ "${SECONDO_PL_FOUND:-no}" = yes ]; then pl="${SWI_HOME_DIR:-found}"; else pl="none"; fi printf 'secondo env: platform %s | swipl %s | jdk %s | bdb %s\n' \ "${SECONDO_PLATFORM:-?}" "$pl" "${J2SDK_ROOT:-MISSING}" "${BERKELEY_DB_DIR:-MISSING}" secondo_env_warnings } # The variables that make/runtime care about, in one place. -SECONDO_VARS='SECONDO_BUILD_DIR SECONDO_PLATFORM PL_VERSION SWI_HOME_DIR PL_LIB_DIR - PL_DLL_DIR PL_INCLUDE_DIR PL_LIB JPL_JAR JPL_DLL J2SDK_ROOT SECONDO_JAVA +SECONDO_VARS='SECONDO_BUILD_DIR SECONDO_PLATFORM SWI_HOME_DIR PL_LIB_DIR + PL_DLL_DIR PL_INCLUDE_DIR PL_LIB J2SDK_ROOT SECONDO_JAVA BERKELEY_DB_DIR BERKELEY_DB_LIB SECONDO_READLINE_DIR SECONDO_JPEG_DIR SECONDO_FLEX_DIR SECONDO_LIBXML2_DIR SECONDO_JVM_LIB_DIR SECONDO_CONFIG PD_HEADER PD_DVI_VIEWER PD_PS_VIEWER' diff --git a/ClientServer/SecondoInterfaceCS.cpp b/ClientServer/SecondoInterfaceCS.cpp index 89c5ebfdd6..95cf6cb459 100755 --- a/ClientServer/SecondoInterfaceCS.cpp +++ b/ClientServer/SecondoInterfaceCS.cpp @@ -55,6 +55,7 @@ provides functions useful for the client and for the server implementation. #include "CSProtocol.h" #include "StringUtils.h" #include "satof.h" +#include "SQLLanguage.h" using namespace std; @@ -90,6 +91,9 @@ SecondoInterfaceCS::SecondoInterfaceCS(bool isServer, /*= false*/ user = ""; pswd = ""; multiUser = false; + sqlPlanOnly = false; + sqlOptimizerAddressed = false; + resolvedCmdLevel = CMD_LEVEL_TEXT; traceSocketIn = 0; traceSocketOut = 0; } @@ -486,7 +490,7 @@ For an explanation of the error codes refer to SecondoInterface.h } else { switch (commandType) { - case 0: // list form + case CMD_LEVEL_NESTED_LIST: // list form { dwriter.write(debugSecondoMethod, cout, this, pid, "commandType = 0"); if ( commandAsText ) @@ -508,15 +512,29 @@ For an explanation of the error codes refer to SecondoInterface.h break; } - case 1: // text form + case CMD_LEVEL_TEXT: // text form { dwriter.write(debugSecondoMethod, cout, this, pid, "commandType 1"); cmdText = commandText; break; } + case CMD_LEVEL_SQL: // forwarded verbatim to the server's optimizer + { + dwriter.write(debugSecondoMethod, cout, this, pid, + "commandType 2 (sql)"); + cmdText = commandText; + break; + } + case CMD_LEVEL_AUTO: // the server classifies the command + { + dwriter.write(debugSecondoMethod, cout, this, pid, + "commandType auto"); + cmdText = commandText; + break; + } default: { - dwriter.write(debugSecondoMethod, cout, this, pid, + dwriter.write(debugSecondoMethod, cout, this, pid, "unknown commandType"); // Command type not implemented errorCode = ERR_CMD_LEVEL_NOT_YET_IMPL; @@ -552,6 +570,16 @@ For an explanation of the error codes refer to SecondoInterface.h return; } + // save/restore are carried out by the client -- it is the client that holds + // the file -- so they have to be recognized here even when the server was + // asked to classify the command (a negative level, see SQLLanguage.h). They + // are kernel commands in list or text syntax, never SQL, so deriving 0 vs 1 + // for them is the same "leading ( ?" test the server would apply and not a + // second copy of the language detection. + const int specialCmdLevel = (commandType < 0) + ? deriveKernelCommandLevel( cmdText ) + : commandType; + string::size_type posDatabase = cmdText.find( "database " ); string::size_type posSave = cmdText.find( "save " ); string::size_type posRestore = cmdText.find( "restore " ); @@ -560,12 +588,13 @@ For an explanation of the error codes refer to SecondoInterface.h dwriter.write(debugSecondoMethod, cout, this, pid, "try to find out kind of cmd"); - if ( posDatabase != string::npos && + if ( specialCmdLevel != CMD_LEVEL_SQL && + posDatabase != string::npos && posSave != string::npos && posTo != string::npos && posSave < posDatabase && posDatabase < posTo ) { - if ( commandType == 1 ) + if ( specialCmdLevel == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } @@ -639,7 +668,8 @@ For an explanation of the error codes refer to SecondoInterface.h errorCode = ERR_SYNTAX_ERROR; } } - else if ( posSave != string::npos && // save object to filename + else if ( specialCmdLevel != CMD_LEVEL_SQL && + posSave != string::npos && // save object to filename posTo != string::npos && posDatabase == string::npos && posSave < posTo ) @@ -647,7 +677,7 @@ For an explanation of the error codes refer to SecondoInterface.h dwriter.write(debugSecondoMethod, cout, this, pid, "check for save obj"); - if ( commandType == 1 ) + if ( specialCmdLevel == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } @@ -726,13 +756,14 @@ For an explanation of the error codes refer to SecondoInterface.h } } - else if ( posRestore != string::npos && + else if ( specialCmdLevel != CMD_LEVEL_SQL && + posRestore != string::npos && posDatabase == string::npos && posFrom != string::npos && posRestore < posFrom ) { dwriter.write(debugSecondoMethod, cout, this, pid, "check for restore db"); - if ( commandType == 1 ) + if ( specialCmdLevel == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } @@ -802,14 +833,15 @@ For an explanation of the error codes refer to SecondoInterface.h } } - else if ( posDatabase != string::npos && + else if ( specialCmdLevel != CMD_LEVEL_SQL && + posDatabase != string::npos && posRestore != string::npos && posFrom != string::npos && posRestore < posDatabase && posDatabase < posFrom ) { dwriter.write(debugSecondoMethod, cout, this, pid, "check for restore db"); - if ( commandType == 1 ) + if ( specialCmdLevel == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } @@ -890,14 +922,35 @@ For an explanation of the error codes refer to SecondoInterface.h " send command to server"); iosock << "" << endl; dwriter.write(debugSecondoMethod, cout, this, pid, " send "); - iosock << commandType << endl; + // The command level, optionally followed by per-command protocol flags. + // The server has always discarded the rest of this line, so a flag here + // is invisible to one that does not know it (and no flag at all is what + // every other client sends). + iosock << commandType << (sqlPlanOnly ? " planonly" : "") + << (sqlOptimizerAddressed ? " optimizer" : "") + << endl; dwriter.write(debugSecondoMethod, cout, this, pid, "CommandType send "); iosock << cmdText << endl; dwriter.write(debugSecondoMethod, cout, this, pid, "CommandText send "); iosock << "" << endl; - dwriter.write(debugSecondoMethod, cout, this, pid, + dwriter.write(debugSecondoMethod, cout, this, pid, "command transmitted completely, read response"); - + + // When the server was asked to classify the command it answers with + // the level it resolved to, ahead of everything else -- that is how the + // caller knows whether the result is an ordinary one, the SQL triple + // (plan result costs) or the text an optimizer directive printed. It is + // written only for a client that asked, so the protocol is unchanged + // for everyone sending an explicit level. + resolvedCmdLevel = commandType; + if ( commandType < 0 ) + { + string levelLine = ""; + getline( iosock, levelLine ); + dwriter.write(debugSecondoMethod, cout, this, pid, levelLine); + resolvedCmdLevel = parseCommandLevelEcho( levelLine ); + } + // Receive result errorCode = csp->ReadResponse( resultList, errorCode, errorPos, @@ -1240,6 +1293,110 @@ std::string SecondoInterfaceCS::getHome(){ return line; } +bool SecondoInterfaceCS::optimizerAvailable(){ + if(!server){ + return false; + } + iostream& iosock = server->GetSocketStream(); + iosock << "" << endl; + iosock.flush(); + string line; + getline(iosock,line); + stringutils::trim(line); + return line=="yes"; +} + +int SecondoInterfaceCS::parseCommandLevelEcho(const std::string& line){ + const string open = ""; + const string close = ""; + string l = line; + stringutils::trim(l); + if( l.size() <= open.size() + close.size() + || l.compare(0, open.size(), open) != 0 + || l.compare(l.size()-close.size(), close.size(), close) != 0){ + // Not the expected echo: the connection is out of step with the server. + return CMD_LEVEL_TEXT; + } + string digits = l.substr(open.size(), + l.size() - open.size() - close.size()); + bool correct = false; + int level = stringutils::str2int(digits, correct); + return correct ? level : CMD_LEVEL_TEXT; +} + +void SecondoInterfaceCS::SecondoAuto(const std::string& command, + const bool optimizerAddressed, + int& resolvedLevel, + ListExpr& resultList, + int& errorCode, + int& errorPos, + std::string& errorMessage){ + // Carry the flag through the one call that sends it, so it can never leak + // into an unrelated command. + ListExpr cmdList = nl->TheEmptyList(); + sqlOptimizerAddressed = optimizerAddressed; + Secondo( command, cmdList, CMD_LEVEL_AUTO, false, false, + resultList, errorCode, errorPos, errorMessage ); + sqlOptimizerAddressed = false; + resolvedLevel = resolvedCmdLevel; +} + +void SecondoInterfaceCS::SecondoSql(const std::string& sql, + const bool planOnly, + ListExpr& resultList, + int& errorCode, + int& errorPos, + std::string& errorMessage){ + // Carry the flag through the one call that sends it, so it can never leak + // into an unrelated command. + ListExpr cmdList = nl->TheEmptyList(); + sqlPlanOnly = planOnly; + Secondo( sql, cmdList, CMD_LEVEL_SQL, false, false, + resultList, errorCode, errorPos, errorMessage ); + sqlPlanOnly = false; +} + +std::string SecondoInterfaceCS::optimizerCommand(const std::string& directive){ + if(!server){ + return "Error: not connected to a server."; + } + iostream& iosock = server->GetSocketStream(); + iosock << "" << endl; + iosock << directive << endl; + iosock << "" << endl; + iosock.flush(); + + // Reply: a status line ("ok" / "ERR:") then a framed text block. + string status; + getline(iosock,status); + stringutils::trim(status); + + string line, output = ""; + getline(iosock,line); // opening + bool first = true; + while(getline(iosock,line)){ + if(line == ""){ + break; + } + // Preserve the directive's own layout (showOptions relies on leading + // whitespace), so do not trim the content lines. + if(!first){ + output += "\n"; + } + output += line; + first = false; + } + + if(status.compare(0,4,"ERR:")==0){ + // A failing directive may still have printed something useful; prefer it. + if(!output.empty()){ + return output; + } + return "Error: " + status.substr(4); + } + return output; +} + bool SecondoInterfaceCS::setHeartbeat(const int heart1, const int heart2){ iostream& iosock = server->GetSocketStream(); iosock << "" << endl; diff --git a/ClientServer/SecondoInterfaceREPLAY.cpp b/ClientServer/SecondoInterfaceREPLAY.cpp index 53c322e5ca..066737c179 100644 --- a/ClientServer/SecondoInterfaceREPLAY.cpp +++ b/ClientServer/SecondoInterfaceREPLAY.cpp @@ -39,6 +39,7 @@ February 2016 Matthias Kunsmann, ReplayVersion of the ~SecondoInterfaceCS~ #include "LogMsg.h" #include "SecondoInterfaceREPLAY.h" +#include "SQLLanguage.h" #include "SocketIO.h" #include "Profiles.h" #include "CSProtocol.h" @@ -2579,7 +2580,7 @@ transfer it to the node and restore (import) it bool SecondoInterfaceREPLAY::importAllImgOnNode(const unsigned int nodeNo, - std::vector imageList, + std::vector imageList, std::vector numberer, const string relName) { /* @@ -2970,7 +2971,7 @@ For an explanation of the error codes refer to SecondoInterface.h { switch (commandType) { - case 0: // list form + case CMD_LEVEL_NESTED_LIST: // list form { if ( commandAsText ) { @@ -2986,7 +2987,7 @@ For an explanation of the error codes refer to SecondoInterface.h } break; } - case 1: // text form + case CMD_LEVEL_TEXT: // text form { cmdText = commandText; break; @@ -3025,7 +3026,7 @@ For an explanation of the error codes refer to SecondoInterface.h posTo != string::npos && posSave < posDatabase && posDatabase < posTo ) { - if ( commandType == 1 ) + if ( commandType == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } @@ -3077,7 +3078,7 @@ For an explanation of the error codes refer to SecondoInterface.h posDatabase == string::npos && posSave < posTo ) { - if ( commandType == 1 ) + if ( commandType == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } @@ -3137,7 +3138,7 @@ For an explanation of the error codes refer to SecondoInterface.h posFrom != string::npos && posRestore < posFrom ) { - if ( commandType == 1 ) + if ( commandType == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } @@ -3195,7 +3196,7 @@ For an explanation of the error codes refer to SecondoInterface.h posFrom != string::npos && posRestore < posDatabase && posDatabase < posFrom ) { - if ( commandType == 1 ) + if ( commandType == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } diff --git a/ClientServer/SecondoMonitor.cpp b/ClientServer/SecondoMonitor.cpp index 743c7e53f5..0a0c368c04 100755 --- a/ClientServer/SecondoMonitor.cpp +++ b/ClientServer/SecondoMonitor.cpp @@ -643,6 +643,15 @@ int main( const int argc, const char* argv[] ) execute = true; autostartup = true; pos++; +#ifndef NO_OPTIMIZER + } else if (arg == "--no-optimizer") { + // Disable the server-side SQL optimizer for the servers this monitor + // forks. They read SECONDO_PARAM_EnableOptimizer (an env override of + // the config parameter Environment/EnableOptimizer) and inherit this + // monitor's environment. + setenv("SECONDO_PARAM_EnableOptimizer", "false", 1); + pos++; +#endif } else if (arg == "--help") { // list allowed arguments cout << "Usage: " << argv[0] @@ -650,6 +659,9 @@ int main( const int argc, const char* argv[] ) cout << "Options:" << endl; cout << " --help Display this information and exit" << endl; cout << " -s or --startup Run Startup command automatically" << endl; + #ifndef NO_OPTIMIZER + cout << " --no-optimizer Disable the server-side optimizer " << endl; + #endif cout << " -V or --version Display version information and exit" << endl << endl; cout << "The following parameters may be combined with \"-s\":" << endl; @@ -683,9 +695,19 @@ int main( const int argc, const char* argv[] ) } if(execute){ - SecondoMonitor* appPointer = new SecondoMonitor( argc, argv ); + // Strip monitor-only flags handled above (via the environment) from the + // argv before it reaches the configuration parser (TTYParameter), which + // would otherwise reject them as invalid parameters. + const char** monArgv = new const char*[argc]; + int monArgc = 0; + for (int i = 0; i < argc; i++) { + if (string(argv[i]) == "--no-optimizer") continue; + monArgv[monArgc++] = argv[i]; + } + SecondoMonitor* appPointer = new SecondoMonitor( monArgc, monArgv ); int rc = appPointer->Execute(autostartup); delete appPointer; + delete[] monArgv; return (rc); }else{ return 0; diff --git a/ClientServer/SecondoServer.cpp b/ClientServer/SecondoServer.cpp index 21a027208a..143b10b0fd 100755 --- a/ClientServer/SecondoServer.cpp +++ b/ClientServer/SecondoServer.cpp @@ -71,6 +71,12 @@ are implemented in class ~CSProtocol~ and can be used by inside the #include "CSProtocol.h" #include "NList.h" #include "satof.h" +#include "ErrorCodes.h" +#include "SQLLanguage.h" + +#ifndef NO_OPTIMIZER +#include "SecondoPL.h" +#endif using namespace std; @@ -144,24 +150,58 @@ class SecondoServer : public Application void CallGetCostFun(); void CallCancelQuery(); void CallHeartbeat(); - + void CallOptimizerAvailable(); + // Runs an optimizer control directive (e.g. showOptions, setOption(X), + // delOption(X), updateCatalog, resetKnowledgeDB) in the embedded optimizer + // and returns whatever the directive prints. Reached via the + // tag; the reply is a status line plus a framed text + // block. + void CallOptimizerCommand(); + private: + // Runs an SQL-dialect command (protocol command level 2): drives the + // embedded optimizer to obtain an executable plan and returns the list + // (plan result costs). With executePlan the plan is executed and its result + // returned; without it (the "planonly" protocol flag) the plan is only + // reported and result stays empty. Only reached when the optimizer is both + // compiled in and enabled for this server. + void CallSql(const string& sqlText, bool executePlan); + // Runs an optimizer control directive reached over the framing, + // i.e. one the server itself recognized while resolving CMD_LEVEL_AUTO. + // The text the directive prints is returned as a single text atom, so the + // answer fits the ordinary response shape. (The tag above + // is the other way in: it is what a client uses when it knows it wants a + // directive.) + void CallOptimizerDirective(const string& goal); + // True iff the optimizer is compiled in AND enabled for this server. + bool OptimizerAvailable(); +#ifndef NO_OPTIMIZER + // Bring the embedded optimizer up (lazily) and, if a database is open, make + // sure it tracks that database's schema. Shared by CallSql and + // CallOptimizerCommand. When requireDb is true (SQL: a plan needs a schema) a + // missing open database is an error; when false (global option directives + // such as showOptions/setOption) it is fine. Returns false with errMsg set + // when the optimizer cannot be made ready. + bool ensureOptimizerReady(string& errMsg, bool requireDb); +#endif + void CallRestore(const string& tag, bool database=false); void CallSave(const string& tag, bool database=false); string CreateTmpName(const string& prefix); bool WaitForRequest(); - + Socket* client; SecondoInterface* si; NestedList* nl; string parmFile; string dbDir; - string port; + string port; bool quit; string registrar; string user; string pswd; + bool sqlEnabled; CSProtocol* csp; }; @@ -197,7 +237,18 @@ SecondoServer::CallSecondo() int type=0; iosock >> type; debug_server(type); - csp->skipRestOfLine(); + // The remainder of the level line carries per-command protocol flags. It was + // always skipped, so a client that sends none (all of them until now) is + // unaffected, and an unknown flag is simply ignored rather than breaking the + // framing. Currently only "planonly" is defined: optimize the SQL but do not + // execute the plan. "optimizer" says the user addressed the optimizer + // explicitly (the "optimizer " prefix) and is only meaningful together with + // the auto level below. + string flags = ""; + getline( iosock, flags ); + debug_server(flags); + bool planOnly = flags.find("planonly") != string::npos; + bool optimizerAddressed = flags.find("optimizer") != string::npos; csp->IgnoreMsg(false); bool ready=false; do @@ -211,16 +262,296 @@ SecondoServer::CallSecondo() } } while (!ready && !iosock.fail()); + + // The auto level is a client asking the server which language the command is + // written in, instead of classifying it itself (see SQLLanguage.h). The + // level it resolves to is echoed back before anything else is written, so + // the client knows how to read the answer -- a level 2 answer is the list + // (plan result costs), a directive answer is the text the goal printed, and + // a level 0/1 answer is an ordinary result. The echo is written only for a + // client that asked, so clients sending an explicit level see the protocol + // exactly as before. + if ( type == CMD_LEVEL_AUTO ) + { + // With the "optimizer" flag the user addressed the optimizer explicitly + // ("optimizer "): SQL is then optimized but not executed, and + // anything else is a directive rather than a kernel command. + type = resolveCommandLevel( cmdText, optimizerAddressed ); + if ( optimizerAddressed && type == CMD_LEVEL_SQL ) + { + planOnly = true; + } + iosock << "" << type << "" << endl; + iosock.flush(); + } + + // Command level 2 is SQL: it is not an executable command, so it + // is not passed to si->Secondo but handled here by the embedded optimizer. + // The "planonly" flag stops it after optimizing (the client wants the plan, + // not its result). + if ( type == CMD_LEVEL_SQL ) + { + CallSql( cmdText, !planOnly ); + return; + } + + // An optimizer control goal. Only reachable through the auto level above: + // no client sends this level, the server resolves to it. + if ( type == CMD_LEVEL_OPT_DIRECTIVE ) + { + CallOptimizerDirective( cmdText ); + return; + } + ListExpr commandLE = nl->TheEmptyList(); ListExpr resultList = nl->TheEmptyList(); int errorCode=0, errorPos=0; string errorMessage=""; - si->Secondo( cmdText, commandLE, type, true, false, + si->Secondo( cmdText, commandLE, type, true, false, resultList, errorCode, errorPos, errorMessage ); NList::setNLRef(nl); WriteResponse( errorCode, errorPos, errorMessage, resultList ); } +bool +SecondoServer::OptimizerAvailable() +{ +#ifdef NO_OPTIMIZER + return false; +#else + return sqlEnabled; +#endif +} + +void +SecondoServer::CallSql(const string& sqlText, bool executePlan) +{ + if ( !OptimizerAvailable() ) + { + WriteResponse( ERR_OPTIMIZER_NOT_AVAILABLE, 0, + "The optimizer (SQL dialect) is not available on " + "this server.", nl->TheEmptyList() ); + return; + } + +#ifndef NO_OPTIMIZER + // Bring the optimizer up (sharing this server's interface for its secondo/2 + // catalog callbacks) and make sure it tracks the open database's schema. + { + string readyErr = ""; + if ( !ensureOptimizerReady( readyErr, true ) ) + { + NList::setNLRef(nl); + WriteResponse( ERR_OPTIMIZER_NOT_AVAILABLE, 0, readyErr, + nl->TheEmptyList() ); + return; + } + } + + // Trim a trailing newline accumulated by the framing loop. + string sql = sqlText; + while ( !sql.empty() + && (sql[sql.size()-1] == '\n' || sql[sql.size()-1] == '\r') ) + { + sql.erase(sql.size()-1); + } + + string plan, optErr; + double costs = 0.0; + bool alreadyExecuted = false; + bool ok = embeddedSqlToPlan( sql, plan, costs, optErr, alreadyExecuted ); + NList::setNLRef(nl); + if ( !ok ) + { + WriteResponse( ERR_OPTIMIZER_NOT_AVAILABLE, 0, + "Optimization failed: " + optErr, nl->TheEmptyList() ); + return; + } + + ListExpr commandLE = nl->TheEmptyList(); + ListExpr planResult = nl->TheEmptyList(); + int errorCode=0, errorPos=0; + string errorMessage=""; + if ( executePlan && !alreadyExecuted ) + { + // Execute the generated executable plan (text syntax). + si->Secondo( plan, commandLE, CMD_LEVEL_TEXT, true, false, + planResult, errorCode, errorPos, errorMessage ); + NList::setNLRef(nl); + } + // else: either the client asked for the plan only, or this was a create/drop + // the optimizer already carried out; "done" is returned as the plan. Either + // way the result stays empty. + // + // Note that "plan only" cannot suppress a create/drop: the optimizer's + // sqlToPlan executes those itself while translating, which is why the + // catalog refresh below is not conditional on executePlan. + + // DDL run through the optimizer (create table/index, drop, let X = select) + // changes the catalog the optimizer has cached; refresh it so later queries + // on this connection are optimized against the new schema. + if ( errorCode == 0 && embeddedOptimizerSqlChangesCatalog( sql ) ) + { + string refreshErr = ""; + embeddedOptimizerRefreshCatalog( refreshErr ); + NList::setNLRef(nl); + } + + // Return (plan result costs): the generated executable plan, the query + // result, and the optimizer's cost estimate for the plan. Callers that opted + // into the SQL level (command level 2) unwrap this shape; level-0/1 clients + // never receive it. Costs is appended rather than inserted so that the first + // two elements keep their meaning and a client that does not care about the + // estimate can ignore the tail. + ListExpr planText = nl->TextAtom(); + nl->AppendText( planText, plan ); + ListExpr resultList = nl->ThreeElemList( planText, planResult, + nl->RealAtom( costs ) ); + WriteResponse( errorCode, errorPos, errorMessage, resultList ); +#endif +} + +#ifndef NO_OPTIMIZER +bool +SecondoServer::ensureOptimizerReady(string& errMsg, bool requireDb) +{ + // Bring up the optimizer lazily, sharing this server's interface for its + // secondo/2 catalog callbacks (no second SMI environment). + if ( !initEmbeddedOptimizer( si ) ) + { + errMsg = "Could not initialize the optimizer."; + return false; + } + + // The optimizer needs the schema of the open database. It only learns it + // when the database is opened through its own logic, so make sure it is + // loaded (the client opened the database directly at the kernel). + if ( SecondoSystem::GetInstance()->IsDatabaseOpen() ) + { + string openDb = SecondoSystem::GetInstance()->GetDatabaseName(); + if ( !embeddedOptimizerUseDatabase( openDb ) ) + { + errMsg = "Could not load the database schema into the optimizer."; + return false; + } + } + else if ( requireDb ) + { + errMsg = "No database is open; cannot use the optimizer."; + return false; + } + return true; +} +#endif + +void +SecondoServer::CallOptimizerDirective(const string& goal) +{ + // Trim the trailing newline the framing loop accumulated; a Prolog goal must + // not carry it. + string directive = goal; + while ( !directive.empty() + && (directive[directive.size()-1] == '\n' + || directive[directive.size()-1] == '\r') ) + { + directive.erase(directive.size()-1); + } + + if ( !OptimizerAvailable() ) + { + WriteResponse( ERR_OPTIMIZER_NOT_AVAILABLE, 0, + "The optimizer is not available on this server.", + nl->TheEmptyList() ); + return; + } + +#ifndef NO_OPTIMIZER + // A directive is a global optimizer goal (showOptions, setOption, ...), so + // an open database is not required. + string errMsg = ""; + if ( !ensureOptimizerReady( errMsg, false ) ) + { + NList::setNLRef(nl); + WriteResponse( ERR_OPTIMIZER_NOT_AVAILABLE, 0, errMsg, + nl->TheEmptyList() ); + return; + } + + string output = ""; + bool ok = embeddedOptimizerRunGoal( directive, output, errMsg ); + NList::setNLRef(nl); + if ( !ok ) + { + // A directive may fail in Prolog yet still have written a useful message; + // prefer that over the bare exception text. + WriteResponse( ERR_OPTIMIZER_NOT_AVAILABLE, 0, + output.empty() ? errMsg : output, nl->TheEmptyList() ); + return; + } + + // What a directive produces is the text it printed, so that is its result. + ListExpr outText = nl->TextAtom(); + nl->AppendText( outText, output ); + WriteResponse( 0, 0, "", outText ); +#endif +} + +void +SecondoServer::CallOptimizerCommand() +{ + iostream& iosock = client->GetSocketStream(); + + // Read the directive text: lines up to the closing tag (framed like + // ). The opening tag was already consumed by the dispatcher. + string line = "", directive = ""; + bool ready = false; + do + { + getline( iosock, line ); + debug_server(line); + ready = (line == ""); + if ( !ready ) + { + if ( !directive.empty() ) + { + directive += "\n"; + } + directive += line; + } + } + while ( !ready && !iosock.fail() ); + + string status = "ok"; + string output = ""; +#ifdef NO_OPTIMIZER + status = "ERR:The optimizer is not available on this server."; +#else + string errMsg = ""; + if ( !OptimizerAvailable() ) + { + status = "ERR:The optimizer (SQL dialect) is not available on this server."; + } + else if ( !ensureOptimizerReady( errMsg, false ) ) + { + status = "ERR:" + errMsg; + } + else if ( !embeddedOptimizerRunGoal( directive, output, errMsg ) ) + { + // A directive may fail in Prolog yet still have written a useful message, + // so keep whatever it printed (output) and report the failure. + status = "ERR:" + errMsg; + } +#endif + + // Reply: a status line, then the captured (possibly multi-line) output framed + // so the client can read it back verbatim. + iosock << status << endl; + iosock << "" << endl; + iosock << output << endl; + iosock << "" << endl; + iosock.flush(); +} + void SecondoServer::CallNumericType() { @@ -775,7 +1106,7 @@ SecondoServer::CallSave(const string& tag, bool database /*=false*/) if (errorCode == ERR_NO_ERROR) { - si->Secondo( cmdText, commandLE, 0, true, false, + si->Secondo( cmdText, commandLE, CMD_LEVEL_NESTED_LIST, true, false, resultList, errorCode, errorPos, errorMessage ); NList::setNLRef(nl); @@ -845,7 +1176,7 @@ SecondoServer::CallRestore(const string& tag, bool database/*=false*/) " from " + serverFileName + ")"; } - si->Secondo( cmdText, commandLE, 0, true, false, + si->Secondo( cmdText, commandLE, CMD_LEVEL_NESTED_LIST, true, false, resultList, errorCode, errorPos, errorMessage ); NList::setNLRef(nl); } @@ -1002,6 +1333,12 @@ void SecondoServer::CallServerPid(){ iosock.flush(); } +void SecondoServer::CallOptimizerAvailable(){ + iostream& iosock = client->GetSocketStream(); + iosock << (OptimizerAvailable() ? "yes" : "no") << endl; + iosock.flush(); +} + void SecondoServer::CallRequestFile(){ initTransferFolders(); @@ -1118,6 +1455,16 @@ int SecondoServer::Execute() { si = new SecondoInterfaceTTY(true); + // Whether this server accepts the SQL dialect (command level 2) and drives + // the embedded optimizer. Controlled per server via the config the monitor + // hands us; defaults to enabled. Only effective if the optimizer is also + // compiled in (NO_OPTIMIZER not set). + string enableOpt = SmiProfile::GetParameter( "Environment", + "EnableOptimizer", "true", parmFile ); + stringutils::toLower( enableOpt ); + stringutils::trim( enableOpt ); + sqlEnabled = !(enableOpt == "false" || enableOpt == "no" || enableOpt == "0"); + cout << "Initialize the secondo interface " << endl; map commandTable; @@ -1152,7 +1499,11 @@ int SecondoServer::Execute() { commandTable[""] = &SecondoServer::CallCancelQuery; commandTable[""] = &SecondoServer::CallGetHome; commandTable[""] = &SecondoServer::CallHeartbeat; - + commandTable[""] = + &SecondoServer::CallOptimizerAvailable; + commandTable[""] = + &SecondoServer::CallOptimizerCommand; + string logMsgList = SmiProfile::GetParameter( "Environment", "RTFlags", "", parmFile ); RTFlag::initByString(logMsgList); diff --git a/ClientServer/TestClientServer b/ClientServer/TestClientServer index b849c294a6..0f4baa860f 100755 --- a/ClientServer/TestClientServer +++ b/ClientServer/TestClientServer @@ -8,10 +8,15 @@ # access, and the shutdown of that whole process tree. This test does, by # starting a real SecondoMonitor on a private port and driving N real clients # (SecondoCS, i.e. the SecondoInterfaceCS path the WebUI and the Java GUI use) -# against it concurrently. +# against it concurrently. Two client workloads run: executable plans, and -- +# when the server was built with the optimizer -- the SQL dialect, which each +# server optimizes in-process, so several embedded optimizers run at once. A +# serial phase then covers SQL that is *not* a query: the CREATE/DROP TABLE +# statements the optimizer executes itself, how a rejected query is reported, +# and the "planonly" protocol flag. # -# Modelled on Optimizer/TestOptServer, which is the other test here that starts -# a live monitor. +# Modelled on the former Optimizer/TestOptServer (the retired JPL optimizer +# server's test); this is now the test here that starts a live monitor. # # Assertions check the client's exit status *and* its log. Both are needed: the # exit status catches a failed command file (2) or a failed connect (1), while @@ -29,9 +34,9 @@ fi export SECONDO_CONFIG=${SECONDO_CONFIG:-$buildDir/bin/SecondoConfig.ini} export PATH="$buildDir/bin:$PATH" -# A private port keeps this off 1234, so it neither collides with a developer's -# running Secondo nor with Optimizer/TestOptServer. It also gives the registrar -# its own socket name (SmiProfile::GetUniqueSocketName keys on the port). +# A private port keeps this off 1234, so it does not collide with a developer's +# running Secondo. It also gives the registrar its own socket name +# (SmiProfile::GetUniqueSocketName keys on the port). SEC_PORT=${SECONDO_CS_TEST_PORT:-12234} DBNAME=cstest @@ -41,6 +46,14 @@ DBNAME=cstest # SECONDO_CS_TEST_CLIENTS=50 ./TestClientServer NCLIENTS=${SECONDO_CS_TEST_CLIENTS:-25} +# Concurrent clients for the SQL (optimizer) phase. Kept lower than NCLIENTS on +# purpose: each SQL client makes its server load an in-process SWI-Prolog and the +# optimizer, so this phase is far heavier (CPU and memory) than the plain-query +# phase above. The point is still concurrency -- N servers optimizing at once -- +# just bounded so it does not exhaust a CI runner. Override with +# SECONDO_CS_TEST_SQL_CLIENTS=25 ./TestClientServer +NSQLCLIENTS=${SECONDO_CS_TEST_SQL_CLIENTS:-10} + home=$(mktemp -d "${TMPDIR:-/tmp}/TestClientServer.XXXXXX") export SECONDO_PARAM_SecondoHome="$home" monPid="" @@ -235,7 +248,352 @@ else fi # -# Phase 3: graceful shutdown. Send the monitor a SIGTERM -- what a service +# Phase 4: concurrent SQL optimization. The clients above ran executable plans; +# here they send the SQL dialect (command level 2), which the server optimizes +# in-process before executing. Each connection forks its own server, so this +# runs N independent embedded optimizers against the one shared database at +# once -- the concurrency the embedded optimizer must survive. +# +# Skipped, not failed, when the server was built without the optimizer: level 2 +# then returns ERR_OPTIMIZER_NOT_AVAILABLE ("... not available on this server"). +# A serial probe decides which case we are in before the fan-out, so a genuine +# optimizer regression still fails rather than being mistaken for "not built". +# +echo "*** ClientServer test: SQL optimizer probe ***" +cat >"$home/sqlprobe.sec" <"$home/sqlprobe.log" 2>&1 +probeRc=$? + +# Set once the probe has shown the server really optimizes; the DDL phase below +# reuses it instead of probing again. +sqlEnabled=0 + +if grep -q "not available on this server" "$home/sqlprobe.log"; then + echo "SKIP: server has no optimizer (non-optimizer build); skipping SQL phase" +elif [ "$probeRc" -ne 0 ] \ + || ! grep -q "successfully processed" "$home/sqlprobe.log" \ + || ! grep -q "Optimized plan:" "$home/sqlprobe.log" \ + || ! grep -q "Elem : 10" "$home/sqlprobe.log"; then + # The optimizer should be here (no "not available" message) but the probe did + # not produce an optimized plan and its result -- a real regression. + echo "FAIL: SQL optimizer probe did not return an optimized result" + tail -30 "$home/sqlprobe.log" + rc=1 +else + sqlEnabled=1 + echo "*** ClientServer test: $NSQLCLIENTS parallel SQL (optimizer) clients ***" + declare -a spid src + for i in $(seq 1 "$NSQLCLIENTS"); do + cat >"$home/s$i.sec" <"$home/s$i.log" 2>&1 & + spid[$i]=$! + done + + for i in $(seq 1 "$NSQLCLIENTS"); do + wait "${spid[$i]}" 2>/dev/null + src[$i]=$? + done + + # As in the plain phase, assert on both exit status and log. "Optimized plan:" + # proves the server actually optimized the SQL (not just executed a plan the + # client sent), and "Elem : 10" proves that optimized plan then ran and + # returned the whole relation. + sqlFailed=0 + for i in $(seq 1 "$NSQLCLIENTS"); do + log="$home/s$i.log" + if [ "${src[$i]}" -ne 0 ]; then + echo "FAIL: SQL client $i exited with ${src[$i]}" + sqlFailed=$((sqlFailed + 1)) + elif ! grep -q "successfully processed" "$log" 2>/dev/null; then + echo "FAIL: SQL client $i did not complete its command file" + sqlFailed=$((sqlFailed + 1)) + elif grep -qE "SECONDO-000[0-9]|Error in Secondo|Errors during processing|not available on this server" "$log"; then + echo "FAIL: SQL client $i reported an error" + sqlFailed=$((sqlFailed + 1)) + elif ! grep -q "Optimized plan:" "$log"; then + echo "FAIL: SQL client $i did not receive an optimized plan" + sqlFailed=$((sqlFailed + 1)) + elif ! grep -q "Elem : 10" "$log"; then + echo "FAIL: SQL client $i did not return the expected query result" + sqlFailed=$((sqlFailed + 1)) + fi + done + + if [ "$sqlFailed" -gt 0 ]; then + echo "*** $sqlFailed/$NSQLCLIENTS SQL clients failed ***" + echo "=== first failing SQL client log ===" + for i in $(seq 1 "$NSQLCLIENTS"); do + if ! grep -q "Optimized plan:" "$home/s$i.log" 2>/dev/null; then + tail -30 "$home/s$i.log"; break + fi + done + echo "=== monitor log ===" + tail -30 "$home/monitor.log" + rc=1 + else + echo "OK: $NSQLCLIENTS/$NSQLCLIENTS SQL clients optimized and ran concurrently" + fi +fi + +# +# Phase 5: SQL DDL round-trip through the optimizer. Deliberately serial and a +# single client -- the concurrency this test exists for is covered by phase 4; +# what is new here is the *shape* of the commands. +# +# "create table" and "drop table" are not optimized into a plan: the optimizer +# carries them out itself and yields the sentinel "done" instead of a plan +# (sqlToPlan2, Optimizer/optimizerNewProperties.pl), which the client reports as +# "Executed by the optimizer (no plan to run)." Executing "done" as a query +# ("query done") was a real bug, so assert the sentinel is honoured. +# +# The "select count(*)" in between is the point of the phase: it can only be +# optimized if the optimizer re-read the catalog after the CREATE. The server +# caches the schema and returns early when the database is already loaded, so +# without the post-DDL refresh (embeddedOptimizerSqlChangesCatalog / +# embeddedOptimizerRefreshCatalog) the new table is invisible and the +# optimization fails. +# +if [ "$sqlEnabled" -eq 1 ]; then + echo "*** ClientServer test: SQL DDL round-trip (create/select/drop) ***" + cat >"$home/sqlddl.sec" <"$home/sqlddl.log" 2>&1 + ddlRc=$? + + ddlFailed=0 + if [ "$ddlRc" -ne 0 ]; then + echo "FAIL (ddl): client exited with $ddlRc" + ddlFailed=1 + elif ! grep -q "successfully processed" "$home/sqlddl.log"; then + echo "FAIL (ddl): client did not complete its command file" + ddlFailed=1 + elif grep -qE "SECONDO-000[0-9]|Error in Secondo|Errors during processing|not available on this server" "$home/sqlddl.log"; then + echo "FAIL (ddl): client reported an error" + ddlFailed=1 + elif [ "$(grep -c "Executed by the optimizer" "$home/sqlddl.log")" -ne 2 ]; then + # Once for CREATE TABLE, once for DROP TABLE. + echo "FAIL (ddl): CREATE/DROP were not reported as executed by the optimizer" + ddlFailed=1 + elif ! grep -qE "Optimized plan:.*Tmptab.*count" "$home/sqlddl.log"; then + # The plan must name the freshly created relation -- proof the optimizer's + # catalog picked the CREATE up. + echo "FAIL (ddl): SELECT on the new table was not optimized (stale catalog?)" + ddlFailed=1 + elif ! grep -qE "^[[:space:]]*0[[:space:]]*$" "$home/sqlddl.log"; then + # "count(*)" on the empty table must return 0, i.e. the plan really ran. + echo "FAIL (ddl): SELECT did not return the expected count" + ddlFailed=1 + fi + + if [ "$ddlFailed" -ne 0 ]; then + tail -40 "$home/sqlddl.log" + rc=1 + else + echo "OK (ddl): create table / select / drop table round-trip" + fi +fi + +# +# Phase 6: optimizer error reporting. A query the optimizer must reject has to +# come back as a readable sentence, not as the raw Prolog encoding. +# +# The optimizer reports failures as "::ERROR::" plus the message written back as +# a term (term_to_atom in sqlToPlan/3), i.e. quoted and escaped: +# +# '\n\nSQL ERROR (usually a user error): Unknown symbol: \'x\' is not ...' +# +# The server decodes that (prologQuotedToPlain, UserInterfaces/SecondoPL.cpp) so +# no client has to. Assert both halves: the sentence is there, and none of the +# encoding survived -- a regression would still "surface an error", just an +# unreadable one, which the presence check alone would not catch. +# +# Unlike the phases above this client is *expected* to fail its command file +# (the rejected query makes the TTY exit non-zero), so only the log is asserted. +# +if [ "$sqlEnabled" -eq 1 ]; then + echo "*** ClientServer test: optimizer error reporting ***" + cat >"$home/sqlerr.sec" <"$home/sqlerr.log" 2>&1 + + errFailed=0 + if ! grep -q "Optimization failed:" "$home/sqlerr.log"; then + echo "FAIL (error): the rejected query did not report an optimizer error" + errFailed=1 + elif ! grep -qF "SQL ERROR (usually a user error): Unknown symbol: 'nonexistingattr'" \ + "$home/sqlerr.log"; then + echo "FAIL (error): the optimizer error message is not the decoded text" + errFailed=1 + elif grep "Optimization failed:" "$home/sqlerr.log" | grep -qF '\n'; then + # A literal backslash-n means the term_to_atom encoding was passed through. + echo "FAIL (error): the optimizer error message is still Prolog-escaped" + errFailed=1 + fi + + if [ "$errFailed" -ne 0 ]; then + grep -n "Optimization failed:" "$home/sqlerr.log" | head -5 + tail -20 "$home/sqlerr.log" + rc=1 + else + echo "OK (error): optimizer error reported as plain text" + fi +fi + +# +# Phase 7: plan-only. "optimizer " sends the same SQL with the "planonly" +# protocol flag, so the server optimizes but does not execute. +# +# The oracle is the *same* query phase 4 runs: there it must produce "Elem : 10" +# (the last tuple of ten), here that output must be absent while the plan is +# still reported. A flag that silently did nothing would pass a plan check +# alone, so the negative assertion is the one that matters. +# +if [ "$sqlEnabled" -eq 1 ]; then + echo "*** ClientServer test: plan-only (optimizer prefix) ***" + cat >"$home/sqlplan.sec" <"$home/sqlplan.log" 2>&1 + planRc=$? + + planFailed=0 + if [ "$planRc" -ne 0 ]; then + echo "FAIL (planonly): client exited with $planRc" + planFailed=1 + elif ! grep -q "Optimized plan:" "$home/sqlplan.log"; then + echo "FAIL (planonly): no plan was reported" + planFailed=1 + elif ! grep -q "Plan only" "$home/sqlplan.log"; then + echo "FAIL (planonly): the plan was not reported as unexecuted" + planFailed=1 + elif grep -q "Elem : 10" "$home/sqlplan.log"; then + # The very output phase 4 requires -- here it means the plan ran anyway. + echo "FAIL (planonly): the plan was executed despite the planonly flag" + planFailed=1 + fi + + if [ "$planFailed" -ne 0 ]; then + tail -30 "$home/sqlplan.log" + rc=1 + else + echo "OK (planonly): plan reported, query not executed" + fi +fi + +# +# Phase 7b: language routing. The client no longer decides which of the three +# input languages a typed command is written in -- it sends the auto command +# level and the server answers with the level it resolved to (SQLLanguage.h). +# So the routing itself is now a server behaviour, and this is where it is +# pinned down. +# +# Everything below is typed the way a user types it, with no prefix and no +# level. Two of them are traps: "delete database X" and "drop database X" begin +# with words the optimizer also uses ("delete from ...", "drop table ..."), and +# a rule that looks only at the first word hands them to the optimizer -- the +# user then gets "no plan found" or "no database is open; cannot use the +# optimizer" instead of being told that a database is still open. +# +# The save/restore pair is the other thing worth guarding: those two are +# carried out by the *client* (it holds the file), so the client has to keep +# recognizing them even though it no longer classifies anything else. They run +# on a database of their own, so the shared test database survives. +# +if [ "$sqlEnabled" -eq 1 ]; then + echo "*** ClientServer test: language routing (server-side detection) ***" + cat >"$home/route.sec" <"$home/route.log" 2>&1 + + routeFailed=0 + if ! grep -qE "^10$" "$home/route.log"; then + echo "FAIL (routing): a plain kernel command did not return its result" + routeFailed=1 + elif ! grep -q "$(echo $DBNAME | tr a-z A-Z)" "$home/route.log"; then + echo "FAIL (routing): a nested list command did not list the databases" + routeFailed=1 + elif ! grep -q "Optimized plan:" "$home/route.log"; then + echo "FAIL (routing): SQL was not recognized without a prefix" + routeFailed=1 + elif ! grep -q "Elem : 10" "$home/route.log"; then + echo "FAIL (routing): the optimized plan did not run" + routeFailed=1 + elif ! grep -q "Optimizer options (and sub-options):" "$home/route.log"; then + echo "FAIL (routing): a bare optimizer directive did not reach the optimizer" + routeFailed=1 + elif ! grep -q "A database is open." "$home/route.log"; then + echo "FAIL (routing): 'delete database' did not reach the kernel" + routeFailed=1 + elif grep -qE "cannot use the optimizer|Optimization failed" "$home/route.log"; then + echo "FAIL (routing): a kernel command was routed to the optimizer" + routeFailed=1 + elif [ ! -f "$home/csdump" ]; then + # The client writes this file itself; if it were sent to the server as an + # ordinary command instead, no file would appear here. + echo "FAIL (routing): 'save database' did not transfer the dump to the client" + routeFailed=1 + elif [ "$(grep -cE "^10$" "$home/route.log")" -lt 2 ]; then + echo "FAIL (routing): the restored database did not answer the query" + routeFailed=1 + fi + + if [ "$routeFailed" -ne 0 ]; then + grep -nE "cannot use the optimizer|Optimization failed|Error" \ + "$home/route.log" | head -5 + tail -30 "$home/route.log" + rc=1 + else + echo "OK (routing): each language reached the right interpreter" + fi +fi + +# +# Phase 8: graceful shutdown. Send the monitor a SIGTERM -- what a service # manager or a CTRL+C does -- and assert the whole tree comes down cleanly: # * the monitor exits rather than hanging (it used to deadlock in BerkeleyDB # teardown run from its signal handler, roughly two shutdowns in three), @@ -278,7 +636,7 @@ else fi # -# Phase 4: hard kill. A kill -9 of the monitor never runs Terminate(), so the +# Phase 9: hard kill. A kill -9 of the monitor never runs Terminate(), so the # only thing that can bring its children down is PR_SET_PDEATHSIG, armed in each # child at spawn. Start a fresh monitor -- no clients needed, the registrar, # checkpoint and listener are what must not be orphaned -- SIGKILL it, and diff --git a/Documents/SecondoVM-FAQ.txt b/Documents/SecondoVM-FAQ.txt deleted file mode 100644 index b13b58914d..0000000000 --- a/Documents/SecondoVM-FAQ.txt +++ /dev/null @@ -1,121 +0,0 @@ -=================== -== SecondoVM FAQ == -=================== - -What is SecondoVM? -------------------------- - -SecondoVM is a Linux-based installation of the Secondo -extensible DBMS on a virtual machine. It is distributed as a -zip-archive file. A user just needs to install VMware Player, -a virtualization software, in order to play the virtual machine. - -VMware Player is available from the VMware website -(http://info.vmware.com/). It is available for Linux, -Windows and Mac platforms. For non-commercial use, Licences -are free of charge. - -The SecondoVM appliance was set up using the 32bit variant of -Xubuntu (relying on Ubuntu 10.04 LTS) as a base. When starting -the virtual machine, VMware will set up a virtual network, -acting as a NAT-bridge between the virtual, and your machine's -physical network. This allows for full communications with the -system running on the virtual machine. Hence, you can use -secure shell (ssh) to communicate with the virtual machine. -Also, VMware tools can be used to share folders between the -host and guest system. - -Setting up the virtual machine does not require any difficult -or time-intensive installation process. - -How to install SecondoVM? --------------------------------- - (1) Install VMware Player on your computer. - (2) Download the most recent SecondoVM - distribution from the Secondo website - (http://dna.fernuni-hagen.de/secondo). - (We recommend to verify a correct download by comparing the MD5-checksum of - the downloaded archive file with the provided MD5-value from the web site). - (3) Unzip the downloaded archive file. - (4) Run the VMplayer application. - (5) Load the Virtual Machine "Ubuntu_32bit.vmx" - (6) Change the virtual machine's settings according to your - requirements (increasing maximum memory size or cpu number - to be assigned to the virtual machine). - (7) Start the virtual machine. - -After starting the virtual machine, the system will automatically -log you on as the predefined user "secondo" (password: secondo). -User "secondo" has administrative rights and may use the "sudo" -command to run administrative tasks. - -If you notice problems with the keyboard key mappings, you may use the -keyboard-mapping tool from the application launcher bar to adopt to your -keyboard. If this does not help, please consult the internet to find a -solution appropriate to your setting. - - -How do I get rid of it? ------------------------ - (1) Terminate the virtual machine (if running). - (2) Delete the files unpacked from the downloaded archive file. - - -How to run Secondo with a command line? ---------------------------------------- - (1) Open a bash shell. (There should be a Shell icon on your desktop.) - (2) Change to directory /home/secondo/secondo/bin - (3) Execute the following command: secinit - (4) Execute the following command: SecondoTTYBDB - - -How to run Secondo with a GUI? ------------------------------- -(I) In order to run Secondo with a GUI, you first - need to run a Secondo Server: - (1) Open a bash shell. - (2) Change to directory /home/secondo/secondo/bin - (3) Execute the following command: secinit - (4) Execute the folling command: SecondoMonitor -s - -(II) If you want to use the query optimizer, you - need to start the optimizer server: - (1) Open a bash shell. - (2) Change to directory /home/secondo/secondo/Optimizer - (3) Execute the following command: secinit - (4) Execute the following command: StartOptServer - -(III) Then, run the Java-based GUI: - (1) Open a bash shell. - (2) Change to directory /home/secondo/secondo/Javagui - (3) Execute the following command: secinit - (4) Execute the following command: sgui - (5) The Java-based GUI starts up. - Confirm the dialog. The GUI will auto-connect - with a database server and the OptimizerServer. - - -How to update Secondo? ----------------------- - (1) Open a web browser and open the Secondo homepage - (http://dna.fernuni-hagen.de/secondo) - (2) Download the latest Secondo for Linux release. - (3) Unpack the downloaded archive file and - overwrite the contents of folder - /home/secondo/secondo and all its subfolders - with the archive's contents. - (4) Rebuild Secondo (see below). - - -How to (re-)build Secondo? --------------------------- - (1) Open a bash shell. - (2) Change to directory /home/secondo/secondo - (3) Execute the following command: secinit - (4) Execute the following command: make clean; make - -More Information ----------------- -The Secondo Manual and Programmer's Guides are located on your Desktop. -You can also consult the Secondo homepage to download recent versions, demos etc. - diff --git a/Javagui/JDBC/communication/CommunicationInterface.java b/Javagui/JDBC/communication/CommunicationInterface.java index 30de6b061a..db460afd55 100644 --- a/Javagui/JDBC/communication/CommunicationInterface.java +++ b/Javagui/JDBC/communication/CommunicationInterface.java @@ -1,11 +1,10 @@ package communication; -import communication.optimizer.OptimizerInterface; -import communication.optimizer.IntObj; import java.sql.SQLException; import tools.Reporter; //import Verbindungstest.Declarations; import sj.lang.ESInterface; +import sj.lang.SecondoInterface; import sj.lang.ListExpr; import sj.lang.IntByReference; /** @@ -18,7 +17,6 @@ public class CommunicationInterface { private final String AlterTempTabName = "typeTesttmp"; //AlterTabTmp - private OptimizerInterface OI; private ESInterface SI; private ListExpr LEresult; private IntByReference ErrCode; @@ -26,7 +24,6 @@ public class CommunicationInterface { private StringBuffer ErrMess; private boolean connectedToDB; private String connectedDB; - private IntObj OptIO; //needed for the Optimizer, it contains the errorcode private int SecPort; private int OptPort; @@ -40,9 +37,7 @@ public CommunicationInterface() { ErrMess = new StringBuffer(); LEresult = new ListExpr(); - OI = new OptimizerInterface(); SI = new ESInterface(); - OptIO = new IntObj(); connectedToDB = false; } @@ -50,7 +45,9 @@ public CommunicationInterface() { /** * Task of this method
- * initializes connection to Secondo server and Secondo optimizer + * initializes the connection to the Secondo server. The optimizer runs + * inside that server, so there is no second connection to open; OPort is + * kept for the sake of existing jdbc:secondo:// URLs and is not used. * @return true if connection has been established */ public boolean initialize(String HName, int SPort, int OPort) { @@ -68,12 +65,8 @@ public boolean initialize(String HName, int SPort, int OPort) { else Reporter.writeError("ERROR: Connection to Secondo server could not be established"); - OI.setHost(HostName); - OI.setPort(OptPort); - if (OI.connect()) - Reporter.writeInfo("Connected to Secondo optimizer"); - else { - Reporter.writeError("ERROR: Connection to Secondo optimizer could not be established"); + if (IstOk && !SI.optimizerAvailable()) { + Reporter.writeError("ERROR: the Secondo server provides no optimizer"); IstOk = false; } return IstOk; @@ -120,12 +113,11 @@ public boolean isConnected() { /** * Task of this method
- * The connection to the Optimizer Server and to the Secondo Server is terminated
+ * The connection to the Secondo Server is terminated
* It reports an error if the connection has not been established */ public void closeDB() { if (connectedToDB) { - OI.disconnect(); SI.terminate(); connectedToDB = false; connectedDB = ""; @@ -175,54 +167,81 @@ public ListExpr getResult() { */ public boolean executeCommand(String command) { boolean IstOk = false; - boolean IsUpdate = false; - boolean AlterTCommand = false; - String result; - /* IsUpdate is always false. If changed to true it is expected - * than a sql mquerie command is given. In this case the command - * would be processed by the Optimizer directly - * if (command.startsWith("select")) - IsUpdate = false; - else - IsUpdate = true; */ LEresult = new ListExpr(); // after executeCommand has been invoked for the second time // it still has the result from the first call. Therfore it is // reinitialized here if(command.startsWith("altertable")) { - AlterTCommand = true; - result = this.getAlterCommands(command); - } - else - result = OI.optimize_execute(command, connectedDB, OptIO, IsUpdate); - - if (result.startsWith("::ERROR")) - Reporter.writeError(result); - else if (result.equals("done")) - // DDL-Command like CREATE TABLE - IstOk = true; - else { - if (!AlterTCommand) - result="query "+result; + // ALTER TABLE is rewritten into a sequence of kernel commands + String result = this.getAlterCommands(command); + if (result == null) + return false; SI.secondo(result, LEresult, ErrCode, ErrPos, ErrMess); - if (ErrCode.value == 0) { - if (AlterTCommand) { - SI.secondo(AlterCommand2, LEresult, ErrCode, ErrPos, ErrMess); - SI.secondo(AlterCommand3, LEresult, ErrCode, ErrPos, ErrMess); - SI.secondo(AlterCommand4, LEresult, ErrCode, ErrPos, ErrMess); - //OI.optimize_execute("updateCatalog", connectedDB, OptIO, true); - } - IstOk = true; //query was successful - Reporter.reportInfo(LEresult.toString(), true); - } - else + if (ErrCode.value != 0) { Reporter.writeError(ErrMess.toString()); + return false; + } + SI.secondo(AlterCommand2, LEresult, ErrCode, ErrPos, ErrMess); + SI.secondo(AlterCommand3, LEresult, ErrCode, ErrPos, ErrMess); + SI.secondo(AlterCommand4, LEresult, ErrCode, ErrPos, ErrMess); + Reporter.reportInfo(LEresult.toString(), true); + return true; } + // SQL: the server optimizes the command and runs the plan in one step + ListExpr answer = sqlCommand(command, false); + if (answer == null) + return false; + if (planOf(answer).equals("done")) + // DDL-Command like CREATE TABLE: the optimizer carried it out + // itself while translating, so there is no plan to run + return true; + LEresult = answer.second(); + Reporter.reportInfo(LEresult.toString(), true); + IstOk = true; + return IstOk; } + /** + * Task of this method
+ * Sends an SQL command to the Secondo server, which optimizes it itself + * and answers with the list (plan result costs). + * @param command the command in SQL + * @param planOnly if true the server stops after optimizing and executes + * nothing, so only the plan and its costs come back + * @return the answer list, or null if the command could not be optimized + */ + private ListExpr sqlCommand(String command, boolean planOnly) { + ListExpr answer = new ListExpr(); + SI.secondo(command, answer, ErrCode, ErrPos, ErrMess, + SecondoInterface.SQL_COMMAND_LEVEL, planOnly); + if (ErrCode.value != 0) { + Reporter.writeError(ErrMess.toString()); + return null; + } + if (answer.listLength() < 2) { + Reporter.writeError("unexpected answer from the optimizer: " + answer.toString()); + return null; + } + return answer; + } + + /** + * Task of this method
+ * Returns the generated plan of an answer of sqlCommand. Note that this is + * a ready to run command, not a bare plan expression: the server already + * wrapped it into "query ..." resp. "let X = ...". + * @param answer an answer list of sqlCommand + * @return the plan text + */ + private String planOf(ListExpr answer) { + ListExpr plan = answer.first(); + return plan.atomType() == ListExpr.TEXT_ATOM ? plan.textValue().trim() + : plan.toString().trim(); + } + public void executeSettings(boolean UseSubqueries) { String Ausgabe=""; @@ -233,18 +252,11 @@ public void executeSettings(boolean UseSubqueries) { else command = "delOption(subqueries)"; - Ausgabe = OI.optimize_execute(command, connectedDB, OptIO, true); + Ausgabe = SI.optimizerCommand(command); + if (Ausgabe == null) + Reporter.writeError("ERROR: " + command + " failed"); } - /*test - public void executeSettings1(String command) { - - String Ausgabe=""; - - - Ausgabe = OI.optimize_execute(command, connectedDB, OptIO, true); - }*/ - public void executeSecSettings(String statm) { LEresult = new ListExpr(); @@ -294,9 +306,18 @@ private String getAlterCommands(String OrgCommand) { colName = commandTemp.substring(pos1 + 1); PreCommand = "select " + colName + " from " + tabName; - PreResult = OI.optimize_execute(PreCommand, connectedDB, OptIO, false); + // only the plan is wanted here (it carries the attribute name with + // its real spelling), so ask the server not to run the query + ListExpr PreAnswer = sqlCommand(PreCommand, true); + if (PreAnswer == null) + return null; + PreResult = planOf(PreAnswer); pos1 = PreResult.indexOf('['); pos2 = PreResult.indexOf(']'); + if (pos1 < 0 || pos2 < pos1) { + Reporter.writeError("cannot read the attribute name from the plan: " + PreResult); + return null; + } colName = PreResult.substring(pos1+1, pos2); } diff --git a/Javagui/communication/makefile b/Javagui/communication/makefile deleted file mode 100755 index f8e3ab376d..0000000000 --- a/Javagui/communication/makefile +++ /dev/null @@ -1,35 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# filename communication/makefile -# -# last change 10-2003; Thomas Behr - -include ../makefile.inc - -.PHONY: all -all: - $(MAKE) -C optimizer all - - -.PHONY: clean -clean: - $(MAKE) -C optimizer clean - - diff --git a/Javagui/communication/optimizer/ErrorCodes.java b/Javagui/communication/optimizer/ErrorCodes.java deleted file mode 100755 index f5eff837bc..0000000000 --- a/Javagui/communication/optimizer/ErrorCodes.java +++ /dev/null @@ -1,61 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package communication.optimizer; - -public class ErrorCodes{ - -public static final int NO_ERROR=0; -public static final int NO_OPTIMIZER=1; -public static final int UNKNOW_HOST=2; -public static final int IO_ERROR=3; -public static final int SECURITY_ERROR=4; -public static final int NOT_CONNECTED =5; -public static final int PROTOCOL_ERROR = 6; -public static final int OPTIMIZATION_FAILED = 7; -public static final int NO_OPTIMIZATION_POSSIBLE = 8; -public static final int CONNECTION_BROKEN = 9; - - -public static String getErrorMessage(int ErrorCode){ - - switch(ErrorCode){ - case NO_ERROR : return "no error"; - case NO_OPTIMIZER : return "server is not an optimizer"; - case UNKNOW_HOST : return "host-name unknown"; - case IO_ERROR : return "io-error"; - case SECURITY_ERROR : return "security error"; - case NOT_CONNECTED : return "not connected"; - case PROTOCOL_ERROR : return "protocol error"; - case OPTIMIZATION_FAILED : return "optimization failed"; - case NO_OPTIMIZATION_POSSIBLE : return "no optimization possible"; - case CONNECTION_BROKEN : return "connection to server lost"; - default : return "unknow error-code"; - } - - - -} - - - - - - -} diff --git a/Javagui/communication/optimizer/IntObj.java b/Javagui/communication/optimizer/IntObj.java deleted file mode 100755 index 88c39d39dc..0000000000 --- a/Javagui/communication/optimizer/IntObj.java +++ /dev/null @@ -1,24 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package communication.optimizer; - -public class IntObj{ - public int value; -} diff --git a/Javagui/communication/optimizer/OptimizerInterface.java b/Javagui/communication/optimizer/OptimizerInterface.java deleted file mode 100755 index b0dba4f620..0000000000 --- a/Javagui/communication/optimizer/OptimizerInterface.java +++ /dev/null @@ -1,251 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package communication.optimizer; - -import java.io.*; -import java.net.*; - - -/* this class provides a interface for communication with a - * optimizer server. - */ -public class OptimizerInterface{ - -/** sets the Hostname of the optimizer server */ -public void setHost(String HostName){ - if(HostName!=null){ - if(!HostName.equals(this.HostName)) - ServerChanged=true; - this.HostName = HostName; - } -} - -/** sets the port no of the optimizer server */ -public void setPort(int Port){ - if(Port>=0){ - if(Port!=PortNr) - ServerChanged=true; - PortNr = Port; - } -} - -/** return the host-name of the optimizer server */ -public String getHost(){ - return HostName; -} - -/** returns the port no of the optimizer server */ -public int getPort(){ - return PortNr; -} - -/** connect this interface with the optimizerServer - * returns true if successful, false otherwise - */ -public boolean connect(){ - if(isConnected() & !ServerChanged) // connection exists - return true; - if(isConnected() & ServerChanged) // close existing connection - disconnect(); - try{ - ClientSocket = new Socket(HostName,PortNr); - try{ - in = new BufferedReader(new InputStreamReader(ClientSocket.getInputStream(),"UTF-8")); - } catch (UnsupportedEncodingException e){ - System.err.println("Internal error, UTF-8 not supported"); - in = new BufferedReader(new InputStreamReader(ClientSocket.getInputStream())); - } - try{ - out = new BufferedWriter(new OutputStreamWriter(ClientSocket.getOutputStream(),"UTF-8")); - } catch (UnsupportedEncodingException e){ - System.err.println("Internal error, UTF-8 not supported"); - out = new BufferedWriter(new OutputStreamWriter(ClientSocket.getOutputStream())); - } - sendLine(""); - out.flush(); - String answer = in.readLine(); - if(answer==null){ // Server is down - disconnect(); - LastError = ErrorCodes.CONNECTION_BROKEN; - return false; - } - - if(answer.equals("")){ // found an optimizer - LastError = ErrorCodes.NO_ERROR; - return true; - } - else{ - disconnect(); - LastError=ErrorCodes.NO_OPTIMIZER; - return false; - } - - } - catch(UnknownHostException UHE){ - LastError = ErrorCodes.UNKNOW_HOST; - ClientSocket = null; - return false; - } - catch(IOException IOE){ - LastError = ErrorCodes.IO_ERROR; - ClientSocket = null; - return false; - } - catch(SecurityException SE){ - LastError = ErrorCodes.SECURITY_ERROR; - ClientSocket = null; - return false; - } - -} - -public boolean isConnected(){ - if(ClientSocket==null) - return false; - return ClientSocket.isConnected(); -} - - -public int getLastError(){ - return LastError; -} - - - - -public void disconnect(){ - if(ClientSocket!=null){ - try{ - sendLine(""); - out.flush(); - }catch(Exception e){ - System.err.println("error in sending end-message to optimizer-server"); - } - finally{ - try{ - ClientSocket.close(); - } - catch(Exception e2){ - System.err.println("error in closing connection to optimizer-server"); - } - } - } - ClientSocket = null; - in = null; - out = null; - LastError = ErrorCodes.NO_ERROR; -} - - -public String optimize_execute(String query, String Database, IntObj ErrorCode, boolean executeFlag){ - query = query.trim(); - String QUERY = query.toUpperCase(); -// if(!QUERY.startsWith("SQL") && !QUERY.startsWith("SELECT") && ! executeFlag){ -// ErrorCode.value = ErrorCodes.NO_OPTIMIZATION_POSSIBLE; -// return query; -// } - - try{ - if(executeFlag) - sendLine(""); - else - sendLine(""); - sendLine(""); - sendLine(Database); - sendLine(""); - sendLine(""); - sendLine(query); - sendLine(""); - if(executeFlag) - sendLine(""); - else - sendLine(""); - out.flush(); - String answer = in.readLine(); - if(answer==null){ // Server is down - disconnect(); - LastError = ErrorCodes.CONNECTION_BROKEN; - return ""; - } - if(!answer.equals("")){ - ErrorCode.value=ErrorCodes.PROTOCOL_ERROR; - disconnect(); - return ""; - } - String Line = in.readLine(); - if(Line==null){ // Server is down - disconnect(); - LastError = ErrorCodes.CONNECTION_BROKEN; - return ""; - } - StringBuffer result = new StringBuffer(); - while(!Line.equals("")){ - if(executeFlag) - result.append(Line+"\n"); - else - result.append(Line); - Line = in.readLine(); - if(Line==null){ // Server is down - LastError = ErrorCodes.CONNECTION_BROKEN; - disconnect(); - return ""; - } - } - ErrorCode.value = ErrorCodes.NO_ERROR; - String Opt = result.toString(); - if(Opt.equals("")){ - ErrorCode.value = ErrorCodes.OPTIMIZATION_FAILED; - return ""; - } - return removeSpecialSymbols(Opt); - }catch(IOException IOE){ - ErrorCode.value = ErrorCodes.IO_ERROR; - disconnect(); - return ""; - } -} - -private String removeSpecialSymbols(String p){ - p = p.replaceAll("\\\\n","\n"); - p = p.replaceAll("\\\\t","\t"); - p = p.replaceAll("\\\\'","'"); - return p; -} - - - - - -private void sendLine(String Line) throws IOException{ - Line +="\n"; - int len = Line.length(); - out.write(Line,0,len); -} - - -private String HostName="localhost"; -private int PortNr=1235; -private boolean ServerChanged=true; -private Socket ClientSocket; -private BufferedReader in; -private BufferedWriter out; -private int LastError = ErrorCodes.NO_ERROR; - -} diff --git a/Javagui/communication/optimizer/OptimizerSettingsDialog.java b/Javagui/communication/optimizer/OptimizerSettingsDialog.java deleted file mode 100755 index 313c5f78ec..0000000000 --- a/Javagui/communication/optimizer/OptimizerSettingsDialog.java +++ /dev/null @@ -1,139 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package communication.optimizer; - -import sj.lang.*; -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; - -public class OptimizerSettingsDialog extends JDialog{ - - -/** creates a new Dialog */ -public OptimizerSettingsDialog(JFrame parent){ - super(parent,true); - setSize(400,400); - setTitle("Optimizer-Settings"); - getContentPane().setLayout(new BorderLayout()); - JPanel ControlPanel = new JPanel(); - ControlPanel.add(OKBtn); - ControlPanel.add(CANCELBtn); - ActionListener BtnListener = new ActionListener(){ - public void actionPerformed(ActionEvent evt){ - Object source = evt.getSource(); - if(source.equals(OKBtn)){ - accept(); - } - if(source.equals(CANCELBtn)){ - abort(); - } - } - }; - OKBtn.addActionListener(BtnListener); - CANCELBtn.addActionListener(BtnListener); - getContentPane().add(ControlPanel,BorderLayout.SOUTH); - JPanel InputPanel = new JPanel(new GridLayout(4,4)); - InputPanel.add(new JLabel("Host")); - InputPanel.add(HostName); - InputPanel.add(new JLabel("Port")); - InputPanel.add(PortNumber); - JPanel P3 = new JPanel(); - P3.add(InputPanel); - getContentPane().add(P3); - Host="localhost"; - Port=1235; -} - - -/** accept the changes */ -private void accept(){ - String H = HostName.getText().trim(); - if(H.equals("")){ - JOptionPane.showMessageDialog(null,"the hostname must not be empty","Error",JOptionPane.ERROR_MESSAGE ); - return; - } - try{ - int P = Integer.parseInt(PortNumber.getText()); - if(P<=0){ - JOptionPane.showMessageDialog(null,"the portnumber must be greater then zero","Error",JOptionPane.ERROR_MESSAGE ); - return; - } - Host = H; - Port = P; - accepted = true; - setVisible(false); - }catch(Exception e){ - JOptionPane.showMessageDialog(null,"the portnumber is not a valid integer","Error",JOptionPane.ERROR_MESSAGE ); - return; - } -} - - -/** gets the changes back */ -private void abort(){ - HostName.setText(Host); - PortNumber.setText(""+Port); - accepted=false; - setVisible(false); -} - - -/** makes this dialog visible - * if the OK button is pressed true is returned - * otherwise the result will be false - */ -public boolean showDialog(){ - accepted = false; - PortNumber.setText(""+Port); - HostName.setText(Host); - setVisible(true); - return accepted; -} - - -/** returns the current HostName */ -public String getHost(){ - return Host; -} - - -/** returns the current PortNumber */ -public int getPort(){ - return Port; -} - - -/** sets the values in this dialog */ -public void setConnection(String Host, int Port){ - this.Host = Host; - this.Port = Port; -} - -private JButton OKBtn= new JButton("Ok"); -private JButton CANCELBtn = new JButton("Cancel"); -private JTextField HostName = new JTextField(20); -private JTextField PortNumber = new JTextField(5); -private String Host; -private int Port; -private boolean accepted; - - -} diff --git a/Javagui/communication/optimizer/makefile b/Javagui/communication/optimizer/makefile deleted file mode 100755 index 968cf4f842..0000000000 --- a/Javagui/communication/optimizer/makefile +++ /dev/null @@ -1,38 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# file: communication/optimizer/makefile -# -# last change: 10-2003; Thomas Behr - -include ../../makefile.inc - - -JAVAFILES =$(shell find . -name "*.java") - -.PHONY: all -all: $(JAVA_STAMP) - -$(JAVA_STAMP): $(JAVAFILES) - $(compile-java) - - -.PHONY: clean -clean: - rm -f *.class $(JAVA_STAMP) diff --git a/Javagui/gui.cfg.example b/Javagui/gui.cfg.example index da82c85a97..83067f6c6f 100755 --- a/Javagui/gui.cfg.example +++ b/Javagui/gui.cfg.example @@ -79,13 +79,7 @@ USE_BINARY_LISTS true # ensure to have the value used in SECONDO MAX_STRING_LENGTH 48 -#the host-name of an optimizer-server -OPTIMIZER_HOST localhost - -#the port-number of an optimizer-server -OPTIMIZER_PORT 1235 - -#enable optimizer at start (true or false) +#enable the optimizer at start (true or false) ENABLE_OPTIMIZER true #adds the entropy items to the main menu diff --git a/Javagui/gui/CommandPanel.java b/Javagui/gui/CommandPanel.java index 2170defc29..1cff6f22bc 100755 --- a/Javagui/gui/CommandPanel.java +++ b/Javagui/gui/CommandPanel.java @@ -26,7 +26,6 @@ import javax.swing.event.*; import java.util.*; import sj.lang.*; -import communication.optimizer.*; import tools.Reporter; import java.io.File; import mmdb.MMDBUserInterfaceController; @@ -57,8 +56,14 @@ public class CommandPanel extends JScrollPane { private ReturnKeyAdapter ReturnKeyListener; private Vector ChangeListeners = new Vector(3); private String OpenedDatabase = ""; - private OptimizerInterface OptInt = new OptimizerInterface(); - private OptimizerSettingsDialog OptSet = new OptimizerSettingsDialog(null); + // The optimizer runs inside the connected Secondo server, so two things + // have to be true for it to be usable: the user asked for it + // (optimizerWanted, from the configuration file or the Optimizer menu) and + // the server we are currently connected to actually has one + // (optimizerEnabled, established by probing that server). The wish outlives + // a connection, the answer does not -- see connect(). + private boolean optimizerWanted = false; + private boolean optimizerEnabled = false; private Object SyncObj = new Object(); private boolean ignoreCaretUpdate=false; private boolean autoUpdateCatalog = true; @@ -104,18 +109,11 @@ public CommandPanel (ResultProcessor aRV,String user, String passwd) { public void databasesChanged(){} // deleted or created or updated object public void objectsChanged(){ - if(sendToOptimizer("updateCatalog")==null){ - Reporter.writeError("updateCatalog failed"); - } - //if(sendToOptimizer("closedb")==null){ - // Reporter.writeError("close database failed"); - //} + updateCatalogIfWanted(); } // deleted or create type public void typesChanged(){ - if(sendToOptimizer("updateCatalog")==null){ - Reporter.writeError("updateCatalog failed"); - } + updateCatalogIfWanted(); } // a database is opened public void databaseOpened(String DBName){} @@ -145,18 +143,18 @@ public void setAutoUpdateCatalog(boolean auc){ } - /** Reopends the currently opened database. - **/ - private boolean reopenDatabase(){ - //System.out.println("reopen database called"); - if(OpenedDatabase.length()==0){ - return false; - } - String db = OpenedDatabase; - if(!execUserCommand("close database")){ - return false; - } - return execUserCommand("open database " + db); + /** Lets the optimizer re-read the catalog after the set of objects or types + * has changed, if the user asked for that. + * Only sensible while the optimizer is enabled -- without that check every + * object change would report a failed updateCatalog. + */ + private void updateCatalogIfWanted(){ + if(!autoUpdateCatalog || !useOptimizer()){ + return; + } + if(sendToOptimizer("updateCatalog")==null){ + Reporter.writeError("updateCatalog failed"); + } } @@ -192,25 +190,6 @@ public String retrieveDBName(){ - /** sets the connection properties for the optimizer server - * the changes holds for the next connection with a optimizer - */ - public void setOptimizer(String Host,int Port){ - OptSet.setConnection(Host,Port); - OptInt.setHost(Host); - OptInt.setPort(Port); - } - - /** Disconnects and connects to the optimizer if already connected **/ - public void reconnectOptimizer(){ - if(OptInt.isConnected()){ - OptInt.disconnect(); - OptInt.connect(); - } - } - - - /** set a new FontSize for this CommanPanel; * the Size should be in [6,50] * if the Size is not in this invervall then Size is @@ -327,438 +306,78 @@ public void clear(){ SystemArea.setCaretPosition(aktPos);; } - private boolean isWhiteSpace(char c){ - return c==' ' || c=='\n' || c=='\t' || c=='\r' ; - } - - private boolean isWordSep(char c){ - return isWhiteSpace(c) || c=='(' || c==')' || c=='[' || c==']' || c=='+'; // .... - } - - private boolean isSymbolStart(char c){ - return (c>='a' && c<='z') - || (c>='A' && c<='Z') - || (c=='_'); - } - - private boolean isSymbolElement(char c){ - return isSymbolStart(c) || (c>='0' && c<='9'); - } - - - - - /** Changes the format of error messages coming from the optimizer. - * The Error messages from the optimizer are not nice formatted. - * For example line breaks are marked by \n. This is changed by this function. - */ - private String formatOptimizerError(String errmsg){ - errmsg = errmsg.replaceAll("\\\\n","\n"); - errmsg = errmsg.replaceAll("\\\\t","\t"); - errmsg = errmsg.replaceAll("\\\\'","'"); - if(errmsg.startsWith("'") && errmsg.endsWith("'") && errmsg.length()>1){ - errmsg = errmsg.substring(1,errmsg.length()-1); - } - errmsg=errmsg.replaceAll("''","\""); - return errmsg; - } - - - - private char toLower(char c){ - if(c>='A' && c<='Z'){ - return (char)(c - 'A' + 'a'); + /** Unwraps the answer of a level 2 (SQL) command, the list + * (plan result costs), and returns the half to be rendered. + * The generated plan is echoed when the user asked for it or when only the + * plan was requested; the result half is then handed to the usual result + * renderer, so an optimized query looks exactly like a kernel query. + * For create/drop the optimizer carried the command out itself while + * translating: the plan is the atom "done" and there is no result. + */ + private ListExpr unwrapSqlAnswer(ListExpr answer, boolean planOnly){ + if(answer==null || answer.listLength()<2){ + return answer; // not the expected shape, show it unchanged } - return c; - } - - private boolean isLetter(char c){ - return ((c>='A') && (c<='Z') ) || ((c>='a' && c<='z')); - } - - private boolean isUpperCase(char c){ - return (c>='A') && (c<='Z'); - } - - - private boolean isDigit(char c){ - return c>='0' && c <= '9'; - } - - private boolean isIdentChar(char c){ - return isLetter(c) || isDigit(c) || (c == '_'); - } - - /* - Changes the first letter of symbols outside quotes starting with an upper case - to lower case. Words insie quotes or words starting with a lower case - are keept as there are. - - */ - - private static char getClosing(char bracket){ - if(bracket=='(') return ')'; - if(bracket=='{') return '}'; - if(bracket=='[') return ']'; - return bracket; - } - - - private boolean checkBrackets(String str, StringBuffer errMsg){ - Stack stack = new Stack(); - int state = 0; // 0 : normal, 1 : double quoted string, 2: single quoted string - int line = 1; - int pos = 0; // pos within line - for(int i=0;i=3 && answer.third().atomType()==ListExpr.REAL_ATOM){ + double costs = answer.third().realValue(); + if(costs>0.0){ + appendText("\nEstimated costs: " + costs); } - case 1: { // string constant - if(c=='"'){ - state = 0; - } - buf.append(c); - break; - } - case 2: { // text constant - if(c=='\''){ - state = 0; - } - buf.append(c); - } - break; - case 3: { // within an indentifier, convert all - if(isIdentChar(c)){ - //buf.append(toLower(c)); - buf.append(c); - } else { - buf.append(c); - if(c=='"'){ - state = 1; - } else if(c=='\''){ - state = 2; - } else { - state = 0; - } - } - } - break; - case 4: { // within an identifier, convert nothing - if(isIdentChar(c)){ - buf.append(c); - } else { - buf.append(c); - if(c=='"'){ - state = 1; - } else if(c=='\''){ - state = 2; - } else { - state = 0; - } - } - } - break; - - default : { - Object o = null; - if(o.equals(null)){ // force a null pointer exception - System.err.println("Bad idea"); - } - } } } - return buf.toString(); + if(planOnly){ + appendText("\nPlan only -- not executed."); + return ListExpr.theEmptyList(); + } + return answer.second(); } - /** optimizes a command if optimizer is enabled */ - private String optimize(String command){ - - // check for secondo command - command = command.trim(); + /** The command level a typed command is sent at. + * With the optimizer switched on the server is asked which of the three + * input languages the command is written in -- it is the server that + * interprets them, so it is the server that knows, and no client has to + * carry a copy of the rules (see include/SQLLanguage.h). With the optimizer + * switched off SQL is not on offer at all, and the level is derived from + * the command text as it always was. + */ + private int commandLevel(){ + return useOptimizer() ? SecondoInterface.AUTO_COMMAND_LEVEL + : SecondoInterface.DERIVE_COMMAND_LEVEL; + } - // special kernel commands - if(command.startsWith("(") || command.startsWith("{")) return command; // command in nl format or command sequence - StringTokenizer st = new StringTokenizer(command, " \t\n\r\f([{=.,;"); - if(!st.hasMoreTokens()){ - return command; - } - String start = st.nextToken(); - // check for kernel command - String[] keywords = {"query","derive","type","kill","if","while","open","close","begin","commit", "abort", - "save", "restore","list"}; - // note "update", "create", and "delete" can be both, part of the kernel and part of the optimizer - for(int i=0;i requires reopen of database (hotfix) - if(command.matches("create\\s+table\\s(.|\n)*")){ - catChanged = true; - } else if(command.matches("create\\s+index\\s(.|\n)*")){ - catChanged = true; - } else if(command.startsWith("drop ")){ - catChanged = true; - } - - - String[] pre_command_suf = rewriteForOptimizer(command); - StringBuffer buf = new StringBuffer(); - command = pre_command_suf[1]; - - if(!checkBrackets(command,buf)){ - appendText("\n\n"+buf.toString()); - showPrompt(); - return ""; - } - - //System.out.println("to " + command); - if(OpenedDatabase.length()==0){ - appendText("\nno database open"); - showPrompt(); - return ""; - } - String opt = OptInt.optimize_execute(command,OpenedDatabase,Err,false); - if(Err.value!=ErrorCodes.NO_ERROR){ // error in optimization - appendText("\nerror in optimization of this query"); - showPrompt(); - return ""; - }else if(opt.startsWith("::ERROR::")){ - appendText("\nproblem in optimization: \n"); - appendText(formatOptimizerError(opt.substring(9))+"\n"); - showPrompt(); - return ""; - } else if(catChanged){ - boolean ok = reopenDatabase(); - appendText("reopen database "); - if(ok){ - appendText("successful \n"); - } else { - appendText("failed \n"); - } - showPrompt(); - return ""; - } else { - return pre_command_suf[0] + opt + pre_command_suf[2]; - } - } + if(level==SecondoInterface.OPT_DIRECTIVE_COMMAND_LEVEL){ + appendText("\n"+(answer.atomType()==ListExpr.TEXT_ATOM + ? answer.textValue() : answer.toString())); + return ListExpr.theEmptyList(); + } + return answer; + } @@ -830,9 +449,12 @@ public boolean execUserCommand (String command, } - // command designates for the optimizer - boolean eval=false; - if((eval = command.startsWith(EvalString)) || command.startsWith(OptString)){ + // A command addressed to the optimizer explicitly. What follows the prefix + // decides what it means -- and the server decides that, exactly as it does + // for a command without the prefix: + // "optimizer " -> optimize only, report the plan, execute nothing + // "optimizer " -> run an optimizer control directive + if(command.startsWith(OptString)){ if(!useOptimizer()){ appendText("\noptimizer not available"); showPrompt(); @@ -842,61 +464,31 @@ public boolean execUserCommand (String command, return !success; } } - long starttime=0; - if(tools.Environment.MEASURE_TIME) - starttime = System.currentTimeMillis(); - - int OptCommandLength = eval?EvalString.length():OptString.length(); + return execServerCommand(command.substring(OptString.length()).trim(), + true,isTest,success,epsilon,isAbsolute, + expectedResult); + } - String answer = sendToOptimizer(command.substring(OptCommandLength)); + return execServerCommand(command,false,isTest,success,epsilon,isAbsolute, + expectedResult); + } - if(tools.Environment.MEASURE_TIME) - Reporter.writeInfo("used time for optimizing: "+(System.currentTimeMillis()-starttime)+" ms"); - if(answer==null){ - appendText("\nerror in optimizer command"); - showPrompt(); - if(!isTest){ - return false; - } else{ - return !success; - } - } - else{ - if(!eval){ - appendText("\n"+answer); - showPrompt(); - if(!isTest){ - return true; - }else{ - return success; - } - }else{ // execute the plan - // remove the "VARNAME = " from the answer - int pos = answer.indexOf("="); - if(pos >= 0){ - answer = "query " + answer.substring(pos+1); - } - if(answer.startsWith(EvalString)){ - appendText("\npossible infinite recursion detected"); - appendText("\nsuppress execution of the optimized result"); - appendText("\n the result is:\n"+answer); - showPrompt(); - if(!isTest){ - return false; - } else{ - return !success; - } - } else{ - appendText("\nevaluate the query:\n"+answer+"\n"); - addToHistory(answer); - return execUserCommand(answer,isTest,success,epsilon,isAbsolute,expectedResult); - } - } - } - } - - // normal command + /** Sends one command to the connected server and processes its result. + * The server is asked which language the command is written in and answers + * with what it decided, so the same typed command routes the same way here + * and in the TTY clients. With optimizerAddressed the user wrote the + * "optimizer " prefix: SQL is then only optimized and the plan reported, + * anything else is run as an optimizer directive. + * @see #execUserCommand(String,boolean,boolean,double,boolean,ListExpr) + */ + private boolean execServerCommand (String command, + boolean optimizerAddressed, + boolean isTest, + boolean success, + double epsilon, + boolean isAbsolute, + ListExpr expectedResult) { ListExpr displayErrorList; int displayErrorCode; @@ -909,25 +501,25 @@ public boolean execUserCommand (String command, // Executes the remote command. if(Secondointerface.isInitialized()){ - command = optimize(command); - if(command.equals("")){ - if(!isTest){ - return false; - } else{ - return !success; - } - } appendText("\n" + command + "..."); long starttime=0; if(tools.Environment.MEASURE_TIME){ starttime = System.currentTimeMillis(); } - Secondointerface.secondo(command, - resultList, - errorCode, - errorPos, - errorMessage); + Secondointerface.secondo(command, + resultList, + errorCode, + errorPos, + errorMessage, + commandLevel(), + false, + optimizerAddressed); + + if(errorCode.value==0){ + resultList.setValueTo( + unwrapAnswer(resultList,optimizerAddressed)); + } if(tools.Environment.MEASURE_TIME){ Reporter.writeInfo("used time for query: "+ @@ -1010,18 +602,35 @@ public boolean execCommand(String cmd, IntByReference errorCode, ListExpr result errorMessage.append("You are not connected to a Secondo Server"); return false; } - cmd = optimize(cmd); IntByReference errorPos=new IntByReference(); - Secondointerface.secondo(cmd, resultList,errorCode,errorPos,errorMessage); + sendCommandToServer(cmd,resultList,errorCode,errorPos,errorMessage); return errorCode.value==0; } + /** Sends a command to the server at the level it belongs to: which language + * it is written in is decided by the server, and its answer is unwrapped + * accordingly, so the caller always sees the same shape as for a kernel + * command. + */ + private void sendCommandToServer(String command, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage){ + Secondointerface.secondo(command,resultList,errorCode,errorPos,errorMessage, + commandLevel(), false); + if(errorCode.value==0){ + resultList.setValueTo(unwrapAnswer(resultList,false)); + } + } + + /** sends command to the SecondoServer the result is ignored * @return the ErrorCode from Server **/ public int internCommand (String command) { - command = optimize(command.trim()); + command = command.trim(); if(command.equals("")) return -1; ListExpr displayErrorList; int displayErrorCode; @@ -1035,11 +644,7 @@ public int internCommand (String command) { starttime = System.currentTimeMillis(); // Executes the remote command. - Secondointerface.secondo(command, //Command to execute. - resultList, - errorCode, - errorPos, - errorMessage); + sendCommandToServer(command,resultList,errorCode,errorPos,errorMessage); if(tools.Environment.MEASURE_TIME){ Reporter.writeInfo("used time for query: "+(System.currentTimeMillis()-starttime)+" ms"); } @@ -1060,7 +665,7 @@ else if(!Secondointerface.isConnected()) // connection lost * if an error occurs, null is returned **/ public ListExpr getCommandResult (String command) { - command = optimize(command.trim()); + command = command.trim(); if(command.equals("")) return ListExpr.theEmptyList(); ListExpr displayErrorList; int displayErrorCode; @@ -1074,9 +679,7 @@ public ListExpr getCommandResult (String command) { starttime = System.currentTimeMillis(); // Executes the remote command. - Secondointerface.secondo(command, //Command to execute. - resultList, - errorCode, errorPos, errorMessage); + sendCommandToServer(command,resultList,errorCode,errorPos,errorMessage); if(tools.Environment.MEASURE_TIME){ Reporter.writeInfo("used time for query: "+(System.currentTimeMillis()-starttime)+" ms"); } @@ -1124,14 +727,27 @@ public void setConnection(String User,String PassWd,String Host,int Port){ /** connect the commandpanel to SECONDO */ public boolean connect(){ + // Whether the optimizer is available is a property of the server, so it + // cannot be carried over from an earlier connection. + optimizerEnabled = false; boolean ok = Secondointerface.connect(); - if(ok) + if(ok){ + if(optimizerWanted){ + optimizerEnabled = Secondointerface.optimizerAvailable(); + if(!optimizerEnabled){ + appendText("\nthe optimizer is not available on this server"); + } + } informListeners("connect"); + } return ok; } /** disconnect from Secondo */ public void disconnect(){ + // there is no optimizer without a server to run it; the user's wish + // survives, so reconnecting brings it back where the server allows it + optimizerEnabled = false; Secondointerface.terminate(); informListeners("disconnect"); } @@ -1142,59 +758,50 @@ public void disconnect(){ * returns true if successful false otherwise */ public boolean enableOptimizer(){ - if(!useOptimizer()){ - Reporter.debug("Connet to Optimiter at " + OptInt.getHost()+":"+OptInt.getPort()); - return OptInt.connect(); + optimizerWanted = true; + if(!Secondointerface.isInitialized()){ + // Switched on from the configuration file before the connection is + // made; connect() probes the server and decides then. + return true; + } + if(!optimizerEnabled){ + // The optimizer belongs to the connected server; if that server has + // none, it cannot be switched on here. + if(!Secondointerface.optimizerAvailable()){ + Reporter.debug("the connected server provides no optimizer"); + return false; + } + optimizerEnabled = true; } return true; } - /** sends the given command to the optimizer + /** runs the given optimizer control directive (a Prolog goal such as + * "showOptions", "setOption(subqueries)", "updateCatalog") in the server's + * optimizer and returns the text it printed * returns null if not successful */ public String sendToOptimizer(String cmd){ - if(!OptInt.isConnected()) - return null; - IntObj Err = new IntObj(); - String res = OptInt.optimize_execute(cmd,OpenedDatabase,Err,true); - if(Err.value!=ErrorCodes.NO_ERROR) + if(!useOptimizer()) return null; - else - return res; + return Secondointerface.optimizerCommand(cmd); } /** disables the use of the optimizer */ public void disableOptimizer(){ - if(useOptimizer()){ - IntObj err = new IntObj(); - OptInt.optimize_execute("secondo('close database')",OpenedDatabase, err, true); - } - OptInt.disconnect(); + optimizerWanted = false; + optimizerEnabled = false; } - /** returns true if the opttimizer is enabled - * if the optimizer was enabled but the connection is broken, - * the function will return false - */ + /** returns true if the optimizer is enabled */ public boolean useOptimizer(){ - return OptInt.isConnected(); - } - - /** shows a dialog for making settings for optimizer - */ - public void showOptimizerSettings(){ - if(OptSet.showDialog()){ - OptInt.setHost(OptSet.getHost()); - OptInt.setPort(OptSet.getPort()); - } + return optimizerEnabled; } - - public String getOpenedDatabase(){ return OpenedDatabase; } @@ -1301,7 +908,9 @@ private void informListeners(String cmd){ OpenedDatabase=""; SCL.databaseClosed(); } else if(cmd.startsWith("create ") || cmd.startsWith("delete ") || cmd.startsWith("let ") || - cmd.startsWith("update ")) + cmd.startsWith("update ") || + // SQL dialect: "drop table/index ..." and "insert into ..." + cmd.startsWith("drop ") || cmd.startsWith("insert ")) SCL.objectsChanged(); else if(cmd.equals("connect")) SCL.connectionOpened(); @@ -1664,8 +1273,7 @@ public Interval(int x, int y){ } // define strings for special treatment when a command begins with it -private static final String OptString ="optimizer "; -private static final String EvalString="eval "; +private static final String OptString ="optimizer "; diff --git a/Javagui/gui/MainWindow.java b/Javagui/gui/MainWindow.java index 984e261914..ca628a1a6b 100755 --- a/Javagui/gui/MainWindow.java +++ b/Javagui/gui/MainWindow.java @@ -116,9 +116,9 @@ public class MainWindow extends JFrame implements ResultProcessor,ViewerControl, private JMenuItem MI_OptimizerDisable; private JMenuItem MI_OptimizerUpdateCatalog; private JMenuItem MI_OptimizerTestOptimizer; -private JCheckBoxMenuItem MI_OptimizerReconnectWhenOpenDB; private JCheckBoxMenuItem MI_OptimizerAutoUpdateCatalog; private JMenuItem MI_OptimizerResetKnowledgeDB; +private JMenuItem MI_OptimizerShowOptions; private JCheckBoxMenuItem ShowRewrittenQuery; private JMenu OptimizerCommandMenu; @@ -130,7 +130,6 @@ public class MainWindow extends JFrame implements ResultProcessor,ViewerControl, private boolean useEntropy; private JMenuItem MI_EnableEntropy; private JMenuItem MI_DisableEntropy; -private JMenuItem MI_OptimizerSettings; private JMenu Menu_ServerCommand; @@ -732,29 +731,8 @@ public String getDescription(){ StartScript = Config.getProperty("STARTSCRIPT"); - // optimizer settings - String OptHost = Config.getProperty("OPTIMIZER_HOST"); - if(OptHost==null){ - OptHost ="localhost"; // the default value - Reporter.writeError("OPTIMIZER_HOST not defined, use default: "+OptHost); - } - String OptPortString = Config.getProperty("OPTIMIZER_PORT"); - int OptPort = 1235; // default value - if(OptPortString!=null){ - try{ - int P = Integer.parseInt(OptPortString); - if(P<=0){ - Reporter.writeError("optimizer-port has no valid value"); - }else - OptPort = P; - } - catch(Exception e){ - Reporter.writeError("optimizer-port is not a valid integer"); - } - }else{ - Reporter.writeError("OPTIMIZER_PORT not defined, use default: "+OptPort); - } - ComPanel.setOptimizer(OptHost,OptPort); + // The optimizer runs inside the connected Secondo server, so there is no + // host/port to configure any more; it only has to be switched on. String OptEnable = Config.getProperty("ENABLE_OPTIMIZER"); if(OptEnable==null){ Reporter.writeError("ENABLE_OPTIMIZER not defined in configuration file"); @@ -1016,24 +994,38 @@ private boolean exportToPS(Component c){ /** Function enabling or disabling the entropy function of the Optimizer. **/ private void enableEntropy(boolean on){ - String command = on?"use_entropy":"dont_use_entropy"; - ComPanel.appendText("\noptimizer "+command+" "); - if(ComPanel.sendToOptimizer(command)==null){ - ComPanel.appendText(" ... failed"); - }else{ - ComPanel.appendText(" ... successful"); - } - ComPanel.showPrompt(); + runOptimizerDirective(on?"use_entropy":"dont_use_entropy"); } private void updateCatalog(){ - String command ="updateCatalog"; + runOptimizerDirective("updateCatalog"); +} + + +/** Shows the optimizer's current option settings. Together with the + * "optimizer setOption(X)" / "optimizer delOption(X)" command entry this + * exposes the whole option family SecondoPL offers. + **/ +private void showOptimizerOptions(){ + runOptimizerDirective("showOptions"); +} + + +/** Runs one optimizer control directive in the connected server and echoes + * whatever it printed. A directive that fails without printing anything + * yields null and is reported as failed. + **/ +private void runOptimizerDirective(String command){ ComPanel.appendText("\noptimizer "+ command +" "); - if(ComPanel.sendToOptimizer(command)==null){ - ComPanel.appendText(" ... failed"); - }else{ - ComPanel.appendText(" ... successful"); + String answer = ComPanel.sendToOptimizer(command); + if(answer==null){ + ComPanel.appendText(" ... failed"); + } else { + ComPanel.appendText(" ... successful"); + if(answer.trim().length()>0){ + ComPanel.appendText("\n"+answer); + } } ComPanel.showPrompt(); } @@ -1052,14 +1044,7 @@ private void testOptimizer(){ private void resetKnowledgeDB(){ - String command ="resetKnowledgeDB"; - ComPanel.appendText("\noptimizer "+ command +" "); - if(ComPanel.sendToOptimizer(command)==null){ - ComPanel.appendText(" ... failed"); - }else{ - ComPanel.appendText(" ... successful"); - } - ComPanel.showPrompt(); + runOptimizerDirective("resetKnowledgeDB"); } @@ -2908,8 +2893,6 @@ public void actionPerformed(ActionEvent evt){ MI_OptimizerUpdateCatalog = new JMenuItem("Update Catalog"); MI_OptimizerTestOptimizer = new JMenuItem("Test Optimizer"); - MI_OptimizerReconnectWhenOpenDB = new JCheckBoxMenuItem("Auto Reconnect"); - MI_OptimizerReconnectWhenOpenDB.setSelected(true); MI_OptimizerAutoUpdateCatalog = new JCheckBoxMenuItem("Auto Update Catalog"); MI_OptimizerAutoUpdateCatalog.setSelected(true); ComPanel.setAutoUpdateCatalog(true); @@ -2931,11 +2914,12 @@ public void stateChanged(ChangeEvent evt){ ShowRewrittenQuery.setSelected(false); MI_OptimizerResetKnowledgeDB = new JMenuItem("Reset Optimizer's Knowledge Database"); + MI_OptimizerShowOptions = new JMenuItem("Show Options"); OptimizerCommandMenu.add(MI_OptimizerUpdateCatalog); OptimizerCommandMenu.add(MI_OptimizerAutoUpdateCatalog); - OptimizerCommandMenu.add(MI_OptimizerReconnectWhenOpenDB); OptimizerCommandMenu.add(MI_OptimizerResetKnowledgeDB); + OptimizerCommandMenu.add(MI_OptimizerShowOptions); // Test Optimizer is currently disabled due to errors in test spec // OptimizerCommandMenu.addSeparator(); @@ -2966,6 +2950,9 @@ public void actionPerformed(ActionEvent evt){ if(src.equals(MI_OptimizerResetKnowledgeDB)){ resetKnowledgeDB(); } + if(src.equals(MI_OptimizerShowOptions)){ + showOptimizerOptions(); + } if(src.equals(MI_OptimizerTestOptimizer)){ testOptimizer(); } @@ -2974,6 +2961,7 @@ public void actionPerformed(ActionEvent evt){ MI_OptimizerUpdateCatalog.addActionListener(b); MI_OptimizerTestOptimizer.addActionListener(b); MI_OptimizerResetKnowledgeDB.addActionListener(b); + MI_OptimizerShowOptions.addActionListener(b); @@ -2995,7 +2983,6 @@ public void actionPerformed(ActionEvent evt){ if(useEntropy) OptimizerCommandMenu.add(Entropy); - MI_OptimizerSettings = OptimizerMenu.add("Settings"); OptimizerMenu.addMenuListener(new MenuListener(){ public void menuSelected(MenuEvent evt){ if(ComPanel.useOptimizer()){ @@ -3031,12 +3018,9 @@ public void actionPerformed(ActionEvent evt){ ComPanel.showPrompt(); ComPanel.disableOptimizer(); } - if(source.equals(MI_OptimizerSettings)) - ComPanel.showOptimizerSettings(); }}; MI_OptimizerEnable.addActionListener(OptimizerListener); - MI_OptimizerSettings.addActionListener(OptimizerListener); MI_OptimizerDisable.addActionListener(OptimizerListener); @@ -3644,10 +3628,6 @@ public void databaseOpened(String DBName){ } public void databaseClosed(){ - if(MI_OptimizerReconnectWhenOpenDB.isSelected()){ - Reporter.debug("HOtfix reconnect optimizer"); - ComPanel.reconnectOptimizer(); - } MI_ListTypes.setEnabled(false); MI_ListObjects.setEnabled(false); MI_CloseDatabase.setEnabled(false); diff --git a/Javagui/makefile b/Javagui/makefile index 2208bd7a85..771cb53c95 100755 --- a/Javagui/makefile +++ b/Javagui/makefile @@ -87,7 +87,6 @@ removedoc: makedirs: rm -rf sj $(MAKE) -j 1 -C secondoInterface SecondoInterface.jar - $(MAKE) -j 1 -C communication all $(MAKE) -j 1 -C extern all $(MAKE) -j 1 -C components all $(MAKE) -j 1 -C viewer all @@ -102,7 +101,6 @@ makedirs: .PHONY: clean # removes the documentation and all .class files clean: removedoc $(MAKE) -C secondoInterface clean - $(MAKE) -C communication clean $(MAKE) -C components clean $(MAKE) -C extern clean $(MAKE) -C gui clean diff --git a/Javagui/secondoInterface/sj/lang/ESInterface.java b/Javagui/secondoInterface/sj/lang/ESInterface.java index 6d2374f281..6aba1f1648 100755 --- a/Javagui/secondoInterface/sj/lang/ESInterface.java +++ b/Javagui/secondoInterface/sj/lang/ESInterface.java @@ -147,7 +147,44 @@ public void secondo(String command, if(errorCode.value==81) terminate(); } - + + /** calls super.secondo with an explicit command level (2 = SQL, or + * AUTO_COMMAND_LEVEL to let the server classify the command) and the + * optional "planonly" protocol flag; behaves like the five argument version + * on a lost connection + */ + public void secondo(String command, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage, + int commandLevel, + boolean planOnly){ + + secondo(command,resultList,errorCode,errorPos,errorMessage, + commandLevel,planOnly,false); + } + + /** calls super.secondo with the "optimizer" protocol flag in addition: the + * user addressed the optimizer explicitly, so on the auto level SQL is only + * optimized and anything else is run as an optimizer directive + */ + public void secondo(String command, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage, + int commandLevel, + boolean planOnly, + boolean optimizerAddressed){ + + super.secondo(command,resultList,errorCode,errorPos,errorMessage, + commandLevel,planOnly,optimizerAddressed); + if(errorCode.value==81) + terminate(); + } + + /* public void secondo( String commandText, diff --git a/Javagui/secondoInterface/sj/lang/SecondoInterface.java b/Javagui/secondoInterface/sj/lang/SecondoInterface.java index aa6720e422..57330c9bad 100755 --- a/Javagui/secondoInterface/sj/lang/SecondoInterface.java +++ b/Javagui/secondoInterface/sj/lang/SecondoInterface.java @@ -614,32 +614,120 @@ private void callSaveCommand(String command, */ +/* The command levels, the Java side of include/SQLLanguage.h. + * 0, 1 and 2 are the levels a command is executed at. AUTO_COMMAND_LEVEL is the + * sentinel sent to ask the server which language the command is written in; it + * answers with the level it resolved to, which getResolvedCommandLevel() + * reports. OPT_DIRECTIVE_COMMAND_LEVEL only ever comes back in such an answer, + * it is never sent. + */ +public static final int NESTED_LIST_COMMAND_LEVEL = 0; +public static final int TEXT_COMMAND_LEVEL = 1; +public static final int SQL_COMMAND_LEVEL = 2; +public static final int OPT_DIRECTIVE_COMMAND_LEVEL = 3; + +public static final int AUTO_COMMAND_LEVEL = -1; + +/** command level to be derived from the command text itself, without asking + * the server: a leading "(" is a nested list, anything else is text. Never + * written to the wire. + */ +public static final int DERIVE_COMMAND_LEVEL = -3; + +/** the level the server resolved the last auto-level command to */ +private int resolvedCommandLevel = TEXT_COMMAND_LEVEL; + protected void secondo(String command, ListExpr resultList, IntByReference errorCode, IntByReference errorPos, StringBuffer errorMessage){ + secondo(command, resultList, errorCode, errorPos, errorMessage, + DERIVE_COMMAND_LEVEL, false); +} + +/** Reports the command level the server resolved the last command sent at + * AUTO_COMMAND_LEVEL to. It tells the caller + * how to read the answer: SQL_COMMAND_LEVEL means the list + * (plan result costs), OPT_DIRECTIVE_COMMAND_LEVEL the text an optimizer goal + * printed, and 0/1 an ordinary result. After a command sent at an explicit + * level it is that level. + */ +public int getResolvedCommandLevel(){ + return resolvedCommandLevel; +} + +/** Sends a command at an explicitly given command level. + * The levels are 0 (nested list), 1 (SOS text) and 2 (SQL: the server + * optimizes the command itself and answers with the list + * (plan result costs)). DERIVE_COMMAND_LEVEL picks 0 or 1 from the command + * text, as the five argument version has always done; AUTO_COMMAND_LEVEL + * leaves the choice to the server (see getResolvedCommandLevel). + * With planOnly the "planonly" protocol flag is written behind the level; + * the server then stops after optimizing, so the plan and its costs come + * back and nothing is executed. It is meaningful for level 2 only. + */ +protected void secondo(String command, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage, + int commandLevel, + boolean planOnly){ + secondo(command, resultList, errorCode, errorPos, errorMessage, + commandLevel, planOnly, false); +} + +/** Sends a command, saying in addition that the user addressed the optimizer + * explicitly (the "optimizer " prefix). That is written as the "optimizer" + * protocol flag and is meaningful on the auto level only: the server then + * optimizes SQL without executing it, and runs anything else as an optimizer + * directive. + */ +protected void secondo(String command, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage, + int commandLevel, + boolean planOnly, + boolean optimizerAddressed){ // write command to console if desired if(Environment.SHOW_COMMAND){ Reporter.write(command); - } + } // clean the errormessage - errorMessage.setLength(0); + errorMessage.setLength(0); errorCode.value = 0; resultList.setValueTo( ListExpr.theEmptyList() ); // check for existing connection - if ( serverSocket == null ) { + if ( serverSocket == null ) { errorCode.value = 80; return; } // check for restore command command=command.trim(); + if(commandLevel==DERIVE_COMMAND_LEVEL){ + commandLevel = command.startsWith("(") ? NESTED_LIST_COMMAND_LEVEL + : TEXT_COMMAND_LEVEL; + } try{ + // The restore/save interception below rewrites the command; it must not + // touch SQL, which only the server can interpret. The C++ client guards + // this the same way (SecondoInterfaceCS.cpp, specialCmdLevel != 2). + // The AUTO levels do pass through it: save and restore are kernel + // commands, never SQL, and it is the client that holds the file, so it + // has to recognize them itself whoever classifies the rest. + if(commandLevel==SQL_COMMAND_LEVEL){ + sendCommand(command, commandLevel, planOnly, optimizerAddressed, + resultList, errorCode, errorPos, errorMessage); + return; + } if(command.startsWith("restore ")){ callRestoreCommand(command, resultList, errorCode, errorPos, errorMessage); return; @@ -658,20 +746,70 @@ protected void secondo(String command, return; } - // not a special command - int commandLevel = command.startsWith("(")?0:1; - outSocketStream.write( "\n"); - outSocketStream.write( commandLevel + "\n" ); - outSocketStream.write(command); - outSocketStream.write("\n\n" ); - outSocketStream.flush(); - receiveResponse(resultList, errorCode, errorPos, errorMessage); + // not a special command + sendCommand(command, commandLevel, planOnly, optimizerAddressed, + resultList, errorCode, errorPos, errorMessage); } catch(IOException e){ errorCode.value=81; return; } } +/** Writes one framed command and reads its answer. + * The level line is "[ planonly]": the server reads the level and + * takes the rest of that line as protocol flags, a part it discarded before + * the flag existed, so omitting it changes nothing. + */ +private void sendCommand(String command, + int commandLevel, + boolean planOnly, + boolean optimizerAddressed, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage) throws IOException { + outSocketStream.write( "\n"); + outSocketStream.write( commandLevel + (planOnly?" planonly":"") + + (optimizerAddressed?" optimizer":"") + + "\n" ); + outSocketStream.write(command); + outSocketStream.write("\n\n" ); + outSocketStream.flush(); + // A server that was asked to classify the command answers with the level it + // resolved to, ahead of everything else. It writes that line only for a + // client that asked, so the protocol is unchanged for everyone sending an + // explicit level. + resolvedCommandLevel = commandLevel; + if(commandLevel<0){ + resolvedCommandLevel = parseCommandLevelEcho(inSocketStream.readLine()); + } + receiveResponse(resultList, errorCode, errorPos, errorMessage); +} + +/** Reads the "<CommandLevel>n</CommandLevel>" line the server + * answers an auto level with. Falls back to the text level when the line is + * not the expected echo -- the connection is then out of step with the + * server, which the response reader reports. + */ +private static int parseCommandLevelEcho(String line){ + if(line==null){ + return TEXT_COMMAND_LEVEL; + } + line = line.trim(); + String open = ""; + String close = ""; + if(!line.startsWith(open) || !line.endsWith(close) + || line.length() <= open.length()+close.length()){ + return TEXT_COMMAND_LEVEL; + } + try{ + return Integer.parseInt( + line.substring(open.length(), line.length()-close.length())); + } catch(NumberFormatException e){ + return TEXT_COMMAND_LEVEL; + } +} + public boolean setHeartbeat(int heart1, int heart2){ try{ outSocketStream.write("\n"); @@ -1163,6 +1301,73 @@ public int getPid(){ } } +/** Asks the connected server whether the optimizer (SQL dialect, command + * level 2) is available, i.e. compiled in and enabled for that server. + */ +public boolean optimizerAvailable(){ + if(serverSocket == null){ + return false; + } + try{ + outSocketStream.writeln(""); + outSocketStream.flush(); + String line = inSocketStream.readLine(); + return line!=null && line.trim().equals("yes"); + } catch(Exception e){ + return false; + } +} + +/** Runs an optimizer control directive (a Prolog goal such as "showOptions", + * "setOption(subqueries)", "updateCatalog") in the server's embedded + * optimizer and returns the text the directive printed. + * Returns null when the directive failed without printing anything -- every + * caller treats null as failure. A goal that fails but still writes + * something useful (some option sub-goals do) yields that text, matching the + * C++ client (SecondoInterfaceCS::optimizerCommand). + */ +public String optimizerCommand(String directive){ + if(serverSocket == null){ + return null; + } + try{ + outSocketStream.writeln(""); + outSocketStream.writeln(directive); + outSocketStream.writeln(""); + outSocketStream.flush(); + + // Reply: a status line ("ok" / "ERR:") then a framed text block. + String status = inSocketStream.readLine(); + if(status==null){ + return null; + } + status = status.trim(); + + StringBuffer output = new StringBuffer(); + inSocketStream.readLine(); // opening + String line; + boolean first = true; + while((line = inSocketStream.readLine())!=null){ + if(line.equals("")){ + break; + } + // Preserve the directive's own layout (showOptions relies on + // leading whitespace), so do not trim the content lines. + if(!first){ + output.append("\n"); + } + output.append(line); + first = false; + } + if(status.startsWith("ERR:") && output.length()==0){ + return null; + } + return output.toString(); + } catch(Exception e){ + return null; + } +} + public boolean cancelQuery(int pid) { try{ outSocketStream.writeln(""); diff --git a/Javagui/viewer/hoese2/gui/MainWindow.java b/Javagui/viewer/hoese2/gui/MainWindow.java index 2ae6d0f9cc..42cf662923 100755 --- a/Javagui/viewer/hoese2/gui/MainWindow.java +++ b/Javagui/viewer/hoese2/gui/MainWindow.java @@ -110,9 +110,9 @@ public class MainWindow extends JFrame implements ResultProcessor,ViewerControl, private JMenuItem MI_OptimizerDisable; private JMenuItem MI_OptimizerUpdateCatalog; private JMenuItem MI_OptimizerTestOptimizer; -private JCheckBoxMenuItem MI_OptimizerReconnectWhenOpenDB; private JCheckBoxMenuItem MI_OptimizerAutoUpdateCatalog; private JMenuItem MI_OptimizerResetKnowledgeDB; +private JMenuItem MI_OptimizerShowOptions; private JMenu OptimizerCommandMenu; private JMenu UpdateRelationsMenu; @@ -123,7 +123,6 @@ public class MainWindow extends JFrame implements ResultProcessor,ViewerControl, private boolean useEntropy; private JMenuItem MI_EnableEntropy; private JMenuItem MI_DisableEntropy; -private JMenuItem MI_OptimizerSettings; private JMenu Menu_ServerCommand; @@ -720,29 +719,8 @@ public String getDescription(){ StartScript = Config.getProperty("STARTSCRIPT"); - // optimizer settings - String OptHost = Config.getProperty("OPTIMIZER_HOST"); - if(OptHost==null){ - OptHost ="localhost"; // the default value - Reporter.writeError("OPTIMIZER_HOST not defined, use default: "+OptHost); - } - String OptPortString = Config.getProperty("OPTIMIZER_PORT"); - int OptPort = 1235; // default value - if(OptPortString!=null){ - try{ - int P = Integer.parseInt(OptPortString); - if(P<=0){ - Reporter.writeError("optimizer-port has no valid value"); - }else - OptPort = P; - } - catch(Exception e){ - Reporter.writeError("optimizer-port is not a valid integer"); - } - }else{ - Reporter.writeError("OPTIMIZER_PORT not defined, use default: "+OptPort); - } - ComPanel.setOptimizer(OptHost,OptPort); + // The optimizer runs inside the connected Secondo server, so there is no + // host/port to configure any more; it only has to be switched on. String OptEnable = Config.getProperty("ENABLE_OPTIMIZER"); if(OptEnable==null){ Reporter.writeError("ENABLE_OPTIMIZER not defined in configuration file"); @@ -998,24 +976,38 @@ private boolean exportToPS(Component c){ /** Function enabling or disabling the entropy function of the Optimizer. **/ private void enableEntropy(boolean on){ - String command = on?"use_entropy":"dont_use_entropy"; - ComPanel.appendText("\noptimizer "+command+" "); - if(ComPanel.sendToOptimizer(command)==null){ - ComPanel.appendText(" ... failed"); - }else{ - ComPanel.appendText(" ... successful"); - } - ComPanel.showPrompt(); + runOptimizerDirective(on?"use_entropy":"dont_use_entropy"); } private void updateCatalog(){ - String command ="updateCatalog"; + runOptimizerDirective("updateCatalog"); +} + + +/** Shows the optimizer's current option settings. Together with the + * "optimizer setOption(X)" / "optimizer delOption(X)" command entry this + * exposes the whole option family SecondoPL offers. + **/ +private void showOptimizerOptions(){ + runOptimizerDirective("showOptions"); +} + + +/** Runs one optimizer control directive in the connected server and echoes + * whatever it printed. A directive that fails without printing anything + * yields null and is reported as failed. + **/ +private void runOptimizerDirective(String command){ ComPanel.appendText("\noptimizer "+ command +" "); - if(ComPanel.sendToOptimizer(command)==null){ - ComPanel.appendText(" ... failed"); - }else{ - ComPanel.appendText(" ... successful"); + String answer = ComPanel.sendToOptimizer(command); + if(answer==null){ + ComPanel.appendText(" ... failed"); + } else { + ComPanel.appendText(" ... successful"); + if(answer.trim().length()>0){ + ComPanel.appendText("\n"+answer); + } } ComPanel.showPrompt(); } @@ -1034,14 +1026,7 @@ private void testOptimizer(){ private void resetKnowledgeDB(){ - String command ="resetKnowledgeDB"; - ComPanel.appendText("\noptimizer "+ command +" "); - if(ComPanel.sendToOptimizer(command)==null){ - ComPanel.appendText(" ... failed"); - }else{ - ComPanel.appendText(" ... successful"); - } - ComPanel.showPrompt(); + runOptimizerDirective("resetKnowledgeDB"); } @@ -2806,8 +2791,6 @@ public void actionPerformed(ActionEvent evt){ MI_OptimizerUpdateCatalog = new JMenuItem("Update Catalog"); MI_OptimizerTestOptimizer = new JMenuItem("Test Optimizer"); - MI_OptimizerReconnectWhenOpenDB = new JCheckBoxMenuItem("Auto Reconnect"); - MI_OptimizerReconnectWhenOpenDB.setSelected(true); MI_OptimizerAutoUpdateCatalog = new JCheckBoxMenuItem("Auto Update Catalog"); MI_OptimizerAutoUpdateCatalog.setSelected(true); ComPanel.setAutoUpdateCatalog(true); @@ -2821,11 +2804,12 @@ public void itemStateChanged(ItemEvent evt){ MI_OptimizerResetKnowledgeDB = new JMenuItem("Reset Optimizer's Knowledge Database"); + MI_OptimizerShowOptions = new JMenuItem("Show Options"); OptimizerCommandMenu.add(MI_OptimizerUpdateCatalog); OptimizerCommandMenu.add(MI_OptimizerAutoUpdateCatalog); - OptimizerCommandMenu.add(MI_OptimizerReconnectWhenOpenDB); OptimizerCommandMenu.add(MI_OptimizerResetKnowledgeDB); + OptimizerCommandMenu.add(MI_OptimizerShowOptions); OptimizerCommandMenu.addSeparator(); OptimizerCommandMenu.add(MI_OptimizerTestOptimizer); @@ -2854,6 +2838,9 @@ public void actionPerformed(ActionEvent evt){ if(src.equals(MI_OptimizerResetKnowledgeDB)){ resetKnowledgeDB(); } + if(src.equals(MI_OptimizerShowOptions)){ + showOptimizerOptions(); + } if(src.equals(MI_OptimizerTestOptimizer)){ testOptimizer(); } @@ -2862,6 +2849,7 @@ public void actionPerformed(ActionEvent evt){ MI_OptimizerUpdateCatalog.addActionListener(b); MI_OptimizerTestOptimizer.addActionListener(b); MI_OptimizerResetKnowledgeDB.addActionListener(b); + MI_OptimizerShowOptions.addActionListener(b); @@ -2883,7 +2871,6 @@ public void actionPerformed(ActionEvent evt){ if(useEntropy) OptimizerCommandMenu.add(Entropy); - MI_OptimizerSettings = OptimizerMenu.add("Settings"); OptimizerMenu.addMenuListener(new MenuListener(){ public void menuSelected(MenuEvent evt){ if(ComPanel.useOptimizer()){ @@ -2919,12 +2906,9 @@ public void actionPerformed(ActionEvent evt){ ComPanel.showPrompt(); ComPanel.disableOptimizer(); } - if(source.equals(MI_OptimizerSettings)) - ComPanel.showOptimizerSettings(); }}; MI_OptimizerEnable.addActionListener(OptimizerListener); - MI_OptimizerSettings.addActionListener(OptimizerListener); MI_OptimizerDisable.addActionListener(OptimizerListener); @@ -3524,10 +3508,6 @@ public void databaseOpened(String DBName){ } public void databaseClosed(){ - if(MI_OptimizerReconnectWhenOpenDB.isSelected()){ - Reporter.debug("HOtfix reconnect optimizer"); - ComPanel.reconnectOptimizer(); - } MI_ListTypes.setEnabled(false); MI_ListObjects.setEnabled(false); MI_CloseDatabase.setEnabled(false); diff --git a/Jpl/jsrc/10/jpl/Atom.java b/Jpl/jsrc/10/jpl/Atom.java deleted file mode 100755 index 0522d877ae..0000000000 --- a/Jpl/jsrc/10/jpl/Atom.java +++ /dev/null @@ -1,239 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import jpl.fli.*; - -//----------------------------------------------------------------------/ -// Atom -/** - * An Atom is a Term with a name field. Use this class to create - * Java representations of Prolog atoms: - *
- * Atom a = new Atom( "a" );
- * 
- * - * An Atom can be used (and re-used) in Compound Terms. - * - *
- * Copyright (C) 1998 Fred Dushin

- * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

- * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

- *


- * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class Atom -extends Term -{ - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * This atom's name - */ - protected java.lang.String name_; - - //------------------------------------------------------------------/ - // name - /** - * @return the name of the Atom - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final java.lang.String - name() - { - return name_; - } - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - //------------------------------------------------------------------/ - // Atom - /** - * @param name the Atom's name - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Atom( java.lang.String name ) - { - this.name_ = name; - } - - //==================================================================/ - // Converting Terms to term_ts - //==================================================================/ - - //------------------------------------------------------------------/ - // put - /** - * To put an Atom in a term, we put an atom_t into the term_t. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have packed in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param term A (previously created) term_t which is to be - * packed with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - put( Hashtable var_table, term_t term ) - { - Prolog.put_atom( term, Prolog.new_atom( name_ ) ); - } - - - //==================================================================/ - // Converting term_ts to Terms - //==================================================================/ - - //------------------------------------------------------------------/ - // from_term_t - /** - * Converts a term_t to an Atom. Assuming the term is an - * atom, we just create a new Atom using the term's name. - * - * We are careful to create a List.Nil object if indeed the - * atom is "[]". Note that nil is an atom in Prolog and jpl. - * - * @param term The term_t to convert - * @return A new Atom - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static Term - from_term_t( Hashtable vars, term_t term ) - { - StringHolder holder = new StringHolder(); - Prolog.get_atom_chars( term, holder ); - - if ( holder.value.equals( "[]" ) ){ - return new List.Nil(); - } else { - return new Atom( holder.value ); - } - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - - //------------------------------------------------------------------/ - // computeSubstitution - /** - * Nothing needs to be done if the Term is an Atom. - * - * @param table table holding Term substitutions, keyed on - * Variables. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - computeSubstitution( Hashtable bindings, Hashtable vars ) - { - } - - - - //------------------------------------------------------------------/ - // toString - /** - * Converts an Atom to its String form -- its name. - * - * @return String representation of an Atom - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.lang.String - toString() - { - return name_; - } - - public java.lang.String - debugString() - { - return "(Atom " + toString() + ")"; - } - - //------------------------------------------------------------------/ - // equals - /** - * Two Atoms are equal if their names are equal - * - * @param obj The Object to compare - * @return true if the Object satisfies the above condition - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - equals( Object obj ) - { - if ( this == obj ){ - return true; - } - - if ( ! (obj instanceof Atom) ){ - return false; - } - - return name_.equals( ((Atom)obj).name_ ); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/Compound.java b/Jpl/jsrc/10/jpl/Compound.java deleted file mode 100755 index 723724bf00..0000000000 --- a/Jpl/jsrc/10/jpl/Compound.java +++ /dev/null @@ -1,693 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import jpl.fli.*; - -//----------------------------------------------------------------------/ -// Compound -/** - * A Compound is a base class for all of the compound class types - * (e.g., List, Tuple, etc.), but it can also be instantiated to - * produce, for example, any functional expression. For example, to - * produce the term f(a), one might write: - *
- * Term[] arg = { new Atom( "a" ) };
- * Compound f = new Compound( new Atom( "f" ), arg );
- * 
- * - * See the List and Tuple classes for common extensions of this class. - * - *
- * Copyright (C) 1998 Fred Dushin

- * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

- * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

- *


- * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.List - * @see jpl.Tuple - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class Compound -extends Term -{ - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the atom in this Compound - */ - protected Atom atom_ = null; - - /** - * the arguments in this Compound - */ - protected Term[] args_ = null; - - /** - * @return the atom in this Compound - */ - public final Atom - atom() - { - return atom_; - } - - /** - * @return the arguments in this Compound - */ - public final Term[] - args() - { - return args_; - } - - /** - * @return the ith argument in this Compound - */ - public final Term - ith( int i) - { - return args_[i]; - } - - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - - //------------------------------------------------------------------/ - // Compound - /** - * Creates a Comound with an Atom and an array of arguments. The - * length of the array determines the arity of the Compound. - * - * @param atom the Atom in this Compound - * @param args the arguments in this Compound - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( Atom atom, Term args[] ) - { - this.atom_ = atom; - this.args_ = args; - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is short for - *
-	 * new Compound( new Atom( name ), arg )
-	 * 
- * - * @param name the name for the Atom in this Compound - * @param args the arguments in this Compound - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( java.lang.String name, Term args[] ) - { - this( new Atom( name ), args ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0 ) - { - this( - new Atom( name ), - Util.toTermArray( t0 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1, t2 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1, - Term t2 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1, t2, t3 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1, t2, t3, t4 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
-	 *                       t5 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
-	 *                       t5, t6 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
-	 *                       t5, t6, t7 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
-	 *                       t5, t6, t7, t8 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - * @param t8 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7, - Term t8 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7, t8 ) ); - } - - //------------------------------------------------------------------/ - // Compound - /** - * This constructor is shorthand for - *
-	 * new Compound( 
-	 *     new Atom( name ), 
-	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
-	 *                       t5, t6, t7, t8, t9 ) )
-	 * 
- * - * @param name the name of the functor in this Compound - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - * @param t8 a jpl.Term - * @param t9 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Compound( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7, - Term t8, - Term t9 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7, t8, t9 ) ); - } - - - - //==================================================================/ - // Converting Terms to term_ts - //==================================================================/ - - //------------------------------------------------------------------/ - // put - /** - * To put an Compound in a term, we create a sequence of term_t - * references from the Term terms_to_term_t method, and then - * use the Prolog cons_functor_v method to create a Prolog compound. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have packed in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param term A (previously created) term_t which is to be - * packed with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - // Implementation notes: This method is over-ridden in each of - // the Term's subclasses, but it is always called from them, as well. - //------------------------------------------------------------------/ - protected final void - put( Hashtable var_table, term_t term ) - { - term_t term0 = Term.terms_to_term_ts( var_table, args_ ); - - Prolog.cons_functor_v( - term, - Prolog.new_functor( - Prolog.new_atom( atom_.name_ ), - args_.length ), - term0 ); - } - - //==================================================================/ - // Converting term_ts to Terms - //==================================================================/ - - //------------------------------------------------------------------/ - // from_term_t - /** - * Converts a term_t to a Compound. In this case, we create - * an Atom and a list of Terms by calling from_term_t for each - * term_t reference we get from Prolog.get_arg (Not sure why - * we couldn't get a sequence from there, but...).

- * - * We have to do a bit of type analysis to create Java objects - * of the right type. For example, we don't want to create just - * a Compound if the term_t is a list or a tuple; we want to - * create a List or a Tuple, accordingly. - * - * @param term The term_t to convert - * @return A new Atom - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static Term - from_term_t( Hashtable vars, term_t term ) - { - atom_t atom = new atom_t(); - IntHolder arity_holder = new IntHolder(); - - Prolog.get_name_arity( term, atom, arity_holder ); - java.lang.String atom_name = Prolog.atom_chars( atom ); - - Term arg[] = new Term[arity_holder.value]; - - for ( int i = 1; i <= arity_holder.value; ++i ){ - term_t termi = Prolog.new_term_ref(); - - Prolog.get_arg( i, term, termi ); - arg[i-1] = Term.from_term_t( vars, termi ); - } - - if ( atom_name.equals( "." ) ){ - return - new List( - arg[0], arg[1] ); - } else if ( atom_name.equals( "," ) ) { - if ( arg.length == 2 ){ - return - new Tuple.Pair( arg[0], arg[1] ); - } else { - return - new Tuple( arg ); - } - } else { - return - new Compound( - new Atom( atom_name ), - arg ); - } - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - - //------------------------------------------------------------------/ - // computeSubstitution - /** - * Nothing needs to be done except to pass the buck to the args. - * - * @param table table holding Term substitutions, keyed on - * Variables. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - computeSubstitution( Hashtable bindings, Hashtable vars ) - { - Term.computeSubstitutions( bindings, vars, args_ ); - } - - - //------------------------------------------------------------------/ - // toString - /** - * Converts a Compound to its String form, atom( arg_1, ..., arg_n ) - * - * @return string representation of an Compound - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.lang.String - toString() - { - return atom_.toString() + "( " + Term.toString( args_ ) + " )"; - } - - public java.lang.String - debugString() - { - return - "(Compound " + - atom_.debugString() + " " + - Term.debugString( args_ ) + ")"; - } - - //------------------------------------------------------------------/ - // equals - /** - * Two Compounds are equal if their atoms are equal and their - * term arguments are equal. - * - * @param obj the Object to compare - * @return true if the Object satisfies the above condition - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - equals( Object obj ) - { - if ( this == obj ){ - return true; - } - - if ( ! (obj instanceof Compound) ){ - return false; - } - - return - atom_.equals( ((Compound)obj).atom_ ) && - Term.terms_equals( args_, ((Compound)obj).args_ ); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/Float.java b/Jpl/jsrc/10/jpl/Float.java deleted file mode 100755 index 565e9ac313..0000000000 --- a/Jpl/jsrc/10/jpl/Float.java +++ /dev/null @@ -1,234 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import jpl.fli.*; - -//----------------------------------------------------------------------/ -// Float -/** - * A Float is a Term with a double field. Use this class to create - * Java representation of Prolog floating point values: - *

- * Float f = new Float( 3.14159265 );
- * 
- * - * A Float can be used (and re-used) in Compound Terms. - * - *
- * Copyright (C) 1998 Fred Dushin

- * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

- * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

- *


- * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class Float -extends Term -{ - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the Float's value - */ - protected double value_; - - /** - * @return the Float's value - */ - public double - value() - { - return value_; - } - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - //------------------------------------------------------------------/ - // Float - /** - * This constructor creates a Float, initialized with the supplied - * value. - * - * @param value this Float's value - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Float( double value ) - { - this.value_ = value; - } - - //==================================================================/ - // Converting Terms to term_ts - //==================================================================/ - - //------------------------------------------------------------------/ - // put - /** - * To put an Float in a term, we put the value field into the - * term_t as a floet. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have packed in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param term A (previously created) term_t which is to be - * packed with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - put( Hashtable var_table, term_t term ) - { - Prolog.put_float( term, value_ ); - } - - - //==================================================================/ - // Converting term_ts to Terms - //==================================================================/ - - //------------------------------------------------------------------/ - // from_term_t - /** - * Converts a term_t to an Atom. Assuming the term is an - * atom, we just create a new Atom using the term's name. - * - * We are careful to create a List.Nil object if indeed the - * atom is "[]". Note that nil is an atom in Prolog and jpl. - * - * @param term The term_t to convert - * @return A new Atom - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static Term - from_term_t( Hashtable vars, term_t term ) - { - DoubleHolder double_holder = new DoubleHolder(); - - Prolog.get_float( term, double_holder ); - return new jpl.Float( double_holder.value ); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - - //------------------------------------------------------------------/ - // computeSubstitution - /** - * Nothing needs to be done if the Term is an Atom. - * - * @param table table holding Term substitutions, keyed on - * Variables. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - computeSubstitution( Hashtable bindings, Hashtable vars ) - { - } - - - - //------------------------------------------------------------------/ - // toString - /** - * Converts an Float to its String form -- its value. - * - * @return String representation of a Float - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.lang.String - toString() - { - return "" + value_ + ""; - } - - public java.lang.String - debugString() - { - return "(Float " + toString() + ")"; - } - - //------------------------------------------------------------------/ - // equals - /** - * Two Floats are equal if their values are equal - * - * @param obj The Object to compare - * @return true if the Object satisfies the above condition - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - equals( Object obj ) - { - if ( this == obj ){ - return true; - } - - if ( ! (obj instanceof Float) ){ - return false; - } - - return value_ == ((Float)obj).value_; - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/Integer.java b/Jpl/jsrc/10/jpl/Integer.java deleted file mode 100755 index 6e009c920f..0000000000 --- a/Jpl/jsrc/10/jpl/Integer.java +++ /dev/null @@ -1,230 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import jpl.fli.*; - -//----------------------------------------------------------------------/ -// Integer -/** - * An Integer is a Term with an int field. Use this class to create - * Java representation of Prolog integers: - *
- * Integer i = new Integer( 1024 );
- * 
- * - * An Integer can be used (and re-used) in Compound Terms. - * - *
- * Copyright (C) 1998 Fred Dushin

- * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

- * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

- *


- * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class Integer -extends Term -{ - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the Integer's value - */ - protected int value_; - - /** - * @return the Integer's value - */ - public final int - value() - { - return value_; - } - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - //------------------------------------------------------------------/ - // Integer - /** - * @param value This Integer's value - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Integer( int value ) - { - this.value_ = value; - } - - //==================================================================/ - // Converting Terms to term_ts - //==================================================================/ - - //------------------------------------------------------------------/ - // put - /** - * To put an Integer in a term, we put an integer. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have packed in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param term A (previously created) term_t which is to be - * packed with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - // Implementation notes: This method is over-ridden in each of - // the Term's subclasses, but it is always called from them, as well. - //------------------------------------------------------------------/ - protected final void - put( Hashtable var_table, term_t term ) - { - Prolog.put_integer( term, value_ ); - } - - - //==================================================================/ - // Converting term_ts to Terms - //==================================================================/ - - //------------------------------------------------------------------/ - // from_term_t - /** - * Converts a term_t to an Atom. Assuming the term is an - * atom, we just create a new Atom using the term's name. - * - * We are careful to create a List.Nil object if indeed the - * atom is "[]". Note that nil is an atom in Prolog and jpl. - * - * @param term The term_t to convert - * @return A new Atom - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static Term - from_term_t( Hashtable vars, term_t term ) - { - IntHolder int_holder = new IntHolder(); - - Prolog.get_integer( term, int_holder ); - return new jpl.Integer( int_holder.value ); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - - //------------------------------------------------------------------/ - // computeSubstitution - /** - * Nothing needs to be done if the Term is an Atom. - * - * @param table table holding Term substitutions, keyed on - * Variables. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - computeSubstitution( Hashtable bindings, Hashtable vars ) - { - } - - - - //------------------------------------------------------------------/ - // toString - /** - * Converts an Integer to its String form -- its value. - * - * @return String representation of an Integer - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.lang.String - toString() - { - return "" + value_ + ""; - } - - public java.lang.String - debugString() - { - return "(Integer " + toString() + ")"; - } - - //------------------------------------------------------------------/ - // equals - /** - * Two Integers are equal if their values are equal - * - * @param obj The Object to compare - * @return true if the Object satisfies the above condition - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - equals( Object obj ) - { - if ( this == obj ){ - return true; - } - - if ( ! (obj instanceof Integer) ){ - return false; - } - - return value_ == ((Integer)obj).value_; - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/JPL.java b/Jpl/jsrc/10/jpl/JPL.java deleted file mode 100755 index 2d15b44330..0000000000 --- a/Jpl/jsrc/10/jpl/JPL.java +++ /dev/null @@ -1,165 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import jpl.fli.Prolog; - - -//----------------------------------------------------------------------/ -// JPL -/** - * The JPL class contains initialization and termination methods for - * the High-Level interface. The Prolog engine must be initialized - * before any queries are made. - * - *
- * Copyright (C) 1998 Fred Dushin

- * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

- * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

- *


- * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class JPL -{ - protected static final boolean DEBUG = false; - private static boolean _initialized = false; - - //------------------------------------------------------------------/ - // init - /** - * Initializes the Prolog engine, using the String argument - * parameters passed. For parameter options, consult your local - * Prolog documentation. The parameter values are passed directly - * to initialization routines for the Prolog environment.

- * - * This method must be called before making any queries. - * - * @param argv Initialization parameter list - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static void - init( java.lang.String argv[] ) - { - if ( !_initialized ){ - Prolog.initialise( argv.length, argv ); - _initialized = true; - } - } - - //------------------------------------------------------------------/ - // init - /** - * Default initializor. Starts the engine with pl, the default - * Prolog command, with the initial goal to be "true" (eliminates - * that initial message). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static void - init() - { - java.lang.String argv[] = { "pl", "-g", "true" }; - init( argv ); - } - - //------------------------------------------------------------------/ - // halt - /** - * Terminates the Prolog session.

- * - * Note. This method calls the FLI halt() method with a - * status of 0, but the halt method currently is a no-op in SWI. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static void - halt() - { - Prolog.halt( 0 ); - } - - - // a static reference to the current Version - private static final Version version_ = new Version(); - - //------------------------------------------------------------------/ - // version - /** - * @return the running version of JPL. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Version - version() - { - return version_; - } - - //------------------------------------------------------------------/ - // version_string - /** - * @return the running version (in String form) of JPL. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static java.lang.String - version_string() - { - return - "JPL " + - version_.major + "." + - version_.minor + "." + - version_.patch + "-" + - version_.status; - } - - public static void - main( java.lang.String argv[] ) - { - System.out.println( version_string() ); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/JPLException.java b/Jpl/jsrc/10/jpl/JPLException.java deleted file mode 100755 index df07fb675e..0000000000 --- a/Jpl/jsrc/10/jpl/JPLException.java +++ /dev/null @@ -1,70 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - - - -//----------------------------------------------------------------------/ -// JPLException -/** - * This base class for JPL Exceptions is thrown from various methods - * in JPL. Consult the documentation for situations in which this - * method has occasion to be thrown. - *


- * Copyright (C) 1998 Fred Dushin

- * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

- * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

- *


- * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class -JPLException extends RuntimeException -{ - public - JPLException() - { - super(); - } - - public - JPLException( java.lang.String s ) - { - super( s ); - } -} diff --git a/Jpl/jsrc/10/jpl/List.java b/Jpl/jsrc/10/jpl/List.java deleted file mode 100755 index 2c73b3c73e..0000000000 --- a/Jpl/jsrc/10/jpl/List.java +++ /dev/null @@ -1,502 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -// ------------------------------------------------------------------------- -// $Id$ -//*****************************************************************************/ -package jpl; - - - -//----------------------------------------------------------------------/ -// List -/** - * A List is a Compound, but with just two args, a head and a tail. - * Use this class to create representations of Prolog lists: - *
- * List el = 
- *     new List(
- *         new Atom( "a" ),
- *         new List(
- *             new Atom( "b" ),
- *             new List(
- *                 new Atom( "c" ),
- *                 List.NIL ) ) );
- * 
- * This constructor (somewhat longwindedly) creates a List that - * corresponds to the Prolog list [a,b,c], or more accurately, - * [a|[b|[c|[]]]].

- * - * Note the following: - *

- *
  • The special Term (static instance) List.NIL is of type - * List.Nil, which extends Atom, not List. So the terminus - * of a List is an Atom, not a List. This is consistent - * with the Prolog representation.
  • - *
  • The List class provides 11 (convenience) list() methods for - * creating Listing without the long-windedness of the above - * constructor
  • - *
    - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class List -extends Compound -{ - /** - * @return the head of the List - */ - public final Term - head() - { - return args_[0]; - } - - - /** - * @return the tail of the List - */ - public final Term - tail() - { - return args_[1]; - } - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - // We only need one reference to this guy - private static final Atom DOT = new Atom( "." ); - - //------------------------------------------------------------------/ - // List - /** - * This constructor is used to create a List. Typically, the - * "last" item in a List is the List.NIL instance, or at least - * an instance of the List.Nil type, though as in Prolog, - * this need not necessarily be the case. Lists are therefore - * usually built "inside-out", or from the tail to the head, though - * you can also use any of the 11 factory list() methods for creating - * Lists if the elements of the List are known beforehand. - * - * @param head the List's head - * @param tail the List's tail - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - List( Term head, Term tail ) - { - super( DOT, Util.toTermArray( head, tail ) ); - } - - //==================================================================/ - // - //==================================================================/ - - //------------------------------------------------------------------/ - // tailIsNil - /** - * @return true if tail of this List is an instance of Nil; false o/w - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - tailIsNil() - { - return args_[1] instanceof Nil; - } - - //------------------------------------------------------------------/ - // toString - /** - * @return the String representation of this List. In this case, - * we use the simplest Prolog represenation [H|T]. For example, - * the list [a,b,c] is represented [a|[b|[c|[]]]]. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.lang.String - toString() - { - return "[" + args_[0] + " | " + args_[1] + "]"; - } - - public java.lang.String - debugString() - { - return "(List " + Term.debugString( args_ ) + ")"; - } - - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [] (i.e., the Atom List.NIL. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Atom - list() - { - return List.NIL; - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0 ) - { - return - new List( t0, list() ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1 ) - { - return - new List( t0, list( t1 ) ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1,t2,t3] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1, Term t2 ) - { - return - new List( t0, list( t1, t2 ) ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1,t2,t3] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1, Term t2, Term t3 ) - { - return - new List( t0, list( t1, t2, t3 ) ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1,t2,t3,t4] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1, Term t2, Term t3, Term t4 ) - { - return - new List( t0, list( t1, t2, t3, t4 ) ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1,t2,t3,t4,t5] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5 ) - { - return - new List( t0, list( t1, t2, t3, t4, t5 ) ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1,t2,t3,t4,t5,t6] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5, Term t6 ) - { - return - new List( t0, list( t1, t2, t3, t4, t5, - t6 ) ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1,t2,t3,t4,t5,t6,t7] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5, Term t6, Term t7 ) - { - return - new List( t0, list( t1, t2, t3, t4, t5, - t6, t7 ) ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1,t2,t3,t4,t5,t6,t7,t8] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5, Term t6, Term t7, Term t8 ) - { - return - new List( t0, list( t1, t2, t3, t4, t5, - t6, t7, t8 ) ); - } - - //------------------------------------------------------------------/ - // list - /** - * @return a jpl.List representing [t0,t1,t2,t3,t4,t5,t6,t7,t8,t9] - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static List - list( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5, Term t6, Term t7, Term t8, Term t9 ) - { - return - new List( t0, list( t1, t2, t3, t4, t5, - t6, t7, t8, t9 ) ); - } - - //------------------------------------------------------------------/ - // length - /** - * This method returns the length of a List. It assumes that - * the List is List.Nil terminated. - * - * @return the length of the List - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public int - length() - { - java.util.Enumeration e = elements(); - int i = 0; - - while ( e.hasMoreElements() ){ - e.nextElement(); - ++i; - } - return i; - } - - //------------------------------------------------------------------/ - // toTermArray - /** - * This method returns an array containg the Terms in - * the List. It assumes that the List is List.Nil terminated. - * - * @return a Term array containing the Terms in the List - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public Term[] - toTermArray() - { - Term[] terms = new Term[length()]; - java.util.Enumeration e = elements(); - - for ( int i = 0; e.hasMoreElements(); ++i ){ - terms[i] = (Term) e.nextElement(); - } - return terms; - } - - - //==================================================================/ - // Nil - /** - * The Nil class is used to terminate a List. - */ - // Implementation notes: NOTE: Nil is not a List! It would be - // nice if it was, but it's not a list in Prolog, either. - //==================================================================/ - public static class Nil - extends Atom - { - public - Nil() - { - super( "[]" ); - } - - } - public static final Atom NIL = new Nil(); - - //------------------------------------------------------------------/ - // - /** - * @return - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected boolean - nil_terminated() - { - List cons = this; - Term tail = cons.tail(); - - while ( tail instanceof List ){ - cons = (List) tail; - tail = cons.tail(); - } - - return cons.tailIsNil(); - } - - //==================================================================/ - // ListEnumerator - /** - * A ListEnumerator enumerates the elements of a List. Note that - * trying to construct one of these on a List that is not nil-terminated - * will cause a JPLException to be thrown - */ - // Implementation notes: - // - //==================================================================/ - private class ListEnumerator - implements java.util.Enumeration - { - private List cons_ = List.this; - - protected - ListEnumerator() - { - if ( !nil_terminated() ){ - throw new JPLException( "List is not a nil-terminated List" ); - } - } - - public boolean - hasMoreElements() - { - return cons_ != null; - } - - public Object - nextElement() - { - Term ret = cons_.head(); - Term tail = cons_.tail(); - - if ( tail instanceof List ){ - cons_ = (List)tail; - } else { - cons_ = null; - } - - return ret; - } - } - - //------------------------------------------------------------------/ - // elements - /** - * This method return an enumeration of a nil-terminated List. - * Calling this method on a List whose last cdr is not an instance of - * List.Nil will cause a JPLException to be thrown. - * - * @return A java.util.Enumeration of all the elements of the List - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.util.Enumeration - elements() - { - return new ListEnumerator(); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/Long.java b/Jpl/jsrc/10/jpl/Long.java deleted file mode 100755 index 6c9f20386e..0000000000 --- a/Jpl/jsrc/10/jpl/Long.java +++ /dev/null @@ -1,236 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import jpl.fli.*; - -//----------------------------------------------------------------------/ -// Integer -/** - * A Long is a Term with an int field. Use this class to create - * Java representation of Prolog longs: - *
    - * Long i = new Long( 1024 );
    - * 
    - * - * A Long can be used (and re-used) in Compound Terms. Note that since - * the long type has a non-standard size in Prolog, it is impossible to - * use Java longs as values and maintain portability, so we just use - * int values, which covers the currently supported implementations. - * This class, therefore, currently provides no more functionality than - * the Integer class. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - * @see jpl.Integer - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class Long -extends Term -{ - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * This Long's value - */ - protected int value_; - - /** - * @return the Long's value - */ - public final int - value() - { - return value_; - } - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - //------------------------------------------------------------------/ - // Long - /** - * @param value This Long's value - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Long( int value ) - { - this.value_ = value; - } - - //==================================================================/ - // Converting Terms to term_ts - //==================================================================/ - - //------------------------------------------------------------------/ - // put - /** - * To put an Long in a term, we put an integer. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have packed in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param term A (previously created) term_t which is to be - * packed with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - // Implementation notes: This method is over-ridden in each of - // the Term's subclasses, but it is always called from them, as well. - //------------------------------------------------------------------/ - protected final void - put( Hashtable var_table, term_t term ) - { - Prolog.put_integer( term, value_ ); - } - - - //==================================================================/ - // Converting term_ts to Terms - //==================================================================/ - - //------------------------------------------------------------------/ - // from_term_t - /** - * Converts a term_t to an Atom. Assuming the term is an - * atom, we just create a new Atom using the term's name. - * - * We are careful to create a List.Nil object if indeed the - * atom is "[]". Note that nil is an atom in Prolog and jpl. - * - * @param term The term_t to convert - * @return A new Atom - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static Term - from_term_t( Hashtable vars, term_t term ) - { - LongHolder long_holder = new LongHolder(); - - Prolog.get_long( term, long_holder ); - return new jpl.Long( (int)long_holder.value ); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - - //------------------------------------------------------------------/ - // computeSubstitution - /** - * Nothing needs to be done if the Term is an Atom. - * - * @param table table holding Term substitutions, keyed on - * Variables. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - computeSubstitution( Hashtable bindings, Hashtable vars ) - { - } - - - - //------------------------------------------------------------------/ - // toString - /** - * Converts a Long to its String form -- its value. - * - * @return String representation of a Long - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.lang.String - toString() - { - return "" + value_ + ""; - } - - public java.lang.String - debugString() - { - return "(Long " + toString() + ")"; - } - - //------------------------------------------------------------------/ - // equals - /** - * Two Longs are equal if their values are equal - * - * @param obj The Object to compare - * @return true if the Object satisfies the above condition - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - equals( Object obj ) - { - if ( this == obj ){ - return true; - } - - if ( ! (obj instanceof Long) ){ - return false; - } - - return value_ == ((Long)obj).value_; - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/PrologException.java b/Jpl/jsrc/10/jpl/PrologException.java deleted file mode 100755 index cae804a20d..0000000000 --- a/Jpl/jsrc/10/jpl/PrologException.java +++ /dev/null @@ -1,83 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - - - -//----------------------------------------------------------------------/ -// PrologException -/** - * An exception of this type is thrown if, in evaluating a Query, - * an exception is thrown in Prolog via the Prolog throw/1 predicate. - *

    - * This method provides High-Level interface programmers to handle - * such exceptions, providing error management between Prolog and Java. - *

    - * Use the exception_term() accessor to obtain the Term that was - * thrown via the throw/1 Prolog predicate. - * - *


    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public final class -PrologException extends JPLException -{ - private Term term_ = null; - - protected - PrologException( Term term ) - { - super( "PrologException: " + term.toString() ); - - this.term_ = term; - } - - /** - * @return a reference to the Term thrown by the call to throw/1 - */ - public Term - term() - { - return this.term_; - } -} diff --git a/Jpl/jsrc/10/jpl/Query.java b/Jpl/jsrc/10/jpl/Query.java deleted file mode 100755 index 216246ea6d..0000000000 --- a/Jpl/jsrc/10/jpl/Query.java +++ /dev/null @@ -1,1189 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import jpl.fli.*; - - -//----------------------------------------------------------------------/ -// Query -/** - * A Query is an Object used to query the Prolog engine. It consists of - * an Atom (corresponding to the name of the predicate being queried) - * and a list (array) of Terms, the arguments to the predicate.

    - * - * The Query class implements the Enumeration interface, and it is - * through this interface that one obtains solutions. The Enumeration - * hasMoreElements() method returns true if the goal succeeded (false, - * o/w), and if the goal did succeed, the nextElement() method returns - * a Hashtable representing variable bindings; the elements in the - * Hashtable are Terms, indexed by the Variables to which they are bound. - * For example, if p(a) and p(b) are facts in the Prolog - * database, then the following is equivalent to printing all - * the solutions to the Prolog query p(X): - * - *

    - * Variable X = new Variable();
    - * Term arg[] = { X };
    - * Query    q = new Query( "p", arg );
    - * 
    - * while ( q.hasMoreElements() ){
    - *     Term bound_to_x = ((Hashtable)q.nextElement()).get( X );
    - *     System.out.println( bound_to_x );
    - * }
    - * 
    - * - * Make sure to rewind the Query if you have not asked for all - * its solutions. To obtain just one solution from a Query, - * use the oneSolution() method. - * To obtain all solutions, use the allSolutions() method. Use the - * query() method if the Query is a ground query. - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class -Query implements Enumeration -{ - - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * This static reference is used to synchronize calls to the - * Low-Level Interface so that only one query can be active - * at a time. Note that the hasMoreSolutuons, nextSolution, - * rewind, allSolutuons, and oneSolution method bodies are - * synchronized on this object reference, which, after initialization, - * is the Class object for the jpl.fli.Prolog class. - */ - private static Object lock_ = null; - - static { - try { - lock_ = Class.forName( "jpl.fli.Prolog" ); - } catch ( ClassNotFoundException cnfe ){ - throw new JPLException( "Query static initializer: Could not find jpl.Prolog class" ); - } - } - - //------------------------------------------------------------------/ - // lock - /** - * Use this method to obtain the lock that is used to synchronize - * all calls to the Low-Level Interface. You should use this - * lock i) if you are using the hasMoreSolutions() and nextSolution() - * methods to enumerate the solutions to a Query, and ii) you need - * these calls to be thread-safe. Example: - *
    -	 * Query query = // get a query somehow
    -	 * synchronized ( jpl.Query.lock() ){
    -	 *     while ( query.hasMoreElements() ){
    -	 *          Hashtable solution = query.nextSolution();
    -	 *          // process solution...
    -	 *     }
    -	 * }
    -	 * 
    - * The lock so acquired is the same lock used internally by - * hasMoreSolutions and nextSolution methods; indeed, it is - * the Class Object for the jpl.fli.Prolog class, so any calls - * to the Low-Level Interface will be blocked, as well. However, - * you should not intermix calls to the Low-Level Interface when using - * the High-Level Interface. - * - * @return the lock on any calls to the FLI - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Object - lock() - { - return lock_; - } - - - /** - * the Atom corresponding to the predicate name in this Query - */ - protected Atom atom_ = null; - /** - * the arguments to this Query - */ - protected Term args_[] = null; - - /** - * @return the Atom corresponding to the predicate name in this Query - */ - public final Atom - atom() - { - return atom_; - } - - /** - * @return the arguments to this Query - */ - public final Term[] - args() - { - return args_; - } - - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - //------------------------------------------------------------------/ - // Query - /** - * This constructor creates a Query object corresponding to a - * Prolog query. The predicate name is determined by the pred_atom - * parameter, and the arguments are given by the arg parameter.

    - * - * NB. Creating an instance of the Query class does not - * result in a call to the Prolog Abstract Machine. - * - * @param atom an Atom that names the predicate in this Query - * @param args the arguments to this Query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( Atom atom, Term args[] ) - { - this.atom_ = atom; - this.args_ = args; - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *

    -	 * new Query( new Atom( name ), arg )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param args the arguments to this Query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( java.lang.String name, Term args[] ) - { - this( new Atom( name ), args ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query(
    -	 *     new Atom( name ),
    -	 *     Util.toTermArray( t0 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0 ) - { - this( - new Atom( name ), - Util.toTermArray( t0 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1, t2 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1, - Term t2 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1, t2, t3 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5, t6 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5, t6, t7 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5, t6, t7, t8 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - * @param t8 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7, - Term t8 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7, t8 ) ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( 
    -	 *     new Atom( name ), 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5, t6, t7, t8, t9 ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - * @param t8 a jpl.Term - * @param t9 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( - java.lang.String name, - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7, - Term t8, - Term t9 ) - { - this( - new Atom( name ), - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7, t8, t9 ) ); - } - - // for use in following constructor - private static final Term[] EMPTY_TERM_ARRAY = new Term[0]; - - //------------------------------------------------------------------/ - // Query - /** - * This constructor creates a Prolog query with no arguments - * (a "proposition" or "sentence"). - * - * @param atom an Atom that names the predicate in this Query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( Atom atom ) - { - this( atom, EMPTY_TERM_ARRAY ); - } - - //------------------------------------------------------------------/ - // Query - /** - * This constructor is shorthand for - *
    -	 * new Query( new Atom( name ) )
    -	 * 
    - * - * @param name the name of the predicate in this Query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Query( java.lang.String name ) - { - this( new Atom( name ) ); - } - - - //==================================================================/ - // Making Prolog Queries - //==================================================================/ - - //------------------------------------------------------------------/ - // create_predicate_t - /** - * @return A predicate_t object for making Prolog queries - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - private predicate_t - create_predicate_t() - { - return Prolog.predicate( atom_.name_, args_.length, null ); - } - - //------------------------------------------------------------------/ - // create_term_ts - /** - * @return A term_t object for making Prolog queries - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - private term_t - create_term_ts() - { - return Term.terms_to_term_ts( new Hashtable(), args_ ); - } - - /** - * These variables are used and set across the hasMoreElements - * and nextElement Enumeration interface implementation - */ - private boolean querying = false; - private qid_t qid; - private predicate_t predicate; - private term_t term0; - private static Query querying_query = null; - - - //------------------------------------------------------------------/ - // hasMoreSolutions - /** - * This method returns true if making a Prolog Query using this - * Object's Atom and Terms succeeds. It is designed to be used in - * conjunction with the nextSolution() method to retrieve one or - * more substitutions in the form of Hashtables. To iterate through - * all the solutions to a Query, for example, one might write - *
    -	 * Query q = // obtain Query reference
    -	 * while ( q.hasMoreSolutions() ){
    -	 *     Hashtable solution = q.nextSolution();
    -	 *     // process solution...
    -	 * }
    -	 * 
    - * To ensure thread-safety, you should wrap sequential calls to - * this method in a synchronized block, using the static - * lock method to obtain the monitor. - *
    -	 * Query q = // obtain Query reference
    -	 * synchronized ( jpl.Query.lock() ){
    -	 *     while ( q.hasMoreElements() ){
    -	 *          Hashtable solution = q.nextSolution();
    -	 *          // process solution...
    -	 *     }
    -	 * }
    -	 * 
    - *

    - * If this method is called while another is in progress, a - * QueryInProgressException will be thrown with the currently - * executing Query. - * - * @return true if the Prolog query succeeds; false, o/w. - * - * @see jpl.Query#lock - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean hasMoreSolutions(){ - return hasMoreSolutions(Prolog.Q_NORMAL); - } - - - public final boolean - hasMoreSolutions(int openMode) - { - synchronized ( lock_ ){ - // - // Check to see if anyone is doing a query; if there is another - // query in process and it is not us, then - // throw a QueryInProgressException - // - if ( querying_query != null && querying_query != this ){ - throw new QueryInProgressException( querying_query ); - } - querying_query = this; - - // - // If we are not already querying, open a query through the FLI - // - if ( !querying ){ - predicate = create_predicate_t(); - term0 = create_term_ts(); - qid = Prolog.open_query( null, openMode, predicate, term0 ); - - querying = true; // for subsequent calls by this - querying_query = this; // for calls by any other Query object - } - - // - // Get the next solution; if it's false, close the query; - // otherwise, keep it open for subsequent calls to this method. - // - int rval = Prolog.next_solution( qid ); - if ( rval == 0 ){ - - // Check to see if the reason for failure was - // as a result of a call to throw/1. If so, build - // the exception term now. - term_t exception_term_t = Prolog.exception( qid ); - Term exception_term = null; - if ( exception_term_t.value != 0L ){ - exception_term = - Term.from_term_t( - new Hashtable(), - exception_term_t ); - } - - // in any event, close the query - Prolog.close_query( qid ); - querying = false; // so we can start this Query again - querying_query = null; // so that someone else can Query - - // if an exception was thrown in Prolog, throw - // a PrologException in Java - if ( exception_term_t.value != 0L ){ - throw new PrologException( exception_term ); - } - } - // return the value of the call to prolog - return rval != 0 ? true : false; - } - } - - //------------------------------------------------------------------/ - // nextSolution - /** - * This method returns a java.util.Hashtable, which represents - * a substitution of Terms for Variables in the Term list in this - * Query. The Hashtable contains instances of Terms, keyed on - * Variable instances in the Term list. - *

    - * For example, if a Query has an occurrence of a jpl.Variable, - * say, named X, one can obtain the Term bound to X in the solution - * by looking up X in the Hashtable. - *

    -	 * Variable X = new Variable();
    -	 * Query q = // obtain Query reference (with X in the Term array)
    -	 * while ( q.hasMoreSolutions() ){
    -	 *     Hashtable solution = q.nextSolution();
    -	 *     // make t the Term bound to X in the solution
    -	 *     Term t = (Term)solution.get( X );
    -	 *     // ...
    -	 * }
    -	 * 
    - * Programmers should obey the following rules when using this method. - * - *
  • The nextSolution() method should only be called after the - * hasMoreSolutions() method returns true; otherwise a JPLException - * will be raised, indicating that no Query is in progress. - *
  • The nextSolution() and hasMoreSolutions() should be called - * in the same thread of execution, at least for a given Query - * instance. - *
  • The nextSolution() method should not be called while - * another Thread is in the process of evaluating a Query. The - * JPL High-Level interface is designed to be thread safe, and - * is thread-safe as long as the previous two rules are obeyed. - *
  • - * - * This method will throw a JPLException if no query is in progress. - * It will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * - * @return A Hashtable representing a substitution. - * - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final Hashtable - nextSolution() - { - synchronized ( lock_ ){ - if ( !querying ){ - throw new JPLException( "No Query is in process" ); - } - - // - // Check to see if anyone is doing a query; if there is another - // query in process and it is not us (denoted by the qid), then - // this is a user error and throw a runtime exception. Otherwise, - // either a query is not in process, or it is and we are the ones - // doing it, so get the next element. - // - if ( querying_query != null && querying_query != this ){ - throw new QueryInProgressException( querying_query ); - } else { - Hashtable substitution = new Hashtable(); - Term.computeSubstitutions( substitution, new Hashtable(), args_ ); - return substitution; - } - } - } - - - //------------------------------------------------------------------/ - // hasMoreElements - /** - * This method is completes the java.util.Enumeration - * interface. It is a wrapper for hasMoreSolutions. - * - * @return true if the Prolog query succeeds; false, o/w. - * - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - hasMoreElements() - { - return hasMoreSolutions(); - } - /** - * @deprecated Substitution too hard to spell; use *Solution* instead. - */ - public final boolean - hasMoreSubstitutions() - { - return hasMoreSolutions(); - } - - //------------------------------------------------------------------/ - // nextElement - /** - * This method is completes the java.util.Enumeration - * interface. It is a wrapper for nextSolution. - *

    - * This method will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * - * @return A Hashtable representing a substitution. - * - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final Object - nextElement() - { - return nextSolution(); - } - /** - * @deprecated Substitution too hard to spell; use *Solution* instead. - */ - public final Hashtable - nextSubstitution() - { - return nextSolution(); - } - - //------------------------------------------------------------------/ - // rewind - /** - * This method is used to rewind the query so that the query - * may be re-run, even if the Query qua Enumeration has more - * elements. Calling rewind() on an exhausted Enumeration has - * no effect.

    - * - * Here is a way to get the first 3 solutions to a Query, - * while subsequently being able to use the same Query object to - * obtain new solutions: - *

    -	 * Query q = new Query( predicate, args );
    -	 * int i = 0;
    -	 * for ( int i = 0; i < 3 && q.hasMoreSolutions();  ++i ){
    -	 *     Hasthable sub = (Hashtable) q.nextSolution();
    -	 *     ...
    -	 * }
    -	 * q.rewind();
    -	 * 

    - * - * This method will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * It is safe to call this method if no query is in progress. - * - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final void - rewind() - { - synchronized ( lock_ ){ - // - // Check to see if anyone is doing a query; if there is another - // query in process and it is not us (denoted by the qid), then - // - // - if ( querying ){ - if ( querying_query != null && querying_query != this ){ - // this should never happen; if the state of a - // Query is querying, then it is the only query in progress - // throw a QueryInProgressException - throw new QueryInProgressException( querying_query ); - } else { - Prolog.close_query( qid ); - querying = false; // so we can start this Query again - querying_query = null; // so other Queries can start - } - } - } - } - - //------------------------------------------------------------------/ - // allSolutions - /** - * @return an array of Hashtables, each of which is a solution - * (in order) of the Query. If the return value is null, this - * means the Query has no solutions.

    - * - * This method will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final Hashtable[] - allSolutions() - { - synchronized ( lock_ ){ - rewind(); - - Hashtable solutions[] = null; - Vector v = new Vector(); - - while ( hasMoreSolutions() ){ - v.addElement( nextSolution() ); - } - - // otherwise, turn the Vector to an array - int n = v.size(); - // choke if there were no solutions - if ( n == 0 ){ - return null; - } - solutions = new Hashtable[n]; - v.copyInto( solutions ); - - return solutions; - } - } - - //------------------------------------------------------------------/ - // oneSolution - /** - * @return one solution, if it has one. If the return value is - * null, this means that the Query has no solutions; otherwise, - * the solution will be a (possibly empty) Hashtable.

    - * - * This method will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final Hashtable - oneSolution() - { - synchronized ( lock_ ){ - Hashtable solution = null; - - rewind(); - if ( hasMoreSolutions() ){ - solution = nextSolution(); - } - rewind(); - - return solution; - } - } - - //------------------------------------------------------------------/ - // query - /** - * @return the value of the Query.

    - * - * This method should only be called for ground queries, since - * the results of any bindings are discarded. - *

    - * This method will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - query() - { - return oneSolution() != null; - } - - //------------------------------------------------------------------/ - // printSolution - /** - * Prints a substitution to stdout. For testing. - * - * @param substitution The substitution to print. - * @deprecated use Util.toString instead. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static void - printSolution( Hashtable substitution ) - { - Enumeration vars = substitution.keys(); - - System.out.println( "Substitutions: " ); - while ( vars.hasMoreElements() ){ - Variable var = (Variable) vars.nextElement(); - System.out.print( var + " = " ); - System.out.println( substitution.get( var ) ); - } - } - /** - * @deprecated use Util.toString instead. - */ - public static void - printSubstitution( Hashtable substitution ) - { - printSolution( substitution ); - } - - //==================================================================/ - // misc - //==================================================================/ - - - //------------------------------------------------------------------/ - // toString - /** - * Returns the String representation of a Query. - * - * @return the String representation of a Query - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.lang.String - toString() - { - return atom_.toString() + "( " + Term.toString( args_ ) + " )"; - } - - public java.lang.String - debugString() - { - return - "(Query " + - atom_.debugString() + " " + - Term.debugString( args_ ) + ")"; - } - - //------------------------------------------------------------------/ - // print_internal_rep - /** - * For debugging... - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - private void - print_internal_rep( predicate_t predicate, term_t term0 ) - { - atom_t atom = new atom_t(); - IntHolder arity = new IntHolder(); - System.err.print( "got: " ); - Prolog.predicate_info( predicate, atom, arity, new module_t() ); - - System.err.print( atom.toString() + "( " ); - System.err.print( term_t.toString( arity.value, term0 ) +" )" ); - System.err.println(); - } -} diff --git a/Jpl/jsrc/10/jpl/QueryInProgressException.java b/Jpl/jsrc/10/jpl/QueryInProgressException.java deleted file mode 100755 index 5e92509f0f..0000000000 --- a/Jpl/jsrc/10/jpl/QueryInProgressException.java +++ /dev/null @@ -1,104 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - - - -//----------------------------------------------------------------------/ -// QueryInProgressException -/** - * An exception of this type is thrown if a Query is made while - * another Query is in progress, for example, if the JPL programmer - * has negglected to close a query by exhausting all solutions or by failing - * to rweind() a Query, or in multi-threaded situations. - *

    - * To prevent this kind of exception from being thrown, first make - * absolutely sure that all Queries are being closed properly, either - * by exhausting all solutions in a Query (i.e., hasMoreSolutions() - * returns false), or by explicitly calling rewind(). If your program - * involves multi-threading, make sure you obtain the lock from the - * Query object before entering a hasMoreSolutions()/nextSolution loop: - *

    - * Query query = // get a query somehow
    - * synchronized ( jpl.Query.lock() ){
    - *     while ( query.hasMoreElements() ){
    - *          Hashtable solution = query.nextSolution();
    - *          // process solution...
    - *     }
    - * }
    - * 
    - * Note: In most situations such care is not necessary, since - * the Query.query(), Query,oneSolution(), and Query.allSolutions() - * methods are thread-safe. However, users may have reason - * to use the hasMoreSolutions() and nextSolutions() methods, which, - * while synchronized, do allow Queries to be opened between calls to - * these methods. - *

    - * If you catch this Exception, you can usese the query() accessor to - * obtain a reference to the Query that is in progress. - * - *


    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public final class -QueryInProgressException extends JPLException -{ - private Query query_ = null; - - protected - QueryInProgressException( Query query ) - { - super( "QueryInProgressException: Query in progress=" + query.toString() ); - - this.query_ = query; - } - - /** - * @return a reference to the Query that is in progress - */ - public final Query - query() - { - return this.query_; - } -} diff --git a/Jpl/jsrc/10/jpl/String.java b/Jpl/jsrc/10/jpl/String.java deleted file mode 100755 index bca8b17d29..0000000000 --- a/Jpl/jsrc/10/jpl/String.java +++ /dev/null @@ -1,226 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -// ------------------------------------------------------------------------- -// $Id$ -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import jpl.fli.*; - -//----------------------------------------------------------------------/ -// String -/** - * A String is a Term with a java.lang.String value. Use this - * class to represent Prolog strings. - *
    - * jpl.String s = new jpl.String( "Haddock's Eyes" );
    - * 
    - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class String -extends Term -{ - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the String's value - */ - java.lang.String value_ = null; - - /** - * @return the String's value - */ - public final java.lang.String - value() - { - return value_; - } - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - //------------------------------------------------------------------/ - // String - /** - * A String holds a java.lang.String and represents a Prolog String, - * whose internal representation may vary across Prolog implementations. - * - * @param value the java.lang.String value of this String. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - String( java.lang.String value ) - { - this.value_ = value; - } - - //==================================================================/ - // Converting Terms to term_ts - //==================================================================/ - - //------------------------------------------------------------------/ - // put - /** - * To put an String in a term, we put the characters of the - * String into the term_t. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have packed in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param term A (previously created) term_t which is to be - * packed with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - put( Hashtable var_table, term_t term ) - { - Prolog.put_string_chars( term, value_ ); - } - - - //==================================================================/ - // Converting term_ts to Terms - //==================================================================/ - - //------------------------------------------------------------------/ - // from_term_t - /** - * Converts a term_t to a String. Assuming the term is an - * Prolog String, we just create a new String using the - * characters in the Prolog String. - * - * @param term The term_t to convert - * @return A new String - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static Term - from_term_t( Hashtable vars, term_t term ) - { - StringHolder holder = new StringHolder(); - Prolog.get_string( term, holder ); - - return new String( holder.value ); - } - - - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - - //------------------------------------------------------------------/ - // computeSubstitution - /** - * Nothing needs to be done if the Term is an Atom. - * - * @param table table holding Term substitutions, keyed on - * Variables. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - computeSubstitution( Hashtable bindings, Hashtable vars ) - { - } - - - //==================================================================/ - // - //==================================================================/ - - - public java.lang.String - toString() - { - return value_; - } - - public java.lang.String - debugString() - { - return "(String " + toString() + ")"; - } - - - //------------------------------------------------------------------/ - // equals - /** - * Two Strings are equal if their values are equal - * - * @param obj The Object to compare - * @return true if the Object satisfies the above condition - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - equals( Object obj ) - { - if ( this == obj ){ - return true; - } - - if ( ! (obj instanceof String) ){ - return false; - } - - return value_.equals( ((String)obj).value_ ); - }} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/Term.java b/Jpl/jsrc/10/jpl/Term.java deleted file mode 100755 index 01025678aa..0000000000 --- a/Jpl/jsrc/10/jpl/Term.java +++ /dev/null @@ -1,469 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import jpl.fli.*; - - -//----------------------------------------------------------------------/ -// Term -/** - * A Term is a base class for the many different kinds of Term - * (Atom, Variable, Compound, etc.). Programmers do not create - * instances of Term classes directly; rather, they should create - * instances of Term subclasses (Atom, Variable, Compound, etc.), - * which will inherit functionality from this class. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public abstract class Term -{ - //==================================================================/ - // Attributes - //==================================================================/ - - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - //------------------------------------------------------------------/ - // Term - /** - * This default constructor is provided in order for subclasses - * to be able to define their own default constructors. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected - Term() - { - } - - - //==================================================================/ - // Converting Terms to term_ts - // - // To convert a Term to a term_t, we need to traverse the Term - // structure and build a corresponding Prolog term_t object. - // There are some issues: - // - // - Prolog term_ts rely on the *consecutive* nature of term_t - // references. In particular, to build a compound structure - // in the Prolog FLI, one must *first* determine the arity of the - // compound, create a *sequence* of term_t references, and then - // put atoms, functors, etc. into those term references. We - // do this in these methods first determinint the arity of the - // Compound, and then by "puting" a type into a term_t. - // The "put" methd is defined differently for each Term subclass. - // - // - What if we are trying to make a term_t from a Term, but the - // Term has multiple instances of the same Variable? We want - // to ensure that one Prolog variable will be created, or else - // queries will give incorrect answers. We thus pass a Hashtable - // (var_table) through these methods. The table contains term_t - // instances, keyed on Variable instances. - //==================================================================/ - - //------------------------------------------------------------------/ - // put - /** - * Cache the reference to the Prolog term_t here. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have been put in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param term A (previously created) term_t which is to be - * put with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - // Implementation notes: This method is over-ridden in each of - // the Term's subclasses, but it is always called from them, as well. - //------------------------------------------------------------------/ - protected abstract void - put( Hashtable var_table, term_t term ); - - - //------------------------------------------------------------------/ - // terms_to_term_ts - /** - * This static method converts an array of Terms to a *consecutive* - * sequence of term_t objects. Note that the first term_t object - * returned is a term_t class (structure); the succeeding term_t - * objects are consecutive references obtained by incrementing the - * *value* field of the term_t. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have be put in in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param arg An array of jpl.Term references. - * @return consecutive term_t references (first of which is - * a structure) - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static term_t - terms_to_term_ts( Hashtable var_table, Term arg[] ) - { - // - // first create a sequence of term_ts. The 0th term_t - // will be a jpl.fli.term_t. Successive Prolog term_t - // references will reside in the Prolog engine, and - // can be obtained by term0.value+i. - // - term_t term0 = Prolog.new_term_refs( arg.length ); - - // - // for each new term reference, construct a prolog term - // by puting an appropriate Prolog type into the reference. - // This is more or less the protocol for building terms in - // Prolog. - // - long ith_term_t = term0.value; - for ( int i = 0; i < arg.length; ++i, ++ith_term_t ){ - term_t term = new term_t(); - term.value = ith_term_t; - arg[i].put( var_table, term ); - } - - return term0; - } - - //==================================================================/ - // Converting term_ts to Terms - // - // Converting back to Terms from term_ts is complex; one - // issue is that there is not as much type information in a - // term_t as one would expect. We can learn that a term_t - // is a compund term, but not, for example, that it is a list - // or a tuple. In this case, we must inspect the name of the - // term_t ("." = list; "," = tuple). - // - // Another problem concerns variable bindings. We illustrate - // with several examples. First, consider the prolog fact - // - // p( f( X, X ) ). - // - // And the query ?- p( Y ). A solution should be y = f( X, X ), - // and indeed, if this query is run, the term_t to which Y will - // be unified is a compound, f( X, X ). The problem is, how do - // we know, in converting the term_ts to Terms in the compound f - // whether we should create one Variable or two? This begs the - // question, how do we _identify_ Variables in JPL? The answer - // to the latter question is, by reference; two Variable (java) - // references refer to the same variable iff they are, in memory, - // the same Variable. That is, they satisfy the Java == relation. - // (Note that this condition is _not_ true of the other Term types.) - // - // Given this design decision, therefore, we should create a - // single Variable instance and a Compound instance whose 2 arg - // values point to the same Variable. We therefore need to keep - // track, in converting a term_t to a Term (in particular, in - // converting a term_t whose type is variable to a Variable), of - // which Variables have been created. We do this by using the vars - // Hashtable, which gets passed recursively though the from_term_t - // methods; this table holds the Variable instances that have been - // created, keyed by the unique and internal-to-Prolog string - // representation of the variable. - //==================================================================/ - - //------------------------------------------------------------------/ - // from_term_t - /** - * This method calls from_term_t on each term in the consecutive list - * of term_ts. A temporary jpl.term_t structure must be created - * in order to extract type information from the Prolog engine. - * - * @param vars A Hashtable containing jpl.Variable instances - * as elements, indexed by their *Prolog* names, which are guaranteed - * to be unique. Cf. the from_term_t method of the Variable class. - * @param n The number of consecutive term_ts - * @param term0 The 0th term_t (structure); subsequent - * term_ts are not structures. - * @return An array of converted Terms - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static Term[] - from_term_t( Hashtable vars, int n, term_t term0 ) - { - // create an array on n term references - Term rval[] = new Term[n]; - - // - // for each term_t (from 0...n-1), create a term_t - // (temporary) structure and dispatch the translation - // to a Term to the static from_term_t method of the Term - // class. This will perform (Prolog) type analysis on the - // term_t and call the appropriate static method to create - // a Term of the right type (e.g., Atom, Variable, List, etc.) - // - long ith_term_t = term0.value; - for ( int i = 0; i < n; ++i, ++ith_term_t ){ - term_t term = new term_t(); - term.value = ith_term_t; - - rval[i] = Term.from_term_t( vars, term ); - } - - return rval; - } - - //------------------------------------------------------------------/ - // from_term_t - /** - * We do some type analysis on the term_t then forward the - * call to the appropriate class - * - * @param vars A Hashtable containing jpl.Variable instances - * as elements, indexed by their *Prolog* names, which are guaranteed - * to be unique. Cf. the from_term_t method of the Variable class. - * @param term The term_t to convert - * @return The converted class. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static Term - from_term_t( Hashtable vars, term_t term ) - { - int type = Prolog.term_type( term ); - - switch( type ){ - case Prolog.VARIABLE: - return Variable.from_term_t( vars, term ); - case Prolog.ATOM: - return Atom.from_term_t( vars, term ); - case Prolog.INTEGER: - return Integer.from_term_t( vars, term ); - case Prolog.FLOAT: - return Float.from_term_t( vars, term ); - case Prolog.STRING: - return String.from_term_t( vars, term ); - case Prolog.TERM: - return Compound.from_term_t( vars, term ); - default: - System.err.println( "Term.from_term_t: unknown term type" ); - return null; - } - } - - //==================================================================/ - // Computing Substitutions - // - // Once a solution has been found, the Prolog term_t references - // will have been unified and will refer to new terms. To compute - // a substitution, we traverse the (original) Term structure, looking - // at the term_t reference in the Term. The only case we really care - // about is if the (original) Term is a Variable; if so, the term_t - // back in the Prolog engine contains the unified term. In this case, - // we can store this term in a Hashtable, keyed by the Variable with - // which the term was unified. - //==================================================================/ - - - //------------------------------------------------------------------/ - // computeSubstitution - /** - * This method computes a substitution from a Term. The bindings - * Hashtable stores Terms, keyed by Variables. Thus, a - * substitution is as it is in mathematical logic, a sequence - * of the form \sigma = {t_0/x_0, ..., t_n/x_n}. Once the - * substitution is computed, the substitution should satisfy - * - * \sigma T = t - * - * where T is the Term from which the substitution is computed, - * and t is the term_t which results from the Prolog query.

    - * - * A second Hashtable, vars, is required; this table holds - * the Variables that occur (thus far) in the unified term. - * The Variable instances in this table are guaranteed to be - * unique and are keyed on Strings which are Prolog internal - * representations of the variables. - * - * @param bingings table holding Term substitutions, keyed on - * Variables. - * @param vars A Hashtable holding the Variables that occur - * thus far in the term; keyed by internal (Prolog) string rep. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected abstract void - computeSubstitution( Hashtable bindings, Hashtable vars ); - - //------------------------------------------------------------------/ - // computeSubstitutions - /** - * Just calls computeSubstitution in each Term in the list. - * - * @param table table holding Term substitutions, keyed on - * Variables. - * @param arg a list of Terms - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static void - computeSubstitutions( Hashtable bindings, Hashtable vars, Term arg[] ) - { - for ( int i = 0; i < arg.length; ++i ){ - arg[i].computeSubstitution( bindings, vars ); - } - } - - //------------------------------------------------------------------/ - // terms_equals - /** - * This method is used to determine the Terms in two Term arrays - * are pairwise equal, where two Terms are equal if they satisfy - * the equals predicate (defined differently in each Term subclass). - * - * @param t1 an array of Terms - * @param t2 an array of Terms - * @return true if all of the Terms in the arrays are pairwise equal - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected static boolean - terms_equals( Term[] t1, Term[] t2 ) - { - if ( t1.length != t2.length ){ - return false; - } - - for ( int i = 0; i < t1.length; ++i ){ - if ( !t1[i].equals( t2[i] ) ){ - return false; - } - } - return true; - } - -// //------------------------------------------------------------------/ -// // equals -// /** -// * Terms (Variables, actually) are keys in Hashtables. This -// * method overrides the Object implementation so that -// * -// * @param obj The Object to compare. -// * @return true if the Object is the same as this or if -// * the Object's term_t is equal to this's. -// */ -// // Implementation notes: I'm not sure if this is needed any more... -// // -// //------------------------------------------------------------------/ -// public boolean -// equals( Object obj ) -// { -// if ( this == obj ){ -// return true; -// } -// -// if ( ! (obj instanceof Term) ){ -// return false; -// } -// -// if ( term == null || ((Term)obj).term == null ){ -// return false; -// } -// -// return this.term.equals( ((Term)obj).term ); -// } - - //------------------------------------------------------------------/ - // toString - /** - * Converts a list of Terms to a String. - * - * @param arg An aaray of Terms to convert - * @return String representation of a list of Terems - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static java.lang.String - toString( Term arg[] ) - { - java.lang.String s = ""; - - for ( int i = 0; i < arg.length; ++i ){ - s += arg[i].toString(); - if ( i != arg.length - 1 ){ - s += ", "; - } - } - - return s; - } - - public abstract java.lang.String - debugString(); - - public static java.lang.String - debugString( Term arg[] ) - { - java.lang.String s = "["; - - for ( int i = 0; i < arg.length; ++i ){ - s += arg[i].debugString(); - if ( i != arg.length - 1 ){ - s += ", "; - } - } - - return s + "]"; - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/Tuple.java b/Jpl/jsrc/10/jpl/Tuple.java deleted file mode 100755 index bc3eee57f3..0000000000 --- a/Jpl/jsrc/10/jpl/Tuple.java +++ /dev/null @@ -1,534 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: Tuple.java -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -// ------------------------------------------------------------------------- -// $Id$ -//*****************************************************************************/ -package jpl; - - - -//----------------------------------------------------------------------/ -// Tuple -/** - * A Tuple is a Compound, used to represent Prolog tuples, the closest - * thing Prolog has to a data structure. - *

    - * Tuple triple = 
    - *     new Tuple(
    - *         jpl.Util.toTermArray(
    - *             new Atom( "a" ),
    - *             new Atom( "b" ),
    - *             new Atom( "c" ) ) );
    - * 
    - * - * This constructor (using the jpl.Util class for convenience) - * creates a triple corresponding to the Prolog tuple (a,b,c).

    - * - * The Tuple.Pair class can be used to create 2-element tuples. - * Use the let() method to obtain a reference to the ith (starting - * from 0) element in the Tuple. - * - *


    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Compound - */ -// Implementation notes: -// -// Tuples, in Prolog, are actually binary terms. Internally, the -// Prolog Tuple (a,b,c,d,e) is represented as follows: -// -// , -// / \ -// / \ -// a , -// / \ -// / \ -// c \ -// , -// / \ -// / \ -// d e -// -// That is, the ',' functor in Prolog is a binary functor. -// -// -// -// -// -// -// -//----------------------------------------------------------------------/ -public class Tuple -extends Compound -{ - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * @return the ith element in the tuple (starting from 0); - * null if the index is out of bounds - */ - public final Term - elt( int i ) - { - Tuple tuple = this; - Term kth = this.args_[0]; - - for ( int k = 0; k < i; ++k ){ - if ( tuple.args_[1] instanceof Tuple ){ - tuple = (Tuple) tuple.args_[1]; - kth = tuple.args_[0]; - } else { - - if ( k == i - 1 ){ - kth = tuple.args_[1]; - } else { - // out of bounds - return null; - } - } - } - - return kth; - } - - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - // we only need one of these guys - private static final Atom COMMA = new Atom( "," ); - - private static Term[] - tuple_chain( Term elts[] ) - { - if ( elts.length < 2 ){ - throw new JPLException( "Error: A Tuple must have 2 or more elements" ); - } else if ( elts.length == 2 ){ - return elts; - } else { - return ((Tuple)tuple_chain( elts, 0 )).args_; - } - } - - private static Term - tuple_chain( Term elts[], int i ) - { - if ( i < elts.length - 1 ){ - Term args[] = new Term[2]; - - args[0] = elts[i]; - args[1] = tuple_chain( elts, i+1 ); - return new Tuple( args ); - } else { - return elts[i]; - } - } - - //------------------------------------------------------------------/ - // Tuple - /** - * Create a Tuple whose arity is determined by the size of the - * input array. - * - * @param elts the Terms in the Tuple - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( Term elts[] ) - { - super( COMMA, tuple_chain( elts ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1 ) - { - this( - Util.toTermArray( t0, t1 ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1, t2 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1, - Term t2 ) - { - this( - Util.toTermArray( t0, t1, t2 ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1, t2, t3 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1, - Term t2, - Term t3 ) - { - this( - Util.toTermArray( t0, t1, t2, t3 ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1, - Term t2, - Term t3, - Term t4 ) - { - this( - Util.toTermArray( t0, t1, t2, t3, t4 ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5 ) - { - this( - Util.toTermArray( t0, t1, t2, t3, t4, - t5 ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5, t6 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6 ) - { - this( - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6 ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5, t6, t7 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7 ) - { - this( - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7 ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5, t6, t7, t8 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - * @param t8 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7, - Term t8 ) - { - this( - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7, t8 ) ); - } - - //------------------------------------------------------------------/ - // Tuple - /** - * This constructor is shorthand for - *
    -	 * new Tuple( 
    -	 *     Util.toTermArray( t0, t1, t2, t3, t4, 
    -	 *                       t5, t6, t7, t8, t9 ) )
    -	 * 
    - * - * @param t0 a jpl.Term - * @param t1 a jpl.Term - * @param t2 a jpl.Term - * @param t3 a jpl.Term - * @param t4 a jpl.Term - * @param t5 a jpl.Term - * @param t6 a jpl.Term - * @param t7 a jpl.Term - * @param t8 a jpl.Term - * @param t9 a jpl.Term - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Tuple( - Term t0, - Term t1, - Term t2, - Term t3, - Term t4, - Term t5, - Term t6, - Term t7, - Term t8, - Term t9 ) - { - this( - Util.toTermArray( t0, t1, t2, t3, t4, - t5, t6, t7, t8, t9 ) ); - } - - - - //------------------------------------------------------------------/ - // toString - /** - * @return the String representation of a Tuple, in this case, - * of the form (t0,...,tn-1). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public java.lang.String - toString() - { - Tuple tuple = this; - java.lang.String s = "("; - - while ( true ){ - s += tuple.args_[0] + ", "; - if ( tuple.args_[1] instanceof Tuple ){ - tuple = (Tuple) tuple.args_[1]; - } else { - return s + tuple.args_[1].toString() + ")"; - } - } - - } - - public java.lang.String - debugString() - { - return "(Tuple " + Term.debugString( args_ ) + ")"; - } - - - //==================================================================/ - // Pair - /** - * A Pair is a two-element Tuple - */ - // Implementation notes: - // - //==================================================================/ - public static class - Pair extends Tuple - { - public - Pair( Term a, Term b ) - { - super( Util.toTermArray( a, b ) ); - } - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/Util.java b/Jpl/jsrc/10/jpl/Util.java deleted file mode 100755 index 6931ccd5fa..0000000000 --- a/Jpl/jsrc/10/jpl/Util.java +++ /dev/null @@ -1,297 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; - -//----------------------------------------------------------------------/ -// Util -/** - * This class provides a bunch of static utility methods for the JPL - * High-Level Interface. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public final class Util -{ - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray() - { - Term t[] = new Term[0]; - - return t; - } - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0 ) - { - Term t[] = { t0 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1 ) - { - Term t[] = { t0, t1 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1, Term t2 ) - { - Term t[] = { t0, t1, t2 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1, Term t2, Term t3 ) - { - Term t[] = { t0, t1, t2, t3 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1, Term t2, Term t3, Term t4 ) - { - Term t[] = { t0, t1, t2, t3, t4 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5 ) - { - Term t[] = { t0, t1, t2, t3, t4, t5 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5, Term t6 ) - { - Term t[] = { t0, t1, t2, t3, t4, t5, t6 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5, Term t6, Term t7 ) - { - Term t[] = { t0, t1, t2, t3, t4, t5, t6, t7 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5, Term t6, Term t7, Term t8 ) - { - Term t[] = { t0, t1, t2, t3, t4, t5, t6, t7, t8 }; - - return t; - } - - - //------------------------------------------------------------------/ - // toTermArray - /** - * Creates an array of Terms, holding Terms in parameter(s). - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term[] - toTermArray( Term t0, Term t1, Term t2, Term t3, Term t4, - Term t5, Term t6, Term t7, Term t8, Term t9 ) - { - Term t[] = { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 }; - - return t; - } - - - //------------------------------------------------------------------/ - // termArrayToList - /** - * Converts an array of Terms to a jpl.List (if there are one or - * more Terms in the array), or jpl.List.NIL if there are no - * Terms in the array. (Since the end of a jpl.List is an Atom, - * the return type of this method must be Term, not List, for - * full generality.) - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static Term - termArrayToList( Term t[] ) - { - Term list = List.NIL; - for ( int i = t.length-1; i >= 0; --i ){ - list = new List( t[i], list ); - } - - return list; - } - - - - //------------------------------------------------------------------/ - // toString - /** - * converts a solution, in the form of a Hashtable, to a String. - * This method is really only for testing - * - * @param solution The solution to stringify. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static java.lang.String - toString( Hashtable solution ) - { - java.util.Enumeration vars = solution.keys(); - - java.lang.String s = "Solutions: "; - while ( vars.hasMoreElements() ){ - Variable var = (Variable) vars.nextElement(); - s += var + " = " + solution.get( var ); - } - return s; - } -} diff --git a/Jpl/jsrc/10/jpl/Variable.java b/Jpl/jsrc/10/jpl/Variable.java deleted file mode 100755 index e0822e1b76..0000000000 --- a/Jpl/jsrc/10/jpl/Variable.java +++ /dev/null @@ -1,233 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import jpl.fli.*; - -//----------------------------------------------------------------------/ -// Variable -/** - * This class provides a Java represenation of a Prolog Variable.

    - * - * In a sense, the Variable is the only interesting class in the - * jpl High-Level Interface, though it is also the most difficult - * to reason about. - * - * - *


    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class Variable -extends Term -{ - //==================================================================/ - // Contructors and Initialization - //==================================================================/ - - /** - * A reference to the term_t (a reference to a term in - * to Prolog Engine) to which this term is bound. This - * reference is only used in the course of translating a - * Term to a term_t. - */ - protected transient term_t term_ = null; - - //------------------------------------------------------------------/ - // Variable - /** - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public - Variable() - { - } - - //==================================================================/ - // Converting Terms to term_ts - //==================================================================/ - - //------------------------------------------------------------------/ - // put - /** - * To put a Variable, we want to be careful that the variable - * does not already occur in the Term. If it does, we have - * already thrown it as a key in the hastable, so we can look - * it up and use the term_t indexed by the Variable as the - * term to put; this way, the term_t in the Prolog Engine - * refers to the same term_t as any other occurrence of the - * same variable. On the other hand, if the variable does not - * (already) occur in the Term, put it in the hashtable and - * put a new variable into the term. - * - * @param var_table A Hashtable containing term_t's that are - * bound to (have packed in) Prolog variables as elements. The - * Elements are keyed by jpl.Variable instances. Cf. the put() - * implementation in the Variable class. - * @param term A (previously created) term_t which is to be - * packed with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - put( Hashtable var_table, term_t term ) - { - term_t t = (term_t) var_table.get( this ); - if ( t == null ){ - this.term_ = term; - Prolog.put_variable( term ); - var_table.put( this, term ); - } else { - this.term_ = t; - Prolog.put_term( term, t ); - } - } - - //==================================================================/ - // Converting term_ts to Terms - //==================================================================/ - - //------------------------------------------------------------------/ - // from_term_t - /** - * Converts a term_t to a Variable. If the term_t is a - * variable, we just make a new Variable. - * - * We are careful to create a List.Nil object if indeed the - * atom is "[]". Note that nil is an atom in Prolog and jpl. - * - * @param term The term_t to convert - * @return A new Variable - */ - // Implementation notes: Is this right? Couldn't there be - // a Prolog formula with more than one term_t, but where - // both refer to the same variable? Someone help! - //------------------------------------------------------------------/ - protected static Term - from_term_t( Hashtable vars, term_t term ) - { - StringHolder holder = new StringHolder(); - - Prolog.get_chars( term, holder, Prolog.CVT_VARIABLE ); - - Variable var = (Variable) vars.get( holder.value ); - if ( var == null ){ - var = new Variable(); - var.term_ = term; - vars.put( holder.value, var ); - } - return var; - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - - //------------------------------------------------------------------/ - // computeSubstitution - /** - * If this Variable instance is not already in the Hashtable, - * put the result of converting the term_t to which this variable - * has been unified to a Term in the Hashtable, keyed on this - * Variable instance. - * - * @param table table holding Term substitutions, keyed on - * Variables. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - protected final void - computeSubstitution( Hashtable bindings, Hashtable vars ) - { - if ( bindings.get( this ) == null ){ - bindings.put( this, Term.from_term_t( vars, this.term_ ) ); - } - } - - - - //------------------------------------------------------------------/ - // equals - /** - * A Variable is equal to another when their corresponding term_ts - * (internal Prolog represenations) are equal. - * - * @param obj The Object to compare. - * @return true if the Object is the above condition applies. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public final boolean - equals( Object obj ) - { - if ( this == obj ){ - return true; - } - - if ( ! (obj instanceof Variable) ){ - return false; - } - - if ( term_ == null || ((Variable)obj).term_ == null ){ - return false; - } - - return term_.equals( ((Variable)obj).term_ ); - } - - public java.lang.String - debugString() - { - return "(Variable " + toString() + ")"; - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/Version.java b/Jpl/jsrc/10/jpl/Version.java deleted file mode 100755 index a361d8f01c..0000000000 --- a/Jpl/jsrc/10/jpl/Version.java +++ /dev/null @@ -1,9 +0,0 @@ -// $Id$ -package jpl; -class Version -{ - public final java.lang.String status = "final"; - public final int major = 1; - public final int minor = 0; - public final int patch = 1; -} diff --git a/Jpl/jsrc/10/jpl/fli/DoubleHolder.java b/Jpl/jsrc/10/jpl/fli/DoubleHolder.java deleted file mode 100755 index a9bd7e88ce..0000000000 --- a/Jpl/jsrc/10/jpl/fli/DoubleHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// DoubleHolder -/** - * A DoubleHolder is merely a Holder class for a double value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class DoubleHolder -{ - public double value; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/IntHolder.java b/Jpl/jsrc/10/jpl/fli/IntHolder.java deleted file mode 100755 index 85d1dea0f9..0000000000 --- a/Jpl/jsrc/10/jpl/fli/IntHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// IntHolder -/** - * An IntHolder is merely a Holder class for an Int value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class IntHolder -{ - public int value; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/LongHolder.java b/Jpl/jsrc/10/jpl/fli/LongHolder.java deleted file mode 100755 index 482c20cf8a..0000000000 --- a/Jpl/jsrc/10/jpl/fli/LongHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// LongHolder -/** - * A Long Holder merely holds a long value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class LongHolder -{ - public long value = 0L; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/PointerHolder.java b/Jpl/jsrc/10/jpl/fli/PointerHolder.java deleted file mode 100755 index aad95c1561..0000000000 --- a/Jpl/jsrc/10/jpl/fli/PointerHolder.java +++ /dev/null @@ -1,63 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// PointerHolder -/** - * A PointerHolder is a trivial extension of a LongHolder. This is sort of - * a no-no in Java, as the long value stored herein is sometimes a - * machine address. (Don't tell Sun.) - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// There could be issues in the future with signedness, since Java -// does not have an unsigned type; make sure not to do any arithmetic -// with the stored value. -//----------------------------------------------------------------------/ -public class PointerHolder extends LongHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/Prolog.java b/Jpl/jsrc/10/jpl/fli/Prolog.java deleted file mode 100755 index aed1f8db97..0000000000 --- a/Jpl/jsrc/10/jpl/fli/Prolog.java +++ /dev/null @@ -1,249 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// Prolog -/** - * This class consists only of constants (static finals) and static - * native methods. The constants and methods defined herein are in - * (almost) strict 1-1 correpsondence with the functions in the Prolog - * FLI by the same name (except without the PL_, SQ_, etc. prefixes).

    - * - * See the file jpl_fli_Prolog.c for the native implementations of these - * methods. Refer to your local Prolog FLI documentations for the meanings - * of these methods, and observe the following:

    - * - *

    - *
  • The types and signatures of the following methods are almost - * in 1-1 correspondence with the Prolog FLI. The Prolog types - * term_t, atom_t, functor_t, etc. are mirrored in this package with - * classes by the same name, making the C and java uses of these - * interfaces similar.
  • - *
  • As term_t, functor_t, etc. types are Java classes, they are - * passed to these methods by vlaue; however, calling these - * methods on such class instances does have side effects. In general, - * the value fields of these instances will be modified, in much the - * same way the term_t, functor_t, etc. Prolog instances would be - * modified.
  • - *
  • The exceptions to this rule occur when maintaining the same - * signature would be impossible, e.g., when the Prolog FLI functions - * require pointers; in this case, the signatures have been - * modified to take *Holder classes (Int, Double, String, etc.), - * to indicate a call by reference parameter. - *
  • Functions which take variable-length argument lists in C - * take arrays in Java; however, due to the fact that Java does not - * support variable length argument lists, these methods currently - * have an upper bound of 5 arguments. Sorry about that. - *
  • - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// Not all of the constants and methods are here. Some will be -// added as this software matures. -//----------------------------------------------------------------------/ -public final class Prolog -{ - static { - System.loadLibrary( "jpl" ); - } - - /* term types */ - public static final int - VARIABLE = 1, - ATOM = 2, - INTEGER = 3, - FLOAT = 4, - STRING = 5, - TERM = 6, - FUNCTOR = 10, - LIST = 11, - CHARS = 12, - POINTER = 13; - - public static final int - succeed = 1, - fail = 0; - - /* query flags */ - public static final int - Q_NORMAL = 0x02, - Q_NODEBUG = 0x04, - Q_CATCH_EXCEPTION = 0x08, - Q_PASS_EXCEPTION = 0x10; - - /* conversion flags */ - public static final int - CVT_ATOM = 0x0001, - CVT_STRING = 0x0002, - VT_LIST = 0x0004, - CVT_INTEGER = 0x0008, - CVT_FLOAT = 0x0010, - CVT_VARIABLE = 0x0020, - CVT_NUMBER = (CVT_INTEGER | CVT_FLOAT), - CVT_ATOMIC = (CVT_NUMBER|CVT_ATOM | CVT_STRING), - CVT_ALL = 0x00ff, - - BUF_DISCARDABLE = 0x0000, - BUF_RING = 0x0100, - BUF_MALLOC = 0x0200; - - /* Creating and destroying term-refs */ - public synchronized static native term_t new_term_refs( int n ); - public synchronized static native term_t new_term_ref(); - public synchronized static native term_t copy_term_ref( term_t from ); - public synchronized static native void reset_term_refs( term_t r ); - - /* Constants */ - public synchronized static native atom_t new_atom( String s ); - public synchronized static native String atom_chars( atom_t a ); - public synchronized static native functor_t new_functor( atom_t f, int a ); - public synchronized static native atom_t functor_name( functor_t f ); - public synchronized static native int functor_arity( functor_t f ); - - /* Get Java-values from Prolog terms */ - public synchronized static native int get_atom( term_t t, atom_t a ); - public synchronized static native int get_atom_chars( term_t t, StringHolder a ); - public synchronized static native int get_string( term_t t, StringHolder s ); - public synchronized static native int get_list_chars( term_t l, StringHolder s, int flags ); - public synchronized static native int get_chars( term_t t, StringHolder s, int flags ); - public synchronized static native int get_integer( term_t t, IntHolder i ); - public synchronized static native int get_long( term_t t, LongHolder l ); - public synchronized static native int get_pointer( term_t t, PointerHolder ptr ); - public synchronized static native int get_float( term_t t, DoubleHolder d ); - public synchronized static native int get_functor( term_t t, functor_t f ); - public synchronized static native int get_name_arity( term_t t, atom_t name, IntHolder arity ); - public synchronized static native int get_module( term_t t, module_t module ); - public synchronized static native int get_arg( int index, term_t t, term_t a ); - public synchronized static native int get_list( term_t l, term_t h, term_t t ); - public synchronized static native int get_head( term_t l, term_t h ); - public synchronized static native int get_tail( term_t l, term_t t ); - public synchronized static native int get_nil( term_t l ); - - /* Verify types */ - public synchronized static native int term_type( term_t t ); - public synchronized static native int is_variable( term_t t ); - public synchronized static native int is_atom( term_t t ); - public synchronized static native int is_integer( term_t t ); - public synchronized static native int is_string( term_t t ); - public synchronized static native int is_float( term_t t ); - public synchronized static native int is_compound( term_t t ); - public synchronized static native int is_functor( term_t t, functor_t f ); - public synchronized static native int is_list( term_t t ); - public synchronized static native int is_atomic( term_t t ); - public synchronized static native int is_number( term_t t ); - - /* Assign to term-references */ - public synchronized static native void put_variable( term_t t ); - public synchronized static native void put_atom( term_t t, atom_t a ); - public synchronized static native void put_atom_chars( term_t t, String chars ); - public synchronized static native void put_string_chars( term_t t, String chars ); - public synchronized static native void put_list_chars( term_t t, String chars); - public synchronized static native void put_integer( term_t t, long i ); - public synchronized static native void put_pointer(term_t t, PointerHolder ptr); - public synchronized static native void put_float( term_t t, double f ); - public synchronized static native void put_functor( term_t t, functor_t functor ); - public synchronized static native void put_list( term_t l ); - public synchronized static native void put_nil( term_t l ); - public synchronized static native void put_term( term_t t1, term_t t2 ); - // this method should be deprecated: - protected synchronized static native void cons_functor( term_t h, functor_t f, term_t terms[] ); - public synchronized static native void cons_functor_v( term_t h, functor_t fd, term_t a0 ); - public synchronized static native void cons_list( term_t l, term_t h, term_t t ); - - /* Unify term-references */ - public synchronized static native int unify( term_t t1, term_t t2 ); - - /* Modules */ - public synchronized static native module_t context(); - public synchronized static native atom_t module_name( module_t module ); - public synchronized static native module_t new_module( atom_t name ); - public synchronized static native int strip_module( term_t in, module_t m, term_t out ); - - /* Foreign context frames */ - public synchronized static native fid_t open_foreign_frame(); - public synchronized static native void close_foreign_frame( fid_t cid ); - public synchronized static native void discard_foreign_frame( fid_t cid ); - - /* Finding predicates */ - public synchronized static native predicate_t pred( functor_t f, module_t m ); - public synchronized static native predicate_t predicate( String name, int arity, String module ); - public synchronized static native int predicate_info( predicate_t pred, atom_t name, IntHolder arity, module_t module); - - /* Call-back */ - public synchronized static native qid_t open_query( module_t m, int flags, predicate_t pred, term_t t0 ); - public synchronized static native int next_solution( qid_t qid ); - public synchronized static native void close_query( qid_t qid ); - public synchronized static native void cut_query( qid_t qid ); - - /* Simplified (but less flexible) call-back */ - public synchronized static native int call( term_t t, module_t m ); - public synchronized static native int call_predicate( module_t m, int debug, predicate_t pred, term_t t0 ); - public synchronized static native term_t exception( qid_t qid ); - - public synchronized static native int initialise( int argc, String argv[] ); - public synchronized static native void halt( int status ); - - /* a simple test; write a test.pl file and run!! */ - public static void - main( String argv[] ) - { - Prolog.initialise( argv.length, argv ); - - atom_t atom = Prolog.new_atom( "test" ); - term_t term = Prolog.new_term_ref(); - Prolog.put_atom( term, atom ); - predicate_t pred = Prolog.predicate( "consult", 1, null ); - qid_t qid = Prolog.open_query( null, Q_NORMAL, pred, term ); - - System.out.println( - Prolog.next_solution( qid ) ); - - Prolog.close_query( qid ); - - Prolog.halt( 0 ); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/StringHolder.java b/Jpl/jsrc/10/jpl/fli/StringHolder.java deleted file mode 100755 index ccd9a41cc8..0000000000 --- a/Jpl/jsrc/10/jpl/fli/StringHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// StringHolder -/** - * A StringHolder is merely a Holder class for a String value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class StringHolder -{ - public String value; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/atom_t.java b/Jpl/jsrc/10/jpl/fli/atom_t.java deleted file mode 100755 index 9fa9b01a3a..0000000000 --- a/Jpl/jsrc/10/jpl/fli/atom_t.java +++ /dev/null @@ -1,75 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// atom_t -/** - * An atom_t is a simple extension of a term_t. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class atom_t -extends LongHolder -{ - //------------------------------------------------------------------/ - // toString - /** - * The String representation of an atom_t is just the atom's name. - * - * @return atom's name - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public String - toString() - { - return Prolog.atom_chars( this ); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/fid_t.java b/Jpl/jsrc/10/jpl/fli/fid_t.java deleted file mode 100755 index 0ac1bf9937..0000000000 --- a/Jpl/jsrc/10/jpl/fli/fid_t.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// fid_t -/** - * An fid_t holds the value of a frame id in the Prolog Engine. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class fid_t -extends LongHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/functor_t.java b/Jpl/jsrc/10/jpl/fli/functor_t.java deleted file mode 100755 index ed0fd13274..0000000000 --- a/Jpl/jsrc/10/jpl/fli/functor_t.java +++ /dev/null @@ -1,61 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// functor_t -/** - * A functor_t holds a reference to a Prolog functor_t in the - * Prolog engine. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: Note that a functor_t is not a term, -// consistent with the treatment in the Prolog FLI. -//----------------------------------------------------------------------/ -public class functor_t -extends LongHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/makefile b/Jpl/jsrc/10/jpl/fli/makefile deleted file mode 100755 index d23d831a30..0000000000 --- a/Jpl/jsrc/10/jpl/fli/makefile +++ /dev/null @@ -1,37 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../../../../makefile.env -include ../../../../../Javagui/makefile.inc - -TMPFILES =$(shell find -name "*.java") -JAVAFILES = $(subst ./,,$(TMPFILES)) - -.PHONY: all -all:$(JPL_CLASS_TARGET)/jpl/fli/Prolog.class - -$(JPL_CLASS_TARGET)/jpl/fli/Prolog.class: $(JAVAFILES) - $(JAVAC) -classpath $(CLASSPATH):$(JPL_CLASSPATH) -d $(JPL_CLASS_TARGET) $(JAVAFILES) - -.PHONY: clean -clean: - rm -f $(JPL_CLASS_TARGET)/jpl/fli/*.class - - - diff --git a/Jpl/jsrc/10/jpl/fli/module_t.java b/Jpl/jsrc/10/jpl/fli/module_t.java deleted file mode 100755 index d000086c52..0000000000 --- a/Jpl/jsrc/10/jpl/fli/module_t.java +++ /dev/null @@ -1,61 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// module_t -/** - * A module_t is a PointerHolder type which holds a reference to a Prolog - * module_t reference. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class module_t -extends PointerHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/predicate_t.java b/Jpl/jsrc/10/jpl/fli/predicate_t.java deleted file mode 100755 index ff3e8cdcc7..0000000000 --- a/Jpl/jsrc/10/jpl/fli/predicate_t.java +++ /dev/null @@ -1,61 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// predicate_t -/** - * A predicate_t is a PointerHolder class whose value is a reference to a - * Prolog predicate_t. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class predicate_t -extends PointerHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/qid_t.java b/Jpl/jsrc/10/jpl/fli/qid_t.java deleted file mode 100755 index 63e187addd..0000000000 --- a/Jpl/jsrc/10/jpl/fli/qid_t.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// qid_t -/** - * A qid_t holds a reference to a Prolog qid_t. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class qid_t -extends LongHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/fli/term_t.java b/Jpl/jsrc/10/jpl/fli/term_t.java deleted file mode 100755 index 025869fa04..0000000000 --- a/Jpl/jsrc/10/jpl/fli/term_t.java +++ /dev/null @@ -1,133 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// term_t -/** - * A term_t is a simple class which mirrors the term_t type in - * the Prolog FLI. All it really does is hold a term reference, - * which is an internal representation of a term in the Prolog - * Engine. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class term_t -extends LongHolder -{ - public static final long UNASSIGNED = -1L; - - public - term_t() - { - value = UNASSIGNED; - } - - //------------------------------------------------------------------/ - // toString - /** - * This static method converts a term_t, which is assumed to contain - * a reference to a *consecutive* list of term_t references to a - * String representation of a list of terms, in this case, a comma - * separated list. - * - * @param n the number of consecutive term_ts - * @param term0 a term_t whose value is the 0th term_t. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static String - toString( int n, term_t term0 ) - { - String s = ""; - int i; - long ith_term_t; - - for ( i = 0, ith_term_t = term0.value; i < n; ++i, ++ith_term_t ){ - term_t term = new term_t(); - term.value = ith_term_t; - s += term.toString(); - - if ( i != n - 1 ){ - s += ", "; - } - } - - return s; - } - - - //------------------------------------------------------------------/ - // equals - /** - * Instances of term_ts are stored in Term objects (see jpl.Term), - * and these term_ts are in some cases stored in Hashtables. - * Supplying this predicate provides the right behavior in Hashtable - * lookup (see the rules for Hashtable lookup in java.util).

    - * - * Note. Two term_ts are *not* equal if their values have not - * been assigned. (Since Prolog FLI term_ts are unsigned values and - * the UNASSIGNED value is -1, this should work). - * - * @param obj the Object to comapre. - * @return true if the supplied object is a term_t instances - * and the long values are the same - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public boolean - equals( Object obj ) - { - return - (obj instanceof term_t) && - this.value == ((term_t)obj).value && - this.value != UNASSIGNED; - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/10/jpl/makefile b/Jpl/jsrc/10/jpl/makefile deleted file mode 100755 index d24096b926..0000000000 --- a/Jpl/jsrc/10/jpl/makefile +++ /dev/null @@ -1,50 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../../../makefile.env -include ../../../../Javagui/makefile.inc - -# get all class files in this directory -TMPFILES =$(shell find -maxdepth 1 -name "*.java") -JAVAFILES = $(subst ./,,$(TMPFILES)) - - - -.PHONY: all -all: check fli $(JPL_CLASS_TARGET)/jpl/Query.class - -.PHONY: check -check: - $(checkjavac) - -.PHONY: fli -fli: - $(MAKE) -C fli all - - -$(JPL_CLASS_TARGET)/jpl/Query.class: $(JAVAFILES) - $(JAVAC) -classpath $(CLASSPATH):$(JPL_CLASSPATH) -d $(JPL_CLASS_TARGET) $(JAVAFILES) - -.PHONY: clean -clean: - $(MAKE) -C fli clean - rm -f $(JPL_CLASS_TARGET)/jpl/*.class - - - diff --git a/Jpl/jsrc/10/makefile b/Jpl/jsrc/10/makefile deleted file mode 100755 index a959e26b52..0000000000 --- a/Jpl/jsrc/10/makefile +++ /dev/null @@ -1,27 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -.PHONY: all -all: - $(MAKE) -C jpl all - -.PHONY: clean -clean: - $(MAKE) -C jpl clean - diff --git a/Jpl/jsrc/30/jpl/Atom.java b/Jpl/jsrc/30/jpl/Atom.java deleted file mode 100644 index 47fa4d9476..0000000000 --- a/Jpl/jsrc/30/jpl/Atom.java +++ /dev/null @@ -1,157 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Map; - -import jpl.fli.Prolog; -import jpl.fli.StringHolder; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// Atom -/** - * Atom is a specialised Compound with zero arguments, representing a Prolog atom with the same name. - * An Atom is constructed with a String parameter (its name, unquoted), which cannot thereafter be changed. - *

    Atom a = new Atom("hello");
    - * An Atom can be used (and re-used) as an argument of Compound Terms. - * Two Atom instances are equal (by equals()) iff they have equal names. - * - *
    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -public class Atom extends Compound { - - //==================================================================/ - // Attributes (none) - //==================================================================/ - - //==================================================================/ - // Constructors - //==================================================================/ - - /** - * @param name the Atom's name (unquoted) - */ - public Atom(String name) { - super(name); - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - // these are all inherited from Compound - - public final int type() { - return Prolog.ATOM; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * Returns a debug-friendly String representation of an Atom. - * - * @return a debug-friendly String representation of an Atom - * @deprecated - */ - public String debugString() { - return "(Atom " + toString() + ")"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - //==================================================================/ - - // (this is done with the put() method inherited from Compound) - - //==================================================================/ - // Converting Prolog terms to JPL Terms - //==================================================================/ - - /** - * Converts a Prolog term to a JPL Atom. This is only called from Term.getTerm(), - * and we can assume the term_t refers to a Prolog atom, - * so we just create a new Atom object with the atom's name. - * - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - * @param term The Prolog term to be converted - * @return A new Atom instance - */ - protected static Term getTerm(Map vars_to_Vars, term_t term) { - StringHolder holder = new StringHolder(); - Prolog.get_atom_chars(term, holder); // ignore return val; assume success... - - return new Atom(holder.value); - } - - /** - * Converts a term_t to an Atom, knowing that it refers to a SWI-Prolog string, - * so we just create a new Atom object initialised with the string's value. - * JPL users should avoid SWI-Prolog's non-ISO strings, but in some obscure - * circumstances they are returned unavoidably, so we have to handle them - * (and this is how). - * - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - * @param term The term_t to convert - * @return A new Atom instance - */ - protected static Term getString(Map vars_to_Vars, term_t term) { - StringHolder holder = new StringHolder(); - Prolog.get_string_chars(term, holder); // ignore return val; assume success... - // System.err.println("Warning: Prolog returns a string: \"" + holder.value + "\""); - return new Atom(holder.value); - } - - //==================================================================/ - // Computing substitutions - //==================================================================/ - - // (done with the inherited Compound.getSubst() method) - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/Compound.java b/Jpl/jsrc/30/jpl/Compound.java deleted file mode 100644 index 31c2e2f1fe..0000000000 --- a/Jpl/jsrc/30/jpl/Compound.java +++ /dev/null @@ -1,324 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Map; - -import jpl.fli.IntHolder; -import jpl.fli.Prolog; -import jpl.fli.StringHolder; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// Compound -/** - * A Compound represents a structured term, - * comprising a functor and arguments (Terms). - * Atom is a subclass of Compound, whose instances have zero arguments. - * Direct instances of Compound must have one or more arguments - * (it is an error to attempt to construct a Compound with zero args; - * a JPLException will be thrown). - * For example, this Java expression yields - * a representation of the term f(a): - *
    - * new Compound( "f", new Term[] { new Atom("a") } )
    - * 
    - * Note the use of the "anonymous array" notation to denote the arguments - * (an anonymous array of Term). - *
    - * Alternatively, construct the Term from Prolog source syntax: - *
    - * Util.textToTerm("f(a)")
    - * 
    - * The arity of a Compound is the quantity of its arguments. - * Once constructed, neither the name, arity nor any argument of a Compound can be altered. - *
    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Atom - */ -public class Compound extends Term { - - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the name of this Compound - */ - protected final String name; - - /** - * the arguments of this Compound - */ - protected final Term[] args; - - //==================================================================/ - // Constructors - //==================================================================/ - - /** - * Creates a Compound with name but no args (i.e. an Atom). - * - * @param name the name of this Compound - * @param args the arguments of this Compound - */ - protected Compound(String name) { - if (name == null) { - throw new JPLException("jpl.Atom: cannot construct with null name"); - } - this.name = name; - this.args = new Term[] { - }; - } - - /** - * Creates a Compound with name and args. - * - * @param name the name of this Compound - * @param args the arguments of this Compound - */ - public Compound(String name, Term[] args) { - if (name == null) { - throw new JPLException("jpl.Compound: cannot construct with null name"); - } - if (args == null) { - throw new JPLException("jpl.Compound: cannot construct with null args"); - } - if (args.length == 0) { - throw new JPLException("jpl.Compound: cannot construct with zero args"); - } - this.name = name; - this.args = args; - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - /** - * Returns the ith argument (counting from 1) of this Compound; - * throws an ArrayIndexOutOfBoundsException if i is inappropriate. - * - * @return the ith argument (counting from 1) of this Compound - */ - public final Term arg(int i) { - return args[i - 1]; - } - - /** - * Tests whether this Compound's functor has (String) 'name' and 'arity'. - * - * @return whether this Compound's functor has (String) 'name' and 'arity' - */ - public final boolean hasFunctor(String name, int arity) { - return name.equals(name) && arity == args.length; - } - - /** - * Returns the name (unquoted) of this Compound. - * - * @return the name (unquoted) of this Compound - */ - public final String name() { - return name; - } - - /** - * Returns the arity (1+) of this Compound. - * - * @return the arity (1+) of this Compound - */ - public final int arity() { - return args.length; - } - - /** - * Returns a prefix functional representation of a Compound of the form name(arg1,...), - * where each argument is represented according to its toString() method. - *
    - * NB 'name' should be quoted iff necessary, and Term.toString(Term[]) is not - * really a Term method, more a utility... - * - * @return string representation of an Compound - */ - public String toString() { - return quotedName() + (args.length > 0 ? "(" + Term.toString(args) + ")" : ""); - } - - /** - * Two Compounds are equal if they are identical (same object) or their names and arities are equal and their - * respective arguments are equal. - * - * @param obj the Object to compare (not necessarily another Compound) - * @return true if the Object satisfies the above condition - */ - public final boolean equals(Object obj) { - return (this == obj || (obj instanceof Compound && name.equals(((Compound) obj).name) && Term.terms_equals(args, ((Compound) obj).args))); - } - - public int type() { - return Prolog.COMPOUND; - } - - public String typeName(){ - return "Compound"; - } - - //==================================================================/ - // Methods (protected) - //==================================================================/ - - /** - * Returns a quoted (iff necessary) form of the Atom's name, as understood by Prolog read/1 - * - * @return a quoted form of the Atom's name, as understood by Prolog read/1 - */ - protected String quotedName() { - return ((Atom) (new Query(new Compound("sformat", new Term[] { new Variable("S"), new Atom("~q"), new Compound(".", new Term[] { new Atom(this.name), new Atom("[]")}) - }))) - .oneSolution() - .get( - "S")).name; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * Returns the arguments of this Compound. - * - * @return the arguments of this Compound - * @deprecated - */ - public final Term[] args() { - return args; - } - - /** - * Returns the ith argument (counting from 0) of this Compound. - * - * @return the ith argument (counting from 0) of this Compound - * @deprecated - */ - public final Term arg0(int i) { - return args[i]; - } - - /** - * Returns a debug-friendly representation of a Compound. - * - * @return a debug-friendly representation of a Compound - * @deprecated - */ - public String debugString() { - return "(Compound " + name + " " + Term.debugString(args) + ")"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - //==================================================================/ - - /** - * To put a Compound in a term, we create a sequence of term_t - * references from the Term.terms_to_term_ts() method, and then - * use the Prolog.cons_functor_v() method to create a Prolog compound - * term. - * - * @param varnames_to_vars A Map from variable names to Prolog variables - * @param term A (previously created) term_t which is to be - * set to a Prolog term corresponding to the Term subtype - * (Atom, Variable, Compound, etc.) on which the method is invoked. - */ - protected final void put(Map varnames_to_vars, term_t term) { - - Prolog.cons_functor_v(term, Prolog.new_functor(Prolog.new_atom(name), args.length), Term.putTerms(varnames_to_vars, args)); - } - - //==================================================================/ - // Converting Prolog terms to JPL Terms - //==================================================================/ - - /** - * Converts the Prolog term in term_t (known to be a compound) to a JPL Compound. - * In this case, we create a list of Terms by calling Term.getTerm for each - * term_t reference we get from Prolog.get_arg - * (Not sure why we couldn't get a sequence from there, but...).

    - * - * @param varnames_to_vars A Map from variable names to Prolog variables - * @param term The Prolog term to convert - * @return A new Compound - */ - protected static Term getTerm(Map varnames_to_vars, term_t term) { - - // we need holders to get the term's name and arity back from the FLI: - StringHolder name_holder = new StringHolder(); - IntHolder arity_holder = new IntHolder(); - Prolog.get_name_arity(term, name_holder, arity_holder); // assume it succeeds - - Term args[] = new Term[arity_holder.value]; - for (int i = 1; i <= arity_holder.value; i++) { - term_t termi = Prolog.new_term_ref(); - Prolog.get_arg(i, term, termi); - args[i - 1] = Term.getTerm(varnames_to_vars, termi); - } - return new Compound(name_holder.value, args); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - /** - * Nothing needs to be done except to pass the buck to this Compound's args. - * - * @param varnames_to_Terms A Map from variable names to JPL Terms - * @param vars_to_Vars A Map from Prolog variables to JPL Variables - */ - protected final void getSubst(Map varnames_to_Terms, Map vars_to_Vars) { - Term.getSubsts(varnames_to_Terms, vars_to_Vars, args); - } - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/Float.java b/Jpl/jsrc/30/jpl/Float.java deleted file mode 100644 index 36fbdc68d4..0000000000 --- a/Jpl/jsrc/30/jpl/Float.java +++ /dev/null @@ -1,295 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Map; - -import jpl.fli.DoubleHolder; -import jpl.fli.Prolog; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// Float -/** - * Float is a specialised Term with a double field, representing a Prolog 64-bit ISO/IEC floating point value. - * Once constructed, a Float's value cannot be altered. - *

    - * Float f = new Float( 3.14159265 );
    - * 
    - * A Float can be used (and re-used) in Compound Terms. - * Two Float instances are equal (by .equals()) iff their (double) values are equal. - * - *
    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -public class Float extends Term { - - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the Float's immutable value - */ - protected final double value; - - //==================================================================/ - // Constructors and Initialization - //==================================================================/ - - /** - * This constructor creates a Float with the supplied - * (double) value. - * - * @param value this Float's value - */ - public Float(double value) { - this.value = value; - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - /** - * throws a JPLException (arg(int) is defined only for Compound and Atom) - * - * @return the ith argument (counting from 1) of this Float (never) - */ - public final Term arg(int i) { - throw new JPLException("jpl.Float.arg(int) is undefined"); - } - - /** - * Tests whether this Float's functor has (String) 'name' and 'arity' (never) - * - * @return whether this Float's functor has (String) 'name' and 'arity' (never) - */ - public final boolean hasFunctor(String name, int arity) { - return false; - } - - /** - * Tests whether this Float's functor has (int) 'name' and 'arity' (never) - * - * @return whether this Float's functor has (int) 'name' and 'arity' (never) - */ - public final boolean hasFunctor(int val, int arity) { - return false; - } - - /** - * Tests whether this Float's functor has (double) 'name' and 'arity' - * - * @return whether this Float's functor has (double) 'name' and 'arity' - */ - public final boolean hasFunctor(double val, int arity) { - return val == this.value && arity == 0; - } - - /** - * throws a JPLException (name() is defined only for Compound, Atom and Variable) - * - * @return the name of this Float (never) - */ - public final String name() { - throw new JPLException("jpl.Float.name() is undefined"); - } - - /** - * Returns the arity (0) of this Float - * - * @return the arity (0) of this Float - */ - public final int arity() { - return 0; - } - - /** - * returns the (double) value of this Float, converted to an int - * - * @return the (double) value of this Float, converted to an int - */ - public final int intValue() { - return (new Double(value)).intValue(); - } - - /** - * returns the (double) value of this Float, converted to a long - * - * @return the (double) value of this Float, converted to a long - */ - public final long longValue() { - return (new Double(value)).longValue(); - } - - /** - * returns the (double) value of this Float, converted to a float - * - * @return the (double) value of this Float, converted to a float - */ - public final float floatValue() { - return (new Double(value)).floatValue(); - } - - /** - * returns the (double) value of this Float - * - * @return the (double) value of this Float - */ - public final double doubleValue() { - return this.value; - } - - /** - * Returns a Prolog source text representation of this Float - * - * @return a Prolog source text representation of this Float - */ - public String toString() { - return "" + value + ""; - } - - /** - * Two Floats are equal if they are the same object, or their values are equal - * - * @param obj The Object to compare - * @return true if the Object satisfies the above condition - */ - public final boolean equals(Object obj) { - return this == obj || (obj instanceof Float && value == ((Float) obj).value); - } - - public final int type() { - return Prolog.FLOAT; - } - - public String typeName(){ - return "Float"; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * The (nonexistent) args of this Float - * - * @return the (nonexistent) args of this Float - * @deprecated - */ - public Term[] args() { - return new Term[] {}; - } - - /** - * The immutable value of this jpl.Float object, as a Java double - * - * @return the Float's value - * @deprecated - */ - public double value() { - return value; - } - - /** - * Returns a debug-friendly String representation of this Float - * - * @return a debug-friendly String representation of this Float - * @deprecated - */ - public String debugString() { - return "(Float " + toString() + ")"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - //==================================================================/ - - /** - * To convert a JPL Float to a Prolog term, we put its value field into the - * term_t as a float. - * - * @param varnames_to_vars A Map from variable names to Prolog variables. - * @param term A (previously created) term_t which is to be - * set to a Prolog float corresponding to this Float's value - */ - protected final void put(Map varnames_to_vars, term_t term) { - Prolog.put_float(term, value); - } - - //==================================================================/ - // Converting Prolog terms to JPL Terms - //==================================================================/ - - /** - * Converts a Prolog term (known to be a float) to a JPL Float. - * - * @param vars_to_Vars A Map from Prolog variables to JPL Variables - * @param term The Prolog term (a float) to convert - * @return A new Float instance - */ - protected static Term getTerm(Map vars_to_Vars, term_t term) { - DoubleHolder double_holder = new DoubleHolder(); - - Prolog.get_float(term, double_holder); // assume it succeeds... - return new jpl.Float(double_holder.value); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - /** - * Nothing needs to be done if the Term is an Atom, Integer or (as in this case) a Float - * - * @param varnames_to_Terms A Map from variable names to JPL Terms - * @param vars_to_Vars A Map from Prolog variables to JPL Variables - */ - protected final void getSubst(Map varnames_to_Terms, Map vars_to_Vars) { - } - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/Integer.java b/Jpl/jsrc/30/jpl/Integer.java deleted file mode 100644 index fdc3f4d1f5..0000000000 --- a/Jpl/jsrc/30/jpl/Integer.java +++ /dev/null @@ -1,269 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Map; - -import jpl.fli.IntHolder; -import jpl.fli.Prolog; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// Integer -/** - * Integer is a specialised Term with a long field, representing a Prolog integer value. - *
    - * Integer i = new Integer(1024);
    - * 
    - * Once constructed, the value of an Integer instance cannot be altered. - * An Integer can be used (and re-used) as an argument of Compounds. - * Beware confusing jpl.Integer with java.lang.Integer. - * - *
    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -public class Integer extends Term { - - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the Integer's immutable long value - */ - protected final long value; - - //==================================================================/ - // Constructors - //==================================================================/ - - /** - * @param value This Integer's (long) value - */ - public Integer(long value) { - this.value = value; - } - - /** - * @param value This Integer's (int) value - */ - public Integer(int value) { - this.value = value; - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - /** - * Tests whether this Integer's functor has (int) 'name' and 'arity' - * - * @return whether this Integer's functor has (int) 'name' and 'arity' - */ - public final boolean hasFunctor(int val, int arity) { - return val == this.value && arity == 0; - } - - /** - * Returns the arity (0) of this jpl.Integer - * - * @return the arity (0) of this jpl.Integer - */ - public final int arity() { - return 0; - } - - /** - * Returns the value of this Integer as an int if possible, else throws exception - * - * @return the int value of this Integer (if representable) - */ - public final int intValue() { - if (value < java.lang.Integer.MIN_VALUE || value > java.lang.Integer.MAX_VALUE) { - throw new JPLException("cannot represent Integer value as an int"); - } else { - return (int) value; - } - } - - /** - * Returns the value of this Integer converted to a long - * - * @return the value of this Integer converted to a long - */ - public final long longValue() { - return (new java.lang.Long(value)).longValue(); // safe but inefficient... - } - - /** - * Returns the value of this Integer converted to a float - * - * @return the value of this Integer converted to a float - */ - public final float floatValue() { - return (new java.lang.Long(value)).floatValue(); // safe but inefficient... - } - - /** - * Returns the value of this Integer converted to a double - * - * @return the value of this Integer converted to a double - */ - public final double doubleValue() { - return (new java.lang.Long(value)).doubleValue(); // safe but inefficient... - } - - /** - * Returns a Prolog source text representation of this Integer's value - * - * @return a Prolog source text representation of this Integer's value - */ - public String toString() { - return "" + value + ""; // hopefully invokes Integer.toString() or equivalent - } - - //------------------------------------------------------------------/ - // equals - /** - * Two Integer instances are equal if they are the same object, or if their values are equal - * - * @param obj The Object to compare (not necessarily an Integer) - * @return true if the Object satisfies the above condition - */ - public final boolean equals(Object obj) { - return this == obj || (obj instanceof Integer && value == ((Integer) obj).value); - } - - public final int type() { - return Prolog.INTEGER; - } - - public String typeName(){ - return "Integer"; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * Returns the int value of this jpl.Integer - * - * @return the Integer's value - * @deprecated - */ - public final int value() { - return (int) value; - } - - /** - * The (nonexistent) args of this Integer - * - * @return the (nonexistent) args of this Integer - * @deprecated - */ - public Term[] args() { - return new Term[] { - }; - } - - /** - * Returns a debug-friendly representation of this Integer's value - * - * @return a debug-friendly representation of this Integer's value - * @deprecated - */ - public String debugString() { - return "(Integer " + toString() + ")"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - //==================================================================/ - - /** - * To convert an Integer into a Prolog term, we put its value into the term_t. - * - * @param varnames_to_vars A Map from variable names to Prolog variables. - * @param term A (previously created) term_t which is to be - * set to a Prolog integer - */ - protected final void put(Map varnames_to_vars, term_t term) { - Prolog.put_integer(term, value); - } - - //==================================================================/ - // Converting Prolog terms to JPL Terms - //==================================================================/ - - /** - * Converts a Prolog term (known to be an integer) to a new Integer instance. - * - * @param vars_to_Vars A Map from Prolog variables to JPL Variables - * @param term The Prolog term (an integer) which is to be converted - * @return A new Integer instance - */ - protected static Term getTerm(Map vars_to_Vars, term_t term) { - IntHolder int_holder = new IntHolder(); - - Prolog.get_integer(term, int_holder); // assume it succeeds... - return new jpl.Integer(int_holder.value); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - /** - * Nothing needs to be done if the Term is an Atom, Integer or Float - * - * @param varnames_to_Terms A Map from variable names to Terms. - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - */ - protected final void getSubst(Map varnames_to_Terms, Map vars_to_Vars) { - } - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/JBoolean.java b/Jpl/jsrc/30/jpl/JBoolean.java deleted file mode 100644 index 19a8ec3e10..0000000000 --- a/Jpl/jsrc/30/jpl/JBoolean.java +++ /dev/null @@ -1,217 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Map; - -import jpl.fli.BooleanHolder; -import jpl.fli.Prolog; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// JBoolean -/** - * A jpl.JBoolean is a specialised Term with a boolean field, representing JPL's Prolog representation of a Java boolean value. - *
    - * JBoolean b = new JBoolean( true or false );
    - * 
    - * A JBoolean can be used (and re-used) in Compound Terms. - * - *
    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -public class JBoolean extends Term { - - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the JBoolean's value (a boolean) - */ - protected final boolean value; - - //==================================================================/ - // Constructors - //==================================================================/ - - /** - * Constructs a JBoolean with the supplied boolean value. - * - * @param b this JBoolean's value (a boolean) - */ - public JBoolean(boolean b) { - this.value = b; - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - /** - * Tests whether this JBoolean's functor has (String) 'name' and 'arity' - * - * @return whether this JBoolean's functor has (String) 'name' and 'arity' - */ - public final boolean hasFunctor(String name, int arity) { - return name.equals("@") && arity==1; - } - - /** - * Returns a Prolog source text representation of this JBoolean - * - * @return a Prolog source text representation of this JBoolean - */ - public String toString() { - return (value ? "@(true)" : "@(false)"); - } - - /** - * Two JBooleans are equal if their values are equal - * - * @param obj The Object to compare (not necessarily a JBoolean) - * @return true if the Object satisfies the above condition - */ - public final boolean equals(Object obj) { - return this == obj || (obj instanceof JBoolean && value == ((JBoolean) obj).value); - } - - //==================================================================/ - // Methods (peculiar) - //==================================================================/ - - /** - * The boolean value which this jpl.JBoolean object represents - * - * @return the boolean value which this jpl.JBoolean object represents - */ - public boolean boolValue() { - return value; - } - - public final int type() { - return Prolog.JBOOLEAN; - } - - public String typeName(){ - return "JBoolean"; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * The (nonexistent) args of this JBoolean - * - * @return the (nonexistent) args of this JBoolean - * @deprecated - */ - public Term[] args() { - throw new JPLException("jpl.JBoolean.args() is undefined"); - } - - /** - * Returns a debug-friendly representation of this JBoolean - * - * @return a debug-friendly representation of this JBoolean - * @deprecated - */ - public String debugString() { - return "(JBoolean " + toString() + ")"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - //==================================================================/ - - /** - * To convert a JBoolean to a term, we unify the (freshly created, hence unbound) - * term_t with either @(false) or @(true) as appropriate. - * - * @param varnames_to_vars A Map from variable names to Prolog variables. - * @param term A (newly created) term_t which is to be - * set to a Prolog @(false) or @(true) structure denoting the - * .value of this JBoolean instance - */ - protected final void put(Map varnames_to_vars, term_t term) { - Prolog.put_jboolean(term, value); - } - - //==================================================================/ - // Converting Prolog terms to JPL Terms - //==================================================================/ - - /** - * Converts a term_t to a JBoolean. If the Prolog term is either - * @(false) or @(true), we just create a new JBoolean with a corresponding value. - * NB This conversion is only invoked if "JPL-aware" term import is specified. - * - * @param vars_to_Vars A Map from Prolog variable to JPL Variables. - * @param term The term (either @(false) or @(true)) to convert - * @return A new JBoolean instance - */ - protected static Term getTerm(Map vars_to_Vars, term_t term) { - BooleanHolder b = new BooleanHolder(); - - Prolog.get_jboolean(term, b); // assume it succeeds... - return new jpl.JBoolean(b.value); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - /** - * Nothing needs to be done if the Term denotes an Atom, Integer, Float, JRef or JBoolean - * - * @param varnames_to_Terms A Map from variable names to Terms. - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - */ - protected final void getSubst(Map varnames_to_Terms, Map vars_to_Vars) { - } - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/JPL.java b/Jpl/jsrc/30/jpl/JPL.java deleted file mode 100644 index 3b80810518..0000000000 --- a/Jpl/jsrc/30/jpl/JPL.java +++ /dev/null @@ -1,199 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import jpl.fli.Prolog; - -//----------------------------------------------------------------------/ -// JPL -/** - * The jpl.JPL class contains methods which allow (i) inspection and alteration - * of the "default" initialisation arguments (ii) explicit initialisation - * (iii) discovery of whether the Prolog engine is already initialised, - * and if so, with what arguments. - * The Prolog engine must be initialized - * before any queries are made, but this will happen automatically - * (upon the first call to a Prolog FLI routine) if it has not already - * been done explicitly. - * - *
    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -public class JPL { - protected static final boolean DEBUG = false; - - protected static boolean modeDontTellMe = true; - - //------------------------------------------------------------------/ - // setDTMMode - /** - * Sets the global "dont-tell-me" mode (default value: true). - * When 'true', bindings will *not* be returned for any variable (in a Query's goal) - * whose name begins with an underscore character (except for "anonymous" variables, - * i.e. those whose name comprises just the underscore character, whose bindings are never returned). - * When 'false', bindings are returned for *all* variables except anonymous ones; - * this mode may be useful when traditional top-level interpreter behaviour is wanted, - * e.g. in a Java-based Prolog IDE or debugger.

    - * This method should be regarded as experimental, and may subsequently be deprecated - * in favour of some more general mechanism for setting options, perhaps per-Query and - * per-call as well as globally. - * - * @param dtm new "dont-tell-me" mode value - */ - public static void setDTMMode( boolean dtm){ - modeDontTellMe = dtm; - } - - //------------------------------------------------------------------/ - // getDefaultInitArgs - /** - * Returns, in an array of String, the sequence of command-line - * arguments that would be used if the Prolog engine were to be initialised now. - * Returns null if the Prolog VM has already been initialised (in which - * case the default init args are irrelevant and the actual init args are of interest)

    - * - * @see jpl.JPL#getActualInitArgs - * @return current default initialisation arguments, or null if already initialised - */ - public static String[] getDefaultInitArgs() { - return Prolog.get_default_init_args(); - } - - //------------------------------------------------------------------/ - // setDefaultInitArgs - /** - * Specifies, in an array of String, the sequence of command-line - * arguments that should be used if the Prolog engine is subsequently initialised.

    - * - * @param args new default initialization arguments - */ - public static void setDefaultInitArgs(String[] args) { - Prolog.set_default_init_args(args); - } - - //------------------------------------------------------------------/ - // getActualInitArgs - /** - * Returns, in an array of String, the sequence of command-line - * arguments that were actually used when the Prolog engine was formerly initialised. - * - * This method returns null if the Prolog engine has not yet been initialised, - * and thus may be used to test this condition. - * - * @return actual initialization arguments - */ - public static String[] getActualInitArgs() { - return Prolog.get_actual_init_args(); - } - - //------------------------------------------------------------------/ - // init - /** - * Initializes the Prolog engine, using the String argument - * parameters passed. This method need be called only if you want to both - * (i) initialise the Prolog engine with parameters other than the default ones - * and (ii) force initialisation to occur - * (rather than allow it to occur automatically at the first query). - * For parameter options, consult your local - * Prolog documentation. The parameter values are passed directly - * to initialization routines for the Prolog environment.

    - * - * This method must be called before making any queries. - * - * @param args Initialization parameter list - */ - public static boolean init(String[] args) { - return Prolog.set_default_init_args(args) && init(); - } - - //------------------------------------------------------------------/ - // init - /** - * Initialises the Prolog engine using the current default initialisation parameters, - * and returns 'true' (or 'false' if already initialised). - */ - public static boolean init() { - return Prolog.initialise(); - } - - //------------------------------------------------------------------/ - // halt - /** - * Terminates the Prolog session.

    - * - * Note. This method calls the FLI halt() method with a - * status of 0, but the halt method currently is a no-op in SWI. - * @deprecated - */ - public static void halt() { - Prolog.halt(0); - } - - // a static reference to the current Version - private static final Version version_ = new Version(); - - //------------------------------------------------------------------/ - // version - /** - * Returns (as a Version) an identification of this version of JPL. - * @return the running version of JPL. - */ - public static Version version() { - return version_; - } - - //------------------------------------------------------------------/ - // version_string - /** - * Returns a String (eg "3.0.0-alpha") identifying this version of JPL. - * @return a String (eg "3.0.0-alpha") identifying this version of JPL. - */ - public static String version_string() { - return version_.major + "." + version_.minor + "." + version_.patch + "-" + version_.status; - } - - public static void main(String[] args) { - System.out.println(version_string()); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/JPLException.java b/Jpl/jsrc/30/jpl/JPLException.java deleted file mode 100644 index d2df1be75b..0000000000 --- a/Jpl/jsrc/30/jpl/JPLException.java +++ /dev/null @@ -1,61 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -//----------------------------------------------------------------------/ -// JPLException -/** - * This is the base class for exceptions thrown by JPL's Java-calls-Prolog interface. - * Such exceptions represent errors and exceptional conditions within the interface code itself; - * see jpl.PrologException for the way Prolog exceptions are returned to calling Java code. - *


    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -public class JPLException extends RuntimeException { - public JPLException() { - super(); - } - - public JPLException(String s) { - super(s); - } -} diff --git a/Jpl/jsrc/30/jpl/JRef.java b/Jpl/jsrc/30/jpl/JRef.java deleted file mode 100644 index 69d9e7f5d0..0000000000 --- a/Jpl/jsrc/30/jpl/JRef.java +++ /dev/null @@ -1,215 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Map; - -import jpl.fli.ObjectHolder; -import jpl.fli.Prolog; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// JRef -/** - * JRef is a specialised Term with an Object field, representing JPL's Prolog references to Java objects (or to null). - *
    - * JRef r = new JRef( non_String_object_or_null );
    - * 
    - * A JRef can be used (and re-used) in Compound Terms. - * - *
    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -public class JRef extends Term { - - //==================================================================/ - // Attributes - //==================================================================/ - - /** - * the JRef's value (a non-String Object or null) - */ - protected final Object ref; - - //==================================================================/ - // Constructors - //==================================================================/ - - /** - * This constructor creates a JRef, initialized with the supplied - * non-String object (or null). - * - * @param ref this JRef's value (a non-String object, or null) - */ - public JRef(Object ref) { - if (ref instanceof String) { - throw new JPLException("a JRef cannot have a String value (String maps to atom)"); - } else { - this.ref = ref; - } - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - /** - * Returns a Prolog source text representation of this JRef - * - * @return a Prolog source text representation of this JRef - */ - public String toString() { - return "" + ref + ""; // WRONG - } - - /** - * Two JRefs are equal if their references are identical (?) - * - * @param obj The Object to compare - * @return true if the Object satisfies the above condition - */ - public final boolean equals(Object obj) { - return this == obj || (obj instanceof JRef && ref == ((JRef) obj).ref); - } - - public final int type() { - return Prolog.JREF; - } - - public String typeName(){ - return "JRef"; - } - - //==================================================================/ - // Methods (peculiar) - //==================================================================/ - - /** - * The non-String object (or null) which this jpl.JRef represents - * - * @return the non-String object (or null) which this jpl.JRef represents - */ - public Object ref() { - return ref; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * The (nonexistent) args of this JRef - * - * @return the (nonexistent) args of this JRef - * @deprecated - */ - public Term[] args() { - return new Term[] { - }; - } - - /** - * Returns a debug-friendly representation of this JRef - * - * @return a debug-friendly representation of this JRef - * @deprecated - */ - public String debugString() { - return "(JRef " + toString() + ")"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - //==================================================================/ - - /** - * To convert a JRef to a term, we put its Object field (.value) into the - * term_t as a JPL ref (i.e. @/1) structure. - * - * @param varnames_to_vars A Map from variable names to Prolog variables. - * @param term A (newly created) term_t which is to be - * set to a Prolog 'ref' (i.e. @/1) structure denoting the - * .value of this JRef instance - */ - protected final void put(Map varnames_to_vars, term_t term) { - - Prolog.put_jref(term, ref); - } - - //==================================================================/ - // Converting Prolog terms to JPL Terms - //==================================================================/ - - /** - * Converts a term_t to a JRef. Assuming the Prolog term is a - * ref, we just create a new JRef using the term_t's value. - * NB This conversion is only invoked if "JPL-aware" term import is specified. - * - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - * @param term The term (a ref) to convert - * @return A new JRef instance - */ - protected static Term getTerm(Map vars_to_Vars, term_t term) { - ObjectHolder obj = new ObjectHolder(); - - Prolog.get_jref(term, obj); // assume it succeeds... - return new jpl.JRef(obj.value); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - /** - * Nothing needs to be done if the Term is an Atom, Integer, Float or JRef - * - * @param varnames_to_Terms A Map from variable names to Terms. - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - */ - protected final void getSubst(Map varnames_to_Terms, Map vars_to_Vars) { - } - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/JVoid.java b/Jpl/jsrc/30/jpl/JVoid.java deleted file mode 100644 index 7c395da15c..0000000000 --- a/Jpl/jsrc/30/jpl/JVoid.java +++ /dev/null @@ -1,185 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Map; - -import jpl.fli.Prolog; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// JVoid -/** - * A jpl.JVoid is a specialised Term. Instances of this class - * denote JPL 'jvoid' values in Prolog, i.e. @(void): - *
    - * JVoid b = new JVoid();
    - * 
    - * A JVoid can be used (and re-used) in Compound Terms. - * - *
    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - * @see jpl.Term - * @see jpl.Compound - */ -public class JVoid extends Term { - - //==================================================================/ - // Attributes (none) - //==================================================================/ - - //==================================================================/ - // Constructors - //==================================================================/ - - /** - * This constructor creates a JVoid. - * - */ - public JVoid() { - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - /** - * Returns a Prolog source text representation of this JVoid - * - * @return a Prolog source text representation of this JVoid - */ - public String toString() { - return "@(void)"; - } - - /** - * Two JVoids are equal - * - * @param obj The Object to compare (not necessarily another JVoid) - * @return true if the Object satisfies the above condition - */ - public final boolean equals(Object obj) { - return this == obj || (obj instanceof JVoid); - } - - public final int type() { - return Prolog.JVOID; - } - - public String typeName(){ - return "JVoid"; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * The (nonexistent) args of this JVoid - * - * @return the (nonexistent) args of this JVoid - * @deprecated - */ - public Term[] args() { - return new Term[] {}; - } - - /** - * Returns a debug-friendly representation of this JVoid - * - * @return a debug-friendly representation of this JVoid - * @deprecated - */ - public String debugString() { - return "(JVoid)"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - //==================================================================/ - - /** - * To convert a JVoid to a term, we unify the (freshly created, hence unbound) - * term_t with @(void). - * - * @param varnames_to_vars A Map from variable names to Prolog variables. - * @param term A (previously created and unbound) term_t which is to be - * assigned a Prolog @(void) structure - */ - protected final void put(Map varnames_to_vars, term_t term) { - Prolog.put_jvoid(term); - } - - //==================================================================/ - // Converting Prolog terms to JPL Terms - //==================================================================/ - - /** - * Converts a term_t to a JVoid. Assuming the Prolog term to be - * @(void), we just create a new JVoid instance. - * NB This conversion is only invoked if "JPL-aware" term import is specified. - * - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - * @param term The term_t to convert - * @return A new JVoid instance - */ - protected static Term getTerm(Map vars_to_Vars, term_t term) { - return new jpl.JVoid(); - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - /** - * Nothing needs to be done if the Term denotes an Atom, Integer, Float, JRef, JBoolean or JVoid - * - * @param varnames_to_Terms A Map from variable names to Terms. - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - * Variables. - */ - protected final void getSubst(Map varnames_to_Terms, Map vars_to_Vars) { - } - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/PrologException.java b/Jpl/jsrc/30/jpl/PrologException.java deleted file mode 100644 index 6c2caef235..0000000000 --- a/Jpl/jsrc/30/jpl/PrologException.java +++ /dev/null @@ -1,74 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -//----------------------------------------------------------------------/ -// PrologException -/** - * PrologException instances wrap Prolog exceptions thrown (either by a Prolog engine or by user code) - * in the course of finding a solution to a Query. See JPLException for the handling of errors within the JPL Java-calls-Prolog interface. - *

    - * This class allows Java code which uses JPL's Java-calls-Prolog API to handle - * Prolog exceptions, which is in general necessary for hybrid Java+Prolog programming. - *

    - * Use the term() accessor to obtain a Term representation of the term that was - * thrown from within Prolog. - * - *


    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -public final class PrologException extends JPLException { - private Term term_ = null; - - protected PrologException(Term term) { - super("PrologException: " + term.toString()); - - this.term_ = term; - } - - /** - * @return a reference to the Term thrown by the call to throw/1 - */ - public Term term() { - return this.term_; - } -} diff --git a/Jpl/jsrc/30/jpl/Query.java b/Jpl/jsrc/30/jpl/Query.java deleted file mode 100644 index 96c33f19a3..0000000000 --- a/Jpl/jsrc/30/jpl/Query.java +++ /dev/null @@ -1,791 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Map; -import java.util.Vector; - -import jpl.fli.*; - -//----------------------------------------------------------------------/ -// Query -/** - * A Query instance is created by an application in order to query the Prolog engine. - * It is initialised with a - * Compound (or Atom) denoting the goal which is to be called, and also contains assorted private state - * relating to solutions. In some future version, it will contain details of the module - * in which the goal is to be called.

    - * A Query is either open or closed: when closed, it has no connection to the Prolog engine; - * when open, it is linked to an active goal within the Prolog engine. - * Only one Query can be open at any one time

    - * The Query class implements the Enumeration interface, and it is - * through this interface that one obtains successive solutions. The Enumeration - * hasMoreElements() method returns true if the call or redo succeeded (otherwise - * false), and if the call or redo did succeed, the nextElement() method returns - * a Hashtable representing variable bindings; the elements in the - * Hashtable are Terms, indexed by the Variables with which they are associated. - * For example, if p(a) and p(b) are facts in the Prolog - * database, then the following is equivalent to printing all - * the solutions to the Prolog query p(X): - *

    - * Variable X = new Variable();
    - * Term arg[] = { X };
    - * Query    q = new Query( "p", arg );
    - * 
    - * while ( q.hasMoreElements() ){
    - *     Term bound_to_x = ((Hashtable)q.nextElement()).get( X );
    - *     System.out.println( bound_to_x );
    - * }
    - * 
    - * Make sure to close the Query (using the rewind() method) if you do not need - * any further solutions which it may have. - * It is safe (although redundant) to close a Query whose solutions are already exhausted, - * or which is already closed. - * - * To obtain just one solution from a Query, use the oneSolution() method. - * - * To obtain all solutions, use the allSolutions() method. - * - * To determine merely whether the Query is provable, - * use the query() method (soon to be deprecated in favour of hasSolution()). - * (i.e. has at least one solution). - *
    - * - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin - *

    - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - * - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class Query implements Enumeration { - - //==================================================================/ - // Attributes - //==================================================================/ - - private static Map m = new Hashtable(); // maps (engine_t) engine handle to (Query) topmost query - - /** - * the Compound (hence perhaps an Atom, but not Integer, Float or Variable) corresponding to the goal of this Query - */ - protected final Compound goal_; // set by all initialisers - protected final String hostModule = "user"; // until revised constructors allow this to be specified - protected final String contextModule = "user"; // until revised constructors allow this to be specified - - /** - * @deprecated Use .goal().name() instead. - * @return the name of this Query's goal (redundant, deprecated) - */ - public final String name() { - return goal_.name(); // it can only be a Compound or Atom - } - - /** - * @deprecated Use .goal().args() instead. - * @return the arguments of this Query's goal (redundant, deprecated) - */ - public final Term[] args() { - return goal_.args(); - } - - /** - * Returns the Compound (hence perhaps an Atom) which is the goal of this Query - * @return a Term representing the goal of this Query - */ - public final Compound goal() { - return goal_; - } - - //==================================================================/ - // Constructors and Initialization - //==================================================================/ - - //------------------------------------------------------------------/ - // Query - /** - * This constructor creates a Query whose goal is the specified Term. - * The Query is initially closed. - * NB Creating an instance of the Query class does not - * result in a call to a Prolog engine. - * NB The goal can be an Atom (Atom extends Compound), but cannot be an instance - * of jpl.Float, jpl.Integer or jpl.Variable. - * @param t the goal of this Query - */ - public Query(Term t) { // formerly insisted (confusingly) on a Compound (or Atom) - this.goal_ = Query1( t); - } - - private Compound Query1( Term t ) { - if (t instanceof Compound) { - return (Compound) t; - } else if (t instanceof Integer) { - throw new JPLException("a Query's goal must be an Atom or Compound (not an Integer)"); - } else if (t instanceof Float) { - throw new JPLException("a Query's goal must be an Atom or Compound (not a Float)"); - } else if (t instanceof Variable) { - throw new JPLException("a Query's goal must be an Atom or Compound (not a Variable)"); - } else { - throw new JPLException("a Query's goal must be an Atom or Compound"); - } - } - - // Query - /** - * If text denotes an atom, this constructor is shorthand for - * new Query(new Compound(name,args)), - * but if text denotes a term containing N query symbols - * and there are N args, each query is replaced by its corresponding arg - * to provide the new Query's goal. - * - * @param text the name of the principal functor of this Query's goal - * @param args the arguments of this Query's goal - */ - public Query(String text, Term[] args) { - this(Query1(text, args)); - } - - // convenience case for a single arg - public Query(String text, Term arg) { - this(Query1(text, new Term[] {arg})); - } - - private static Term Query1( String text, Term[] args) { - Term t = Util.textToTerm(text); - if ( t instanceof Atom ){ - return new Compound(text,args); - } else { - return t.putParams(args); - } - } - - // Query - /** - * This constructor builds a Query from the given Prolog source text - * - * @param text the Prolog source text of this Query - */ - public Query(String text) { - this(Util.textToTerm(text)); - } - - //==================================================================/ - // Making Prolog Queries - //==================================================================/ - - /** - * These variables are used and set across the hasMoreElements - * and nextElement Enumeration interface implementation - */ - private boolean open = false; - // the following state variables are used and defined only if this query is open: - private boolean called = false; // open/get/close vs. hasMoreSolutions/nextSolution - private engine_t engine = null; // handle of attached Prolog engine iff open, else null - private Query subQuery = null; // the open Query (if any) on top of which this open Query is stacked, else null - private predicate_t predicate = null; // handle of this Query's predicate iff open, else undefined - private fid_t fid = null; // id of current Prolog foreign frame iff open, else null - private term_t term0 = null; // term refs of this Query's args iff open, else undefined - private qid_t qid = null; // id of current Prolog query iff open, else null - - //------------------------------------------------------------------/ - // hasMoreSolutions - /** - * This method returns true if JPL was able to initiate a "call" of this - * Query within the Prolog engine. It is designed to be used - * with the nextSolution() method to retrieve one or - * more substitutions in the form of Hashtables. To iterate through - * all the solutions to a Query, for example, one might write - *
    -	 * Query q = // obtain Query reference
    -	 * while ( q.hasMoreSolutions() ){
    -	 *     Hashtable solution = q.nextSolution();
    -	 *     // process solution...
    -	 * }
    -	 * 
    - * To ensure thread-safety, you should wrap sequential calls to - * this method in a synchronized block, using the static - * lock method to obtain the monitor. - *
    -	 * Query q = // obtain Query reference
    -	 * synchronized ( jpl.Query.lock() ){
    -	 *     while ( q.hasMoreElements() ){
    -	 *          Hashtable solution = q.nextSolution();
    -	 *          // process solution...
    -	 *     }
    -	 * }
    -	 * 
    - *

    - * If this method is called on an already-open Query, - * or while another Query is open, then a - * QueryInProgressException will be thrown, containing a reference to the currently - * open Query. - * - * @return true if the Prolog query succeeds; otherwise false. - */ - public synchronized final boolean hasMoreSolutions() { - - if (!open) { - open(); - } - return get1(); - } - - //------------------------------------------------------------------/ - // open - /** - * This method returns true if JPL was able to initiate a "call" of this - * Query within the Prolog engine. It is designed to be used - * with the getSolution() and close() methods to retrieve one or - * more substitutions in the form of Hashtables. - * To ensure thread-safety, you should wrap sequential calls to - * this method in a synchronized block, using the static - * lock method to obtain the monitor. - *

    -	 * Query q = // obtain Query reference
    -	 * synchronized ( jpl.Query.lock() ){
    -	 *     while ( q.hasMoreElements() ){
    -	 *          Hashtable solution = q.nextSolution();
    -	 *          // process solution...
    -	 *     }
    -	 * }
    -	 * 
    - *

    - * If this method is called on an already-open Query, - * or if the query cannot be set up for whatever reason, - * then a JPLException will be thrown. - */ - public synchronized final void open() { - - if (open) { - throw new JPLException("Query is already open"); - } - int self = Prolog.thread_self(); - // System.out.println("JPL thread_self()=" + self); - if (Prolog.thread_self() == -1) { // this Java thread has no attached Prolog engine? - engine = Prolog.attach_pool_engine(); // may block for a while, or fail - // System.out.println("JPL attaching engine[" + engine.value + "] for " + this.hashCode() + ":" + this.toString()); - } else { // this Java thread has an attached engine - engine = Prolog.current_engine(); - // System.out.println("JPL reusing engine[" + engine.value + "] for " + this.hashCode() + ":" + this.toString()); - } - if (m.containsKey(new Long(engine.value))) { - subQuery = (Query) m.get(new Long(engine.value)); // get this engine's previous topmost query - // System.out.println("JPL reusing engine[" + engine.value + "] pushing " + subQuery.hashCode() + ":" + subQuery.toString()); - } else { - subQuery = null; - } - m.put(new Long(engine.value), this); // update this engine's topmost query - predicate = Prolog.predicate(goal_.name(), goal_.args.length, hostModule); - fid = Prolog.open_foreign_frame(); // always succeeds? - Map varnames_to_vars = new Hashtable(); - term0 = Term.putTerms(varnames_to_vars, goal_.args); - // THINKS: invert varnames_to_Vars and use it when getting substitutions? - qid = Prolog.open_query(Prolog.new_module(Prolog.new_atom(contextModule)), Prolog.Q_NORMAL, predicate, term0); - open = true; - called = false; - } - - private final boolean get1() { - - // try to get the next solution; if none, close the query; - if (Prolog.next_solution(qid)) { - called = true; // OK to call get2() - return true; - } else { - // if failure was due to throw/1, build exception term and throw it - term_t exception_term_t = Prolog.exception(qid); - if (exception_term_t.value != 0L) { - Term exception_term = Term.getTerm(new Hashtable(), exception_term_t); - close(); - throw new PrologException(exception_term); - } else { - close(); - return false; - } - } - } - - //------------------------------------------------------------------/ - // getSolution - /** - * This method returns a java.util.Hashtable, which represents - * a set of bindings from the names of query variables to terms within the solution. - * The Hashtable contains instances of Terms, keyed on those - * Variables which were referenced in this Query's goal. - *

    - * For example, if a Query has an occurrence of a jpl.Variable, - * say, named X, one can obtain the Term bound to X in the solution - * by looking up X in the Hashtable. - *

    -	 * Variable X = new Variable();
    -	 * Query q = // obtain Query reference (with X in the Term array)
    -	 * while ( q.hasMoreSolutions() ){
    -	 *     Hashtable solution = q.nextSolution();
    -	 *     // make t the Term bound to X in the solution
    -	 *     Term t = (Term)solution.get( X );
    -	 *     // ...
    -	 * }
    -	 * 
    - * Programmers should obey the following rules when using this method. - * - *
  • The nextSolution() method should only be called after the - * hasMoreSolutions() method returns true; otherwise a JPLException - * will be raised, indicating that no Query is in progress. - *
  • The nextSolution() and hasMoreSolutions() should be called - * in the same thread of execution, at least for a given Query - * instance. - *
  • The nextSolution() method should not be called while - * another Thread is in the process of evaluating a Query. The - * JPL High-Level interface is designed to be thread safe, and - * is thread-safe as long as the previous two rules are obeyed. - *
  • - * - * This method will throw a JPLException if no query is in progress. - * It will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * - * @return A Hashtable representing a substitution, or null - */ - public synchronized final Hashtable getSolution() { - // oughta check: Query is open and thread has its engine - if (get1()) { - return get2(); - } else { - return null; - } - } - - public synchronized final Hashtable getSubstWithNameVars() { - // oughta check: Query is open and thread has its engine - if (get1()) { - return get2WithNameVars(); - } else { - return null; - } - } - - //------------------------------------------------------------------/ - // nextSolution - /** - * This method returns a java.util.Hashtable, which represents - * a binding from the names of query variables to terms within the solution. - * The Hashtable contains instances of Terms, keyed on those - * Variables which were referenced in this Query's goal. - *

    - * For example, if a Query has an occurrence of a jpl.Variable, - * say, named X, one can obtain the Term bound to X in the solution - * by looking up X in the Hashtable. - *

    -	 * Variable X = new Variable();
    -	 * Query q = // obtain Query reference (with X in the Term array)
    -	 * while ( q.hasMoreSolutions() ){
    -	 *     Hashtable solution = q.nextSolution();
    -	 *     // make t the Term bound to X in the solution
    -	 *     Term t = (Term)solution.get( X );
    -	 *     // ...
    -	 * }
    -	 * 
    - * Programmers should obey the following rules when using this method. - * - *
  • The nextSolution() method should only be called after the - * hasMoreSolutions() method returns true; otherwise a JPLException - * will be raised, indicating that no Query is in progress. - *
  • The nextSolution() and hasMoreSolutions() should be called - * in the same thread of execution, at least for a given Query - * instance. - *
  • The nextSolution() method should not be called while - * another Thread is in the process of evaluating a Query. The - * JPL High-Level interface is designed to be thread safe, and - * is thread-safe as long as the previous two rules are obeyed. - *
  • - * - * This method will throw a JPLException if no query is in progress. - * It will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * - * @return A Hashtable representing a substitution. - */ - public synchronized final Hashtable nextSolution() { - return get2(); - } - - private final Hashtable get2() { - if (!open) { - throw new JPLException("Query is not open"); - } else { - Hashtable substitution = new Hashtable(); - // NB I reckon computeSubstitutions needn't be in Term (but where else?) - Term.getSubsts(substitution, new Hashtable(), goal_.args); - return substitution; - } - } - - // assumes that Query's last arg is a Variable which will be bound to a [Name=Var,..] dict - private final Hashtable get2WithNameVars() { - if (!open) { - throw new JPLException("Query is not open"); - } else { - Term[] args = goal_.args; // for slight convenience below - Term argNV = args[args.length - 1]; // the Query's last arg - String nameNV = ((Variable) argNV).name; // its name - - // get the [Name=Var,..] dict from the last arg - Map varnames_to_Terms1 = new Hashtable(); - Map vars_to_Vars1 = new Hashtable(); - args[args.length - 1].getSubst(varnames_to_Terms1, vars_to_Vars1); - - Hashtable varnames_to_Terms2 = new Hashtable(); - Term nvs = (Term) varnames_to_Terms1.get(nameNV); - Map vars_to_Vars2 = Util.namevarsToMap(nvs); - for (int i = 0; i < args.length - 1; ++i) { - args[i].getSubst(varnames_to_Terms2, vars_to_Vars2); - } - - return varnames_to_Terms2; - } - } - - //------------------------------------------------------------------/ - // hasMoreElements - /** - * This method is completes the java.util.Enumeration - * interface. It is a wrapper for hasMoreSolutions. - * - * @return true if the Prolog query succeeds; false, o/w. - */ - public synchronized final boolean hasMoreElements() { - return hasMoreSolutions(); - } - - //------------------------------------------------------------------/ - // nextElement - /** - * This method completes the java.util.Enumeration - * interface. It is a wrapper for nextSolution. - *

    - * This method will throw a QueryInProgressException if another Query - * (besides this one) is in progress while this method is called. - * - * @return A Hashtable representing a substitution. - */ - public synchronized final Object nextElement() { - return nextSolution(); - } - - public synchronized final void rewind() { - close(); - } - - //------------------------------------------------------------------/ - // close - /** - * This method is used to close an open query so that the query - * may be re-run, even if the Query's Enumeration has more - * elements. Calling rewind() on an exhausted Enumeration has - * no effect.

    - * - * Here is a way to get the first three solutions to a Query, - * while subsequently being able to use the same Query object to - * obtain new solutions: - *

    -	 * Query q = new Query( predicate, args );
    -	 * int i = 0;
    -	 * for ( int i = 0; i < 3 && q.hasMoreSolutions();  ++i ){
    -	 *     Hasthable sub = (Hashtable) q.nextSolution();
    -	 *     ...
    -	 * }
    -	 * q.close();
    -	 * 

    - */ - public synchronized final void close() { - if (!open) { - return; // it is not an error to attempt to close a closed Query - } - if (Prolog.thread_self() == -1) { - throw new JPLException("no engine is attached to this thread"); - } - if (Prolog.current_engine().value != engine.value) { - throw new JPLException("this Query's engine is not that which is attached to this thread"); - } - Query topmost = (Query) m.get(new Long(engine.value)); - if (topmost != this) { - throw new JPLException( - "this Query (" - + this.hashCode() - + ":" - + this.toString() - + ") is not topmost (" - + topmost.hashCode() - + ":" - + topmost.toString() - + ") within its engine[" - + engine.value - + "]"); - } - Prolog.close_query(qid); - qid = null; // for tidiness - Prolog.discard_foreign_frame(fid); - fid = null; // for tidiness - m.remove(new Long(engine.value)); - if (subQuery == null) { // only Query open in this engine? - if (Prolog.current_engine_is_pool()) { // this (Query's) engine is from the pool? - Prolog.release_pool_engine(); - // System.out.println("JPL releasing engine[" + engine.value + "]"); - } else { - // System.out.println("JPL leaving engine[" + engine.value + "]"); - } - } else { - m.put(new Long(engine.value), subQuery); - // System.out.println("JPL retaining engine[" + engine.value + "] popping subQuery(" + subQuery.hashCode() + ":" + subQuery.toString() + ")"); - } - // eid = -1; // for tidiness - engine = null; - subQuery = null; - open = false; - called = false; - - } - - //------------------------------------------------------------------/ - // allSolutions - /** - * calls the Query's goal to exhaustion and returns an array containing every solution - * (in the order in which they were found). - * @return an array of Hashtables (possibly none), each of which is a solution - * (in the order in which they were found) of the Query. - * NB in JPL 1.0.1, this method returned null when a Query had no solutions; - * in JPL 2.x.x it returns an emprt array (thus the length of the array is, in every case, - * the quantity of solutions).

    - * - * This method will throw a QueryInProgressException if this or another Query - * is already open. - * - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - public synchronized final Hashtable[] allSolutions() { - if (open) { - throw new JPLException("Query is already open"); - } else { - // get a vector of solutions: - Vector v = new Vector(); - while (hasMoreSolutions()) { - v.addElement(nextSolution()); - } - - // turn the vector into an array: - Hashtable solutions[] = new Hashtable[v.size()]; // 0 solutions -> Hashtable[0] - v.copyInto(solutions); - - return solutions; - } - } - - //------------------------------------------------------------------/ - // oneSolution - /** - * Returns the first solution, if any, as a (possibly empty) Hashtable. - * - * This method will throw a JPLException if this Query - * is already open, and the Query will remain open as before. - * Otherwise, upon return, the Query will be closed. - * @return the first solution, if the query has one, as a (possibly empty) Hashtable. - * If the return value is null, this means that the Query has no solutions.

    - * - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - public synchronized final Hashtable oneSolution() { - if (open) { - throw new JPLException("Query is already open"); - } else { - Hashtable solution = null; - if (hasMoreSolutions()) { - solution = nextSolution(); - } - rewind(); - return solution; - } - } - - //------------------------------------------------------------------/ - // query - /** - * @deprecated Use .hasSolution() instead. - * JPL will attempt to call this Query's goal within the attached Prolog engine. - * @return the provability of the Query, i.e. 'true' if it has at least - * one solution, 'false' if the call fails without finding a solution.

    - * - * Only the first solution (if there is one) will be found; - * any bindings will be discarded, and the Query will be closed.

    - * This method will throw a QueryInProgressException if this or another Query - * is already open. - * - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - public synchronized final boolean query() { - return oneSolution() != null; - } - - //------------------------------------------------------------------/ - // hasSolution - /** - * JPL will attempt to call this Query's goal within the attached Prolog engine. - * @return the provability of the Query, i.e. 'true' if it has at least - * one solution, 'false' if the call fails without finding a solution.

    - * - * Only the first solution (if there is one) will be found; - * any bindings will be discarded, and the Query will be closed.

    - * This method will throw a QueryInProgressException if this or another Query - * is already open. - * - * @see jpl.Query#hasMoreElements - * @see jpl.Query#nextElement - * @see jpl.Query#hasMoreSolutions - * @see jpl.Query#nextSolution - * @see jpl.Query#rewind - * @see jpl.Query#oneSolution - * @see jpl.Query#allSolutions - * @see jpl.Query#query - */ - public synchronized final boolean hasSolution() { - return oneSolution() != null; - } - - public final int abort() { - if (open) { - (new Thread(new Runnable() { - public void run() { - try { - int rc1 = Prolog.attach_engine(engine); - System.out.println("q.abort(): attach_engine() returns " + rc1); - int rc2 = Prolog.action_abort(); - System.out.println("q.abort(): action_abort() returns " + rc2); - // int rc3 = Prolog.release_pool_engine(); - // System.out.println("q.abort(): release_pool_engine() returns " + rc3); - } catch (Exception e) { - - } - } - })).start(); // call the query in a separate thread - /* - int rc0a = Prolog.pool_engine_id(this.engine); - System.out.println("q.abort(): this.engine has id=" + rc0a); - - engine_t e = Prolog.current_engine(); - System.out.println("q.abort(): " + (e == null ? "no current engine" : "current engine id=" + Prolog.pool_engine_id(e))); - - int rc0b = Prolog.release_pool_engine(); - System.err.println("q.abort(): release_pool_engine() returns " + rc0b); - - engine_t e2 = Prolog.current_engine(); - System.out.println("q.abort(): " + (e == null ? "no current engine" : "current engine id=" + Prolog.pool_engine_id(e2))); - - int rc1 = Prolog.attach_engine(this.engine); - System.out.println("q.abort(): attach_engine() returns " + rc1); - - engine_t e3 = Prolog.current_engine(); - System.out.println("q.abort(): " + (e == null ? "no current engine" : "current engine id=" + Prolog.pool_engine_id(e3))); - - int rc2 = Prolog.action_abort(); - System.out.println("q.abort(): action_abort() returns " + rc2); - - int rc3 = Prolog.release_pool_engine(); - System.out.println("q.abort(): release_pool_engine() returns " + rc3); - - int rc4 = Prolog.attach_engine(e); - System.out.println("q.abort(): attach_engine() returns " + rc4); - */ - return 0; - } else { - System.out.println("q.abort(): query is not open"); - return -1; - } - } - - //==================================================================/ - // misc - //==================================================================/ - - /** - * Returns the String representation of a Query. - * - * @return the String representation of a Query - */ - public String toString() { - return goal_.name + "( " + Term.toString(goal_.args) + " )"; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * Returns a debug-friendly representation of a Query - * - * @return a debug-friendly representation of a Query - * @deprecated - */ - public String debugString() { - return "(Query " + goal_.name + " " + Term.debugString(goal_.args) + ")"; - } -} diff --git a/Jpl/jsrc/30/jpl/Term.java b/Jpl/jsrc/30/jpl/Term.java deleted file mode 100644 index 81886e1517..0000000000 --- a/Jpl/jsrc/30/jpl/Term.java +++ /dev/null @@ -1,671 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Map; - -import jpl.fli.IntHolder; -import jpl.fli.Prolog; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// Term -/** - * Term is the abstract base class for - * Compound, Atom, Variable, Integer and Float, which comprise a Java-oriented concrete syntax for Prolog. - * You cannot create instances of Term directly; rather, you should create - * instances of Term's concrete subclasses. - * Alternatively, use textToTerm() to construct a Term from its conventional - * Prolog source text representation. - * - *


    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -public abstract class Term { - //==================================================================/ - // Attributes - //==================================================================/ - - //==================================================================/ - // Constructors - //==================================================================/ - - /** - * This default constructor is provided in order for subclasses - * to be able to define their own default constructors. - */ - protected Term() { - } - - //==================================================================/ - // Methods (abstract, common) - //==================================================================/ - - /** - * returns the ano-th (1+) argument of a (Compound) Term - * throws a JPLException for any other subclass - * - * @return the ano-th argument of a (Compound) Term - */ - public Term arg(int ano) { - throw new JPLException("jpl." + this.typeName() + ".arg() is undefined"); - }; - - /** - * Tests whether this Term's functor has (String) 'name' and 'arity' - * Returns false if called inappropriately - * - * @return whether this Term's functor has (String) 'name' and 'arity' - */ - public boolean hasFunctor(String name, int arity) { - return false; - } - - /** - * Tests whether this Term's functor has (int) 'name' and 'arity' - * Returns false if called inappropriately - * - * @return whether this Term's functor has (int) 'name' and 'arity' - */ - public boolean hasFunctor(int value, int arity) { - return false; - } - - /** - * Tests whether this Term's functor has (double) 'name' and 'arity' - * Returns false if called inappropriately - * - * @return whether this Term's functor has (double) 'name' and 'arity' - */ - public boolean hasFunctor(double value, int arity) { - return false; - } - - /** - * returns, as a String, the name of a Compound, Atom or Variable - * throws a JPLException from an Integer or Float - * - * @return the name of a Compound, Atom or Variable - */ - public String name() { - throw new JPLException("jpl." + this.typeName() + ".name() is undefined"); - }; - - /** - * returns, as an int, the arity of a Compound, Atom, Integer or Float - * throws a JPLException from a Variable - * - * @return the arity of a Compound, Atom, Integer or Float - */ - public int arity() { - throw new JPLException("jpl." + this.typeName() + ".arity() is undefined"); - }; - - /** - * returns the value (as an int) of an Integer or Float - * throws a JPLException from a Compound, Atom or Variable - * - * @return the value (as an int) of an Integer or Float - */ - public int intValue() { - throw new JPLException("jpl." + this.typeName() + ".intValue() is undefined"); - } - /** - * returns the value (as a long) of an Integer or Float - * throws a JPLException from a Compound, Atom or Variable - * - * @return the value (as a long) of an Integer or Float - */ - public long longValue() { - throw new JPLException("jpl." + this.typeName() + ".longValue() is undefined"); - } - /** - * returns the value (as a float) of an Integer or Float - * throws a JPLException from a Compound, Atom or Variable - * - * @return the value (as a float) of an Integer or Float - */ - public float floatValue() { - throw new JPLException("jpl." + this.typeName() + ".floatValue() is undefined"); - } - - /** - * returns the value (as a double) of an Integer or Float - * throws a JPLException from any other subclass - * - * @return the value (as an double) of an Integer or Float - */ - public double doubleValue() { - throw new JPLException("jpl." + this.typeName() + ".doubleValue() is undefined"); - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - /** - * returns the type of this term, as one of jpl.fli.Prolog.COMPOUND, .ATOM, .VARIABLE, .INTEGER, .FLOAT etc - * - * @return the type of this term, as one of jpl.fli.Prolog.COMPOUND, .ATOM, .VARIABLE, .INTEGER, .FLOAT etc - */ - public abstract int type(); - - /** - * returns the name of the type of this term, as one of "Compound", "Atom", "Variable", "Integer", "Float" etc - * - * @return the name of the type of this term, as one of "Compound", "Atom", "Variable", "Integer", "Float" etc - */ - public abstract String typeName(); - - /** - * whether this Term represents an atom - * - * @return whether this Term represents an atom - */ - public boolean isAtom() { - return this instanceof Atom; - } - - /** - * whether this Term represents a compound term - * - * @return whether this Term represents a compound atom - */ - public boolean isCompound() { - return this instanceof Compound; - } - - /** - * whether this Term represents an atom - * - * @return whether this Term represents an atom - */ - public boolean isFloat() { - return this instanceof Float; - } - - /** - * whether this Term represents an atom - * - * @return whether this Term represents an atom - */ - public boolean isInteger() { - return this instanceof Integer; - } - - /** - * whether this Term is a JBoolean - * - * @return whether this Term is a JBoolean - */ - public boolean isJBoolean() { - return this instanceof JBoolean; - } - - /** - * whether this Term is a JRef - * - * @return whether this Term is a JRef - */ - public boolean isJRef() { - return this instanceof JRef; - } - - /** - * whether this Term is a JVoid - * - * @return whether this Term is a JVoid - */ - public boolean isJVoid() { - return this instanceof JVoid; - } - - /** - * whether this Term is a variable - * - * @return whether this Term is a variable - */ - public boolean isVariable() { - return this instanceof Variable; - } - - public Term putParams(Term[] ps) { - IntHolder next = new IntHolder(); - next.value = 0; - Term t2 = this.putParams1(next, ps); - if (next.value != ps.length) { - throw new JPLException("Term.putParams: more actual params than formal"); - } - return t2; - } - - public Term putParams(Term plist) { - Term[] ps = plist.toTermArray(); - return putParams(ps); - } - - protected Term putParams1(IntHolder next, Term[] ps) { - switch (this.type()) { - case Prolog.COMPOUND : - return new Compound(this.name(), putParams2(this.args(), next, ps)); - case Prolog.ATOM : - if (this.name().equals("?")) { - if (next.value >= ps.length) { - throw new JPLException("Term.putParams: fewer actual params than formal params"); - } - return ps[next.value++]; - } // else drop through to default - default : - return this; - } - } - - static protected Term[] putParams2(Term[] ts, IntHolder next, Term[] ps) { - int n = ts.length; - Term[] ts2 = new Term[n]; - for (int i = 0; i < n; i++) { - ts2[i] = ts[i].putParams1(next, ps); - } - return ts2; - } - - /** - * the length of this list, iff it is one, else an exception is thrown - * - * @throws JPLException - * @return the length (as an int) of this list, iff it is one - */ - public int listLength() { - int len = 0; - - if (this.hasFunctor(".", 2)) { - return 1 + this.arg(2).listLength(); - } else if (this.hasFunctor("[]", 0)) { - return 0; - } else { - throw new JPLException("Term.listLength: term is not a list"); - } - } - - /** returns an array of terms which are the successive members of this list, if it is a list, else throws an exception - * - * @throws JPLException - * @return an array of terms which are the successive members of this list, if it is a list - */ - public Term[] toTermArray() { - try { - int len = this.listLength(); - Term[] ts = new Term[len]; - Term t = this; - - for (int i = 0; i < len; i++) { - ts[i] = t.arg(1); - t = t.arg(2); - } - return ts; - } catch (JPLException e) { - throw new JPLException("Term.toTermArray: term is not a proper list"); - } - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * returns, as a Term[], the arguments of a Compound - * returns an empty Term[] from an Atom, Integer or Float - * throws a JPLException from a Variable - * - * @return the arguments of a Compound as a Term[ - * @deprecated - */ - public abstract Term[] args(); - - /** - * Returns a debug-friendly representation of a Term - * - * @return a debug-friendly representation of a Term - * @deprecated - */ - public abstract String debugString(); - - /** - * Returns a debug-friendly representation of a list of Terms - * - * @return a debug-friendly representation of a list of Terms - * @deprecated - */ - public static String debugString(Term arg[]) { - String s = "["; - - for (int i = 0; i < arg.length; ++i) { - s += arg[i].debugString(); - if (i != arg.length - 1) { - s += ", "; - } - } - return s + "]"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - // - // To convert a Term to a term_t, we need to traverse the Term - // structure and build a corresponding Prolog term_t object. - // There are some issues: - // - // - Prolog term_ts rely on the *consecutive* nature of term_t - // references. In particular, to build a compound structure - // in the Prolog FLI, one must *first* determine the arity of the - // compound, create a *sequence* of term_t references, and then - // put atoms, functors, etc. into those term references. We - // do this in these methods by first determining the arity of the - // Compound, and then by "put"-ing a type into a term_t. - // The "put" method is implemented differently in each of Term's - // five subclasses. - // - // - What if we are trying to make a term_t from a Term, but the - // Term has multiple instances of the same Variable? We want - // to ensure that _one_ Prolog variable will be created, or else - // queries will give incorrect answers. We thus pass a Hashtable - // (var_table) through these methods. The table contains term_t - // instances, keyed on Variable instances. - //==================================================================/ - - /** - * Cache the reference to the Prolog term_t here. - * - * @param varnames_to_vars A Map from variable names to JPL Variables. - * @param term A (previously created) term_t which is to be - * put with a Prolog term-type appropriate to the Term type - * (e.g., Atom, Variable, Compound, etc.) on which the method is - * invoked.) - */ - protected abstract void put(Map varnames_to_vars, term_t term); - - /** - * This static method converts an array of Terms to a *consecutive* - * sequence of term_t objects. Note that the first term_t object - * returned is a term_t class (structure); the succeeding term_t - * objects are consecutive references obtained by incrementing the - * *value* field of the term_t. - * - * @param varnames_to_vars Map from variable names to JPL Variables. - * @param args An array of jpl.Term references. - * @return consecutive term_t references (first of which is - * a structure) - */ - protected static term_t putTerms(Map varnames_to_vars, Term[] args) { - - // first create a sequence of term_ts. The 0th term_t - // will be a jpl.fli.term_t. Successive Prolog term_t - // references will reside in the Prolog engine, and - // can be obtained by term0.value+i. - // - term_t term0 = Prolog.new_term_refs(args.length); - - // for each new term reference, construct a Prolog term - // by putting an appropriate Prolog type into the reference. - // - long ith_term_t = term0.value; - for (int i = 0; i < args.length; ++i, ++ith_term_t) { - term_t term = new term_t(); - term.value = ith_term_t; - args[i].put(varnames_to_vars, term); // each subclass defines its own put() - } - - return term0; - } - - //==================================================================/ - // Converting Prolog terms to JPL Terms - // - // Converting back from term_ts to Terms is simple, since - // the (simplified) Term representation is canonical (there is only one - // correct structure for any given Prolog term). - // - // One problem concerns variable bindings. We illustrate - // with several examples. First, consider the Prolog fact - // - // p( f(X,X)). - // - // And the query - // - // ?- p( Y). - // - // A solution should be - // - // y = f(X,X) - // - // and indeed, if this query is run, the term_t to which Y will - // be unified is a compound, f(X,X). The problem is, how do - // we know, in converting the term_ts to Terms in the compound f/2 - // whether we should create one Variable or two? This begs the - // question, how do we _identify_ Variables in JPL? The answer - // to the latter question is, by reference; two Variable (Java) - // references refer to the same variable iff they are, in memory, - // the same Variable object. That is, they satisfy the Java == relation. - // (Note that this condition is _not_ true of the other Term types.) - // - // Given this design decision, therefore, we should create a - // single Variable instance and a Compound instance whose two arg - // values refer to the same Variable object. We therefore need to keep - // track, in converting a term_t to a Term (in particular, in - // converting a term_t whose type is variable to a Variable), of - // which Variables have been created. We do this by using the vars - // Hashtable, which gets passed recursively though the from_term_t - // methods; this table holds the Variable instances that have been - // created, keyed by the unique and internal-to-Prolog string - // representation of the variable (I'm not sure about this...). - //==================================================================/ - - /** - * This method calls from_term_t on each term in the n consecutive term_ts. - * A temporary jpl.term_t "holder" (byref) structure must be created - * in order to extract type information from the Prolog engine. - * - * @param vars_to_Vars A Map from Prolog variables to jpl.Variable instances - * @param n The number of consecutive term_ts - * @param term0 The 0th term_t (structure); subsequent - * term_ts are not structures. - * @return An array of converted Terms - */ - /* - protected static Term[] from_term_ts(Map vars_to_Vars, int n, term_t term0) { - - // create an (uninitialised) array of n Term references - Term[] terms = new Term[n]; - - // for each term_t (from 0...n-1), create a term_t - // (temporary) structure and dispatch the translation - // to a Term to the static from_term_t method of the Term - // class. This will perform (Prolog) type analysis on the - // term_t and call the appropriate static method to create - // a Term of the right type (e.g., Atom, Variable, List, etc.) - // - long ith_term_t = term0.value; - for (int i = 0; i < n; ++i, ++ith_term_t) { - term_t term = new term_t(); - term.value = ith_term_t; - - terms[i] = Term.from_term_t(vars_to_Vars, term); - } - - return terms; - } - */ - - /** - * We discover the Prolog type of the term, then forward the - * call to the appropriate subclass - * - * @param vars A Map from Prolog variables to jpl.Variable instances - * @param term The Prolog term (in a term_t holder) to convert - * @return The converted Term subtype instance. - */ - protected static Term getTerm(Map vars_to_Vars, term_t term) { - int type = Prolog.term_type(term); - - switch (type) { - case Prolog.VARIABLE : - return Variable.getTerm(vars_to_Vars, term); - case Prolog.ATOM : - return Atom.getTerm(vars_to_Vars, term); - case Prolog.STRING : - return Atom.getString(vars_to_Vars, term); - case Prolog.INTEGER : - return Integer.getTerm(vars_to_Vars, term); - case Prolog.FLOAT : - return Float.getTerm(vars_to_Vars, term); - case Prolog.COMPOUND : - return Compound.getTerm(vars_to_Vars, term); - default : - // should never happen... - throw new JPLException("Term.from_term_t: unknown term type=" + type); - } - } - - //==================================================================/ - // Computing Substitutions - // - // Once a solution has been found, the Prolog term_t references - // will have been instantiated and will refer to new terms. To compute - // a substitution, we traverse the (original) Term structure, looking - // at the term_t reference in the Term. The only case we really care - // about is if the (original) Term is a Variable; if so, the term_t - // back in the Prolog engine may be instantiated (non Variable parts - // of the original Term cannot change or become uninstantiated). In - // this case, we can store this term in a Hashtable, keyed by the - // Variable with which the term was unified. - //==================================================================/ - - //------------------------------------------------------------------/ - // getSubst - /** - * This method computes a substitution from a Term. The bindings - * Hashtable stores Terms, keyed by Variables. Thus, a - * substitution is as it is in mathematical logic, a sequence - * of the form \sigma = {t_0/x_0, ..., t_n/x_n}. Once the - * substitution is computed, the substitution should satisfy - * - * \sigma T = t - * - * where T is the Term from which the substitution is computed, - * and t is the term_t which results from the Prolog query.

    - * - * A second Hashtable, vars, is required; this table holds - * the Variables that occur (thus far) in the unified term. - * The Variable instances in this table are guaranteed to be - * unique and are keyed on Strings which are Prolog internal - * representations of the variables. - * - * @param bindings table holding Term substitutions, keyed on - * Variables. - * @param vars A Hashtable holding the Variables that occur - * thus far in the term; keyed by internal (Prolog) string rep. - */ - protected abstract void getSubst(Map varnames_to_Terms, Map vars_to_Vars); - - //------------------------------------------------------------------/ - // getSubsts - /** - * Just calls computeSubstitution for each Term in the array. - * - * @param varnames_to_Terms a Map from variable names to Terms - * @param vars_to_Vars a Map from Prolog variables to JPL Variables - * @param arg a list of Terms - */ - protected static void getSubsts(Map varnames_to_Terms, Map vars_to_Vars, Term[] args) { - for (int i = 0; i < args.length; ++i) { - args[i].getSubst(varnames_to_Terms, vars_to_Vars); - } - } - - //------------------------------------------------------------------/ - // terms_equals - /** - * This method is used (by Compound.equals) to determine the Terms in two Term arrays - * are pairwise equal, where two Terms are equal if they satisfy - * the equals predicate (defined differently in each Term subclass). - * - * @param t1 an array of Terms - * @param t2 another array of Terms - * @return true if all of the Terms in the (same-length) arrays are pairwise equal - */ - protected static boolean terms_equals(Term[] t1, Term[] t2) { - if (t1.length != t2.length) { - return false; - } - - for (int i = 0; i < t1.length; ++i) { - if (!t1[i].equals(t2[i])) { - return false; - } - } - return true; - } - - //------------------------------------------------------------------/ - // toString - /** - * Converts a list of Terms to a String. - * - * @param args An array of Terms to convert - * @return String representation of a list of Terms - */ - public static String toString(Term[] args) { - String s = ""; - - for (int i = 0; i < args.length; ++i) { - s += args[i].toString(); - if (i != args.length - 1) { - s += ", "; - } - } - - return s; - } - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/Util.java b/Jpl/jsrc/30/jpl/Util.java deleted file mode 100644 index 6b5a6d9b46..0000000000 --- a/Jpl/jsrc/30/jpl/Util.java +++ /dev/null @@ -1,172 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Hashtable; -import java.util.Map; - -//----------------------------------------------------------------------/ -// Util -/** - * This class provides a bunch of static utility methods for the JPL - * High-Level Interface. - * - *


    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -public final class Util { - //------------------------------------------------------------------/ - // termArrayToList - /** - * Converts an array of Terms to a JPL representation of a Prolog list of terms - * whose members correspond to the respective array elements. - * - * @param terms An array of Term - * @return Term a list of the array elements - */ - public static Term termArrayToList(Term[] terms) { - Term list = new Atom("[]"); - - for (int i = terms.length - 1; i >= 0; --i) { - list = new Compound(".", new Term[] { terms[i], list }); - } - return list; - } - - /** - * Converts a solution hashtable to an array of Terms. - * - * @param varnames_to_Terms A Map from variable names to Terms - * @return Term[] An array of the Terms to which successive variables are bound - */ - public static Term[] bindingsToTermArray(Map varnames_to_Terms) { - Term[] ts = new Term[varnames_to_Terms.size()]; - - for (java.util.Iterator i = varnames_to_Terms.keySet().iterator(); i.hasNext();) { - Variable k = (Variable) i.next(); - ts[k.index] = (Term) (varnames_to_Terms.get(k)); - } - return ts; - } - - //------------------------------------------------------------------/ - // toString - /** - * Converts a substitution, in the form of a Map from variable names to Terms, to a String. - * - * @param varnames_to_Terms A Map from variable names to Terms. - * @return String A String representation of the variable bindings - */ - public static String toString(Map varnames_to_Terms) { - if (varnames_to_Terms == null) { - return "[no solution]"; - } - java.util.Iterator varnames = varnames_to_Terms.keySet().iterator(); - - String s = "Bindings: "; - while (varnames.hasNext()) { - String varname = (String) varnames.next(); - s += varname + "=" + varnames_to_Terms.get(varname).toString() + "; "; - } - return s; - } - - //------------------------------------------------------------------/ - // namevarsToMap - /** - * Converts a (JPL) list of Name=Var pairs (as yielded by atom_to_term/3) - * to a Map from Prolog variables (necessarily in term_t holders) to named JPL Variables - * - * @param nvs A JPL list of Name=Var pairs (as yielded by atom_to_term/3) - * @return Map A Map from Prolog variables (necessarily in term_t holders) to named JPL Variables - */ - public static Map namevarsToMap(Term nvs) { - - try { - Map vars_to_Vars = new Hashtable(); - - /* - while (nvs.hasFunctor(".", 2) && ((Compound) nvs).arg(1).hasFunctor("=", 2)) { - Atom name = (Atom) ((Compound) ((Compound) nvs).arg(1)).arg(1); // get the Name of the =/2 pair - Variable var = (Variable) ((Compound) ((Compound) nvs).arg(1)).arg(2); // get the Var of the =/2 pair - - vars_to_Vars.put(var.term_, new Variable(name.name())); // map the Prolog variable to a new, named Variable - nvs = ((Compound) nvs).arg(2); // advance to next list cell - } - */ - while (nvs.hasFunctor(".", 2) && nvs.arg(1).hasFunctor("=", 2)) { - // the cast to Variable is necessary to access the (protected) .term_ field - vars_to_Vars.put(((Variable)nvs.arg(1).arg(2)).term_, new Variable(nvs.arg(1).arg(1).name())); // map the Prolog variable to a new, named Variable - nvs = nvs.arg(2); // advance to next list cell - } - - // maybe oughta check that nvs is [] ? - return vars_to_Vars; - } catch (java.lang.ClassCastException e) { // nvs is not of the expected structure - return null; - } - } - - //------------------------------------------------------------------/ - // textToTerm - /** - * Converts a Prolog source text to a corresponding JPL Term - * (in which each Variable has the appropriate name from the source text). - * Throws PrologException containing error(syntax_error(_),_) if text is invalid. - * - * @param text A Prolog source text denoting a term - * @return Term a JPL Term equivalent to the given source text - */ - public static Term textToTerm(String text) { - // it might be better to use PL_chars_to_term() - Query q = new Query(new Compound("atom_to_term", new Term[] { new Atom(text), new Variable("Term"), new Variable("NVdict")})); - q.open(); - Map s = q.getSubstWithNameVars(); - if (s != null) { - q.close(); - return (Term) s.get("Term"); - } else { - return null; - } - } - -} diff --git a/Jpl/jsrc/30/jpl/Variable.java b/Jpl/jsrc/30/jpl/Variable.java deleted file mode 100644 index 0bb863646b..0000000000 --- a/Jpl/jsrc/30/jpl/Variable.java +++ /dev/null @@ -1,301 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 2004 Paul Singleton -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl; - -import java.util.Iterator; -import java.util.Map; - -import jpl.fli.Prolog; -import jpl.fli.term_t; - -//----------------------------------------------------------------------/ -// Variable -/** - * This class supports Java representations of Prolog variables.

    - * - * A jpl.Variable instance is equivalent to a variable in a fragment of Prolog source text: - * it is *not* a "live" variable within a Prolog stack or heap. - * A corresponding Prolog variable is created only upon opening - * a Query whose goal refers to a Variable (and then only temporarily). - * - *


    - * Copyright (C) 2004 Paul Singleton

    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class Variable extends Term { - - //==================================================================/ - // Attributes - //==================================================================/ - - private static long n = 0; // the integral part of the next automatic variable name to be allocated - - public final String name; // the name of this Variable - - protected transient term_t term_ = null; // defined between Query.open() and Query.get2() - protected transient int index; // only used by (redundant?) - - //==================================================================/ - // Constructors - //==================================================================/ - - /** - * Create a new Variable with 'name' (which must not be null or ""), - * and may one day be constrained to comply with traditional Prolog syntax. - * - * @param name the source name of this Variable - */ - public Variable(String name) { - if (name == null) { - throw new JPLException("constructor jpl.Variable(name): name cannot be null"); - } - if (!isValidName(name)) { - throw new JPLException("constructor jpl.Variable(name): name cannot be empty String"); - } - this.name = name; - } - - //==================================================================/ - // Constructors (deprecated) - //==================================================================/ - - /** - * Create a new Variable with new sequential name of the form "_261". - * - * @deprecated use Variable(String name) instead - */ - public Variable() { - this.name = "_" + Long.toString(n++); // e.g. _0, _1 etc. - } - - //==================================================================/ - // Methods (common) - //==================================================================/ - - /** - * returns the lexical name of this Variable - * - * @return the lexical name of this Variable - */ - public final String name() { - return this.name; - } - - /** - * Returns a Prolog source text representation of this Variable - * - * @return a Prolog source text representation of this Variable - */ - public String toString() { - return this.name; - } - - /** - * A Variable is equal to another if their names are the same and they are not anonymous. - * - * @param obj The Object to compare. - * @return true if the Object is a Variable and the above condition apply. - */ - public final boolean equals(Object obj) { - return obj instanceof Variable && !this.name.equals("_") && this.name.equals(((Variable) obj).name); - } - - public final int type() { - return Prolog.VARIABLE; - } - - public String typeName() { - return "Variable"; - } - - //==================================================================/ - // Methods (private) - //==================================================================/ - - /** - * Tests the lexical validity of s as a variable's name - * - * @return the lexical validity of s as a variable's name - * @deprecated - */ - private boolean isValidName(String s) { - if (s == null) { - throw new java.lang.NullPointerException(); // JPL won't call it this way - } - int len = s.length(); - if (len == 0) { - throw new JPLException("invalid variable name"); - } - char c = s.charAt(0); - if (!(c == '_' || c >= 'A' && c <= 'Z')) { - return false; - } - for (int i = 1; i < len; i++) { - c = s.charAt(i); - if (!(c == '_' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9')) { - return false; - } - } - return true; - } - - //==================================================================/ - // Methods (deprecated) - //==================================================================/ - - /** - * The (nonexistent) args of this Variable - * - * @return the (nonexistent) args of this Variable - * @deprecated - */ - public Term[] args() { - return new Term[] { - }; - } - - /** - * Returns a debug-friendly String representation of an Atom. - * - * @return a debug-friendly String representation of an Atom - * @deprecated - */ - public String debugString() { - return "(Variable " + toString() + ")"; - } - - //==================================================================/ - // Converting JPL Terms to Prolog terms - //==================================================================/ - - /** - * To put a Variable, we must check whether a (non-anonymous) variable with the same name - * has already been put in the Term. If one has, then the corresponding Prolog variable has - * been stashed in the varnames_to_vars Map, keyed by the Variable name, so we can look - * it up and reuse it (this way, the sharing of variables in the Prolog term - * reflects the sharing of Variable names in the Term. - * Otherwise, if this Variable name has not - * already been seen in the Term, then we put a new Prolog variable and add it into the Map - * (keyed by this Variable name). - * - * @param varnames_to_vars A Map from variable names to Prolog variables. - * @param term A (previously created) term_t which is to be - * set to a (new or reused) Prolog variable. - */ - protected final void put(Map varnames_to_vars, term_t term) { - term_t var; - // if this var is anonymous or as yet unseen, put a new Prolog variable - if (this.name.equals("_") || (var = (term_t) varnames_to_vars.get(this.name)) == null) { - this.term_ = term; - this.index = varnames_to_vars.size(); // i.e. first var in is #0 etc. - Prolog.put_variable(term); - if (!this.name.equals("_")) { - varnames_to_vars.put(this.name, term); - } - } else { - this.term_ = var; - Prolog.put_term(term, var); - } - } - - //==================================================================/ - // Converting Prolog terms to JPL Terms - //==================================================================/ - - /** - * Converts a term_t (known to refer to a Prolog variable) to a Variable. - * If the variable has already been seen (and hence converted), - * return its corresponding Variable from the map, - * else create a new Variable, stash it in the map (keyed by the Prolog variable), - * and return it. - * - * @param vars_to_Vars a map from Prolog to JPL variables - * @param var The term_t (known to be a variable) to convert - * @return A new or reused Variable - */ - protected static Term getTerm(Map vars_to_Vars, term_t var) { - - for (Iterator i = vars_to_Vars.keySet().iterator(); i.hasNext();) { - term_t varX = (term_t) i.next(); // a previously seen Prolog variable - if (Prolog.compare(varX, var) == 0) { // identical Prolog variables? - return (Term) vars_to_Vars.get(varX); // return the associated JPL Variable - } - } - // otherwise, the Prolog variable in term has not been seen before - Variable Var = new Variable(); // allocate a new (sequentially named) Variable to represent it - Var.term_ = var; // this should become redundant... - vars_to_Vars.put(var, Var); // use Hashtable(var,null), but only need set(var) - return Var; - } - - //==================================================================/ - // Computing Substitutions - //==================================================================/ - - /** - * If this Variable instance is not an anonymous or (in dont-tell-me mode) a dont-tell-me variable, and its binding is not already in the varnames_to_Terms Map, - * put the result of converting the term_t to which this variable - * has been unified to a Term in the Map, keyed on this Variable's name. - * - * @param varnames_to_Terms A Map of bindings from variable names to JPL Terms. - * @param vars_to_Vars A Map from Prolog variables to JPL Variables. - */ - protected final void getSubst(Map varnames_to_Terms, Map vars_to_Vars) { - // NB a Variable.name cannot be "" i.e. of 0 length - // if (!(this.name.charAt(0) == '_') && varnames_to_Terms.get(this.name) == null) { - if (tellThem() && varnames_to_Terms.get(this.name) == null) { - varnames_to_Terms.put(this.name, Term.getTerm(vars_to_Vars, this.term_)); - } - } - - // whether, according to prevailing policy and theis Variable's name, - // any binding should be returned - // (yes, unless it's anonymous or we're in dont-tell-me mode and its a dont-tell-me variable) - private final boolean tellThem() { - return !(this.name.equals("_") || jpl.JPL.modeDontTellMe && this.name.charAt(0) == '_'); - // return !this.name.equals("_"); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/Version.java b/Jpl/jsrc/30/jpl/Version.java deleted file mode 100644 index 1a2d1eb506..0000000000 --- a/Jpl/jsrc/30/jpl/Version.java +++ /dev/null @@ -1,9 +0,0 @@ -// $Id$ -package jpl; -class Version -{ - public final int major = 3; - public final int minor = 0; - public final int patch = 3; - public final String status = "alpha"; -} diff --git a/Jpl/jsrc/30/jpl/fli/BooleanHolder.java b/Jpl/jsrc/30/jpl/fli/BooleanHolder.java deleted file mode 100644 index 27b18f45a6..0000000000 --- a/Jpl/jsrc/30/jpl/fli/BooleanHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// BooleanHolder -/** - * A BooleanHolder is merely a Holder class for a boolean value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class BooleanHolder -{ - public boolean value; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/DoubleHolder.java b/Jpl/jsrc/30/jpl/fli/DoubleHolder.java deleted file mode 100644 index a9bd7e88ce..0000000000 --- a/Jpl/jsrc/30/jpl/fli/DoubleHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// DoubleHolder -/** - * A DoubleHolder is merely a Holder class for a double value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class DoubleHolder -{ - public double value; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/IntHolder.java b/Jpl/jsrc/30/jpl/fli/IntHolder.java deleted file mode 100644 index 85d1dea0f9..0000000000 --- a/Jpl/jsrc/30/jpl/fli/IntHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// IntHolder -/** - * An IntHolder is merely a Holder class for an Int value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class IntHolder -{ - public int value; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/LongHolder.java b/Jpl/jsrc/30/jpl/fli/LongHolder.java deleted file mode 100644 index c42fc6335a..0000000000 --- a/Jpl/jsrc/30/jpl/fli/LongHolder.java +++ /dev/null @@ -1,61 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - -//----------------------------------------------------------------------/ -// LongHolder -/** - * A Long Holder merely holds a long value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class LongHolder { - public long value = 0L; - - public boolean equals(LongHolder lh) { - return lh.value == this.value; - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/ObjectHolder.java b/Jpl/jsrc/30/jpl/fli/ObjectHolder.java deleted file mode 100644 index 0af52330a1..0000000000 --- a/Jpl/jsrc/30/jpl/fli/ObjectHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// ObjectHolder -/** - * A ObjectHolder is merely a Holder class for an Object reference (or null). - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class ObjectHolder -{ - public Object value; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/PointerHolder.java b/Jpl/jsrc/30/jpl/fli/PointerHolder.java deleted file mode 100644 index aad95c1561..0000000000 --- a/Jpl/jsrc/30/jpl/fli/PointerHolder.java +++ /dev/null @@ -1,63 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// PointerHolder -/** - * A PointerHolder is a trivial extension of a LongHolder. This is sort of - * a no-no in Java, as the long value stored herein is sometimes a - * machine address. (Don't tell Sun.) - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// There could be issues in the future with signedness, since Java -// does not have an unsigned type; make sure not to do any arithmetic -// with the stored value. -//----------------------------------------------------------------------/ -public class PointerHolder extends LongHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/Prolog.java b/Jpl/jsrc/30/jpl/fli/Prolog.java deleted file mode 100644 index 654f92b7e7..0000000000 --- a/Jpl/jsrc/30/jpl/fli/Prolog.java +++ /dev/null @@ -1,240 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - -//----------------------------------------------------------------------/ -// Prolog -/** - * This class consists only of constants (static finals) and static - * native methods. The constants and methods defined herein are in - * (almost) strict 1-1 correspondence with the functions in the Prolog - * FLI by the same name (except without the PL_, SQ_, etc. prefixes).

    - * - * See the file jpl_fli_Prolog.c for the native implementations of these - * methods. Refer to your local Prolog FLI documentations for the meanings - * of these methods, and observe the following:

    - * - *

    - *
  • The types and signatures of the following methods are almost - * in 1-1 correspondence with the Prolog FLI. The Prolog types - * term_t, atom_t, functor_t, etc. are mirrored in this package with - * classes by the same name, making the C and Java uses of these - * interfaces similar.
  • - *
  • As term_t, functor_t, etc. types are Java classes, they are - * passed to these methods by value; however, calling these - * methods on such class instances does have side effects. In general, - * the value fields of these instances will be modified, in much the - * same way the term_t, functor_t, etc. Prolog instances would be - * modified.
  • - *
  • The exceptions to this rule occur when maintaining the same - * signature would be impossible, e.g., when the Prolog FLI functions - * require pointers; in this case, the signatures have been - * modified to take *Holder classes (Int, Double, String, etc.), - * to indicate a call by reference parameter. - *
  • Functions which take variable-length argument lists in C - * take arrays in Java; from Java 1.1 onwards, anonymous arrays - * can be used e.g. Term[] { new Atom("a"), new Atom ("b") } - *
  • - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -public final class Prolog { - static { - System.loadLibrary("jpl"); - } - - /* term types */ - public static final int VARIABLE = 1; - public static final int ATOM = 2; - public static final int INTEGER = 3; - public static final int FLOAT = 4; - public static final int STRING = 5; - public static final int COMPOUND = 6; - - public static final int JBOOLEAN = 101; - public static final int JREF = 102; - public static final int JVOID = 103; - - /** - * @deprecated use Prolog.COMPOUND - */ - public static final int TERM = 6; - - public static final int succeed = 1; - public static final int fail = 0; - - /* query flags */ - public static final int Q_NORMAL = 0x02; - public static final int Q_NODEBUG = 0x04; - public static final int Q_CATCH_EXCEPTION = 0x08; - public static final int Q_PASS_EXCEPTION = 0x10; - - /* conversion flags */ - public static final int CVT_ATOM = 0x0001; - public static final int CVT_STRING = 0x0002; - public static final int CVT_LIST = 0x0004; - public static final int CVT_INTEGER = 0x0008; - public static final int CVT_FLOAT = 0x0010; - public static final int CVT_VARIABLE = 0x0020; - public static final int CVT_NUMBER = (CVT_INTEGER | CVT_FLOAT); - public static final int CVT_ATOMIC = (CVT_NUMBER | CVT_ATOM | CVT_STRING); - public static final int CVT_ALL = 0x00ff; - public static final int BUF_DISCARDABLE = 0x0000; - public static final int BUF_RING = 0x0100; - public static final int BUF_MALLOC = 0x0200; - - /* new, for revised term_t-to-Variable stuff */ - public static native int compare(term_t t1, term_t t2); // returns -1, 0 or 1 - - /* Creating and destroying term-refs */ - public static native term_t new_term_ref(); - public static native term_t new_term_refs(int n); - public static native term_t copy_term_ref(term_t from); - public static native void reset_term_refs(term_t r); - - /* Constants */ - public static native atom_t new_atom(String s); - public static native String atom_chars(atom_t a); - public static native functor_t new_functor(atom_t f, int a); - public static native atom_t functor_name(functor_t f); - public static native int functor_arity(functor_t f); - - public static native void unregister_atom(atom_t a); // called from atom_t's finalize() - - /* Get Java-values from Prolog terms */ - public static native boolean get_atom(term_t t, atom_t a); - public static native boolean get_atom_chars(term_t t, StringHolder a); - public static native boolean get_string_chars(term_t t, StringHolder s); - public static native boolean get_integer(term_t t, IntHolder i); - public static native boolean get_pointer(term_t t, PointerHolder ptr); - public static native boolean get_float(term_t t, DoubleHolder d); - public static native boolean get_functor(term_t t, functor_t f); - public static native boolean get_name_arity(term_t t, StringHolder name, IntHolder arity); - public static native boolean get_module(term_t t, module_t module); - public static native boolean get_arg(int index, term_t t, term_t a); - - public static native boolean get_jref(term_t t, ObjectHolder obj); - public static native boolean get_jboolean(term_t t, BooleanHolder b); - - /* Verify types */ - public static native int term_type(term_t t); - public static native boolean is_variable(term_t t); - public static native boolean is_atom(term_t t); - public static native boolean is_integer(term_t t); - public static native boolean is_float(term_t t); - public static native boolean is_compound(term_t t); - public static native boolean is_functor(term_t t, functor_t f); - public static native boolean is_atomic(term_t t); - public static native boolean is_number(term_t t); - - /* Assign to term-references */ - public static native void put_variable(term_t t); - public static native void put_atom(term_t t, atom_t a); - public static native void put_integer(term_t t, long i); - public static native void put_pointer(term_t t, PointerHolder ptr); - public static native void put_float(term_t t, double f); - public static native void put_functor(term_t t, functor_t functor); - public static native void put_term(term_t t1, term_t t2); - public static native void put_jref(term_t t, Object ref); - public static native void put_jboolean(term_t t, boolean b); - public static native void put_jvoid(term_t t); - - /* ... */ - public static native void cons_functor_v(term_t h, functor_t fd, term_t a0); - public static native void cons_list(term_t l, term_t h, term_t t); - - // unification: - // public static native int unify(term_t t1, term_t t2); - - // predicates: - public static native predicate_t pred(functor_t f, module_t m); - public static native predicate_t predicate(String name, int arity, String module); - public static native int predicate_info(predicate_t pred, atom_t name, IntHolder arity, module_t module); - - // querying (general): - public static native qid_t open_query(module_t m, int flags, predicate_t pred, term_t t0); - public static native boolean next_solution(qid_t qid); - public static native void close_query(qid_t qid); - public static native void cut_query(qid_t qid); - - // querying (simplified): - public static native boolean call(term_t t, module_t m); - public static native boolean call_predicate(module_t m, int debug, predicate_t pred, term_t t0); - - // foreign frames: - public static native fid_t open_foreign_frame(); - public static native void close_foreign_frame(fid_t cid); - public static native void discard_foreign_frame(fid_t cid); - - // modules: - public static native module_t context(); - public static native atom_t module_name(module_t module); - public static native module_t new_module(atom_t name); - public static native int strip_module(term_t in, module_t m, term_t out); - - // not yet mapped: raise_exception() - // not yet mapped: throw() - - // exceptions: - public static native term_t exception(qid_t qid); - - // initialisation: - public static native String[] get_default_init_args(); - public static native boolean set_default_init_args(String argv[]); - public static native boolean initialise(); - public static native String[] get_actual_init_args(); - public static native void halt(int status); - - // thread & engine management: - public static native int thread_self(); - public static native engine_t attach_pool_engine(); - public static native int release_pool_engine(); - public static native engine_t current_engine(); - public static native boolean current_engine_is_pool(); - public static native String get_c_lib_version(); - - public static native int action_abort(); - public static native int attach_engine(engine_t e); - public static native int pool_engine_id(engine_t e); - -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/StringHolder.java b/Jpl/jsrc/30/jpl/fli/StringHolder.java deleted file mode 100644 index ccd9a41cc8..0000000000 --- a/Jpl/jsrc/30/jpl/fli/StringHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// StringHolder -/** - * A StringHolder is merely a Holder class for a String value. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class StringHolder -{ - public String value; -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/atom_t.java b/Jpl/jsrc/30/jpl/fli/atom_t.java deleted file mode 100644 index 7ec4d61af4..0000000000 --- a/Jpl/jsrc/30/jpl/fli/atom_t.java +++ /dev/null @@ -1,82 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// atom_t -/** - * An atom_t is a specialised LongHolder which decrements its atom's - * reference count when garbage-collected (finalized). - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class atom_t -extends LongHolder -{ - //------------------------------------------------------------------/ - // toString - /** - * The String representation of an atom_t is just the atom's name. - * - * @return atom's name - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public String - toString() - { - return Prolog.atom_chars( this ); - } - - protected void finalize() throws Throwable { - - super.finalize(); - Prolog.unregister_atom( this); - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/engine_t.java b/Jpl/jsrc/30/jpl/fli/engine_t.java deleted file mode 100644 index bcda448fff..0000000000 --- a/Jpl/jsrc/30/jpl/fli/engine_t.java +++ /dev/null @@ -1,56 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - -//----------------------------------------------------------------------/ -// engine_t -/** - * A engine_t holds a reference to a Prolog engine. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: Note that a engine_t is not a term, -// consistent with the treatment in the Prolog FLI. -//----------------------------------------------------------------------/ -public class engine_t extends LongHolder { -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/fid_t.java b/Jpl/jsrc/30/jpl/fli/fid_t.java deleted file mode 100644 index 0ac1bf9937..0000000000 --- a/Jpl/jsrc/30/jpl/fli/fid_t.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// fid_t -/** - * An fid_t holds the value of a frame id in the Prolog Engine. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class fid_t -extends LongHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/functor_t.java b/Jpl/jsrc/30/jpl/fli/functor_t.java deleted file mode 100644 index ed0fd13274..0000000000 --- a/Jpl/jsrc/30/jpl/fli/functor_t.java +++ /dev/null @@ -1,61 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// functor_t -/** - * A functor_t holds a reference to a Prolog functor_t in the - * Prolog engine. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: Note that a functor_t is not a term, -// consistent with the treatment in the Prolog FLI. -//----------------------------------------------------------------------/ -public class functor_t -extends LongHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/makefile b/Jpl/jsrc/30/jpl/fli/makefile deleted file mode 100755 index d23d831a30..0000000000 --- a/Jpl/jsrc/30/jpl/fli/makefile +++ /dev/null @@ -1,37 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../../../../makefile.env -include ../../../../../Javagui/makefile.inc - -TMPFILES =$(shell find -name "*.java") -JAVAFILES = $(subst ./,,$(TMPFILES)) - -.PHONY: all -all:$(JPL_CLASS_TARGET)/jpl/fli/Prolog.class - -$(JPL_CLASS_TARGET)/jpl/fli/Prolog.class: $(JAVAFILES) - $(JAVAC) -classpath $(CLASSPATH):$(JPL_CLASSPATH) -d $(JPL_CLASS_TARGET) $(JAVAFILES) - -.PHONY: clean -clean: - rm -f $(JPL_CLASS_TARGET)/jpl/fli/*.class - - - diff --git a/Jpl/jsrc/30/jpl/fli/module_t.java b/Jpl/jsrc/30/jpl/fli/module_t.java deleted file mode 100644 index d000086c52..0000000000 --- a/Jpl/jsrc/30/jpl/fli/module_t.java +++ /dev/null @@ -1,61 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// module_t -/** - * A module_t is a PointerHolder type which holds a reference to a Prolog - * module_t reference. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class module_t -extends PointerHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/predicate_t.java b/Jpl/jsrc/30/jpl/fli/predicate_t.java deleted file mode 100644 index ff3e8cdcc7..0000000000 --- a/Jpl/jsrc/30/jpl/fli/predicate_t.java +++ /dev/null @@ -1,61 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// predicate_t -/** - * A predicate_t is a PointerHolder class whose value is a reference to a - * Prolog predicate_t. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class predicate_t -extends PointerHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/qid_t.java b/Jpl/jsrc/30/jpl/fli/qid_t.java deleted file mode 100644 index 63e187addd..0000000000 --- a/Jpl/jsrc/30/jpl/fli/qid_t.java +++ /dev/null @@ -1,60 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// qid_t -/** - * A qid_t holds a reference to a Prolog qid_t. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class qid_t -extends LongHolder -{ -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/fli/term_t.java b/Jpl/jsrc/30/jpl/fli/term_t.java deleted file mode 100644 index 025869fa04..0000000000 --- a/Jpl/jsrc/30/jpl/fli/term_t.java +++ /dev/null @@ -1,133 +0,0 @@ -//tabstop=4 -//*****************************************************************************/ -// Project: jpl -// -// File: $Id$ -// Date: $Date$ -// Author: Fred Dushin -// -// -// Description: -// -// -// ------------------------------------------------------------------------- -// Copyright (c) 1998 Fred Dushin -// All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Library Public License for more details. -//*****************************************************************************/ -package jpl.fli; - - - -//----------------------------------------------------------------------/ -// term_t -/** - * A term_t is a simple class which mirrors the term_t type in - * the Prolog FLI. All it really does is hold a term reference, - * which is an internal representation of a term in the Prolog - * Engine. - * - *
    - * Copyright (C) 1998 Fred Dushin

    - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version.

    - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details.

    - *


    - * @author Fred Dushin - * @version $Revision$ - */ -// Implementation notes: -// -//----------------------------------------------------------------------/ -public class term_t -extends LongHolder -{ - public static final long UNASSIGNED = -1L; - - public - term_t() - { - value = UNASSIGNED; - } - - //------------------------------------------------------------------/ - // toString - /** - * This static method converts a term_t, which is assumed to contain - * a reference to a *consecutive* list of term_t references to a - * String representation of a list of terms, in this case, a comma - * separated list. - * - * @param n the number of consecutive term_ts - * @param term0 a term_t whose value is the 0th term_t. - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public static String - toString( int n, term_t term0 ) - { - String s = ""; - int i; - long ith_term_t; - - for ( i = 0, ith_term_t = term0.value; i < n; ++i, ++ith_term_t ){ - term_t term = new term_t(); - term.value = ith_term_t; - s += term.toString(); - - if ( i != n - 1 ){ - s += ", "; - } - } - - return s; - } - - - //------------------------------------------------------------------/ - // equals - /** - * Instances of term_ts are stored in Term objects (see jpl.Term), - * and these term_ts are in some cases stored in Hashtables. - * Supplying this predicate provides the right behavior in Hashtable - * lookup (see the rules for Hashtable lookup in java.util).

    - * - * Note. Two term_ts are *not* equal if their values have not - * been assigned. (Since Prolog FLI term_ts are unsigned values and - * the UNASSIGNED value is -1, this should work). - * - * @param obj the Object to comapre. - * @return true if the supplied object is a term_t instances - * and the long values are the same - */ - // Implementation notes: - // - //------------------------------------------------------------------/ - public boolean - equals( Object obj ) - { - return - (obj instanceof term_t) && - this.value == ((term_t)obj).value && - this.value != UNASSIGNED; - } -} - -//345678901234567890123456789012346578901234567890123456789012345678901234567890 diff --git a/Jpl/jsrc/30/jpl/makefile b/Jpl/jsrc/30/jpl/makefile deleted file mode 100755 index d24096b926..0000000000 --- a/Jpl/jsrc/30/jpl/makefile +++ /dev/null @@ -1,50 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../../../makefile.env -include ../../../../Javagui/makefile.inc - -# get all class files in this directory -TMPFILES =$(shell find -maxdepth 1 -name "*.java") -JAVAFILES = $(subst ./,,$(TMPFILES)) - - - -.PHONY: all -all: check fli $(JPL_CLASS_TARGET)/jpl/Query.class - -.PHONY: check -check: - $(checkjavac) - -.PHONY: fli -fli: - $(MAKE) -C fli all - - -$(JPL_CLASS_TARGET)/jpl/Query.class: $(JAVAFILES) - $(JAVAC) -classpath $(CLASSPATH):$(JPL_CLASSPATH) -d $(JPL_CLASS_TARGET) $(JAVAFILES) - -.PHONY: clean -clean: - $(MAKE) -C fli clean - rm -f $(JPL_CLASS_TARGET)/jpl/*.class - - - diff --git a/Jpl/jsrc/30/makefile b/Jpl/jsrc/30/makefile deleted file mode 100755 index a959e26b52..0000000000 --- a/Jpl/jsrc/30/makefile +++ /dev/null @@ -1,27 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -.PHONY: all -all: - $(MAKE) -C jpl all - -.PHONY: clean -clean: - $(MAKE) -C jpl clean - diff --git a/Jpl/jsrc/makefile b/Jpl/jsrc/makefile deleted file mode 100755 index 48f33b9894..0000000000 --- a/Jpl/jsrc/makefile +++ /dev/null @@ -1,29 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../makefile.optimizer - -.PHONY: all -all: - $(MAKE) -C $(JPLVER) all - -.PHONY: clean -clean: - $(MAKE) -C 10 clean - $(MAKE) -C 30 clean diff --git a/Jpl/lib/classes/jpl/fli/makefile b/Jpl/lib/classes/jpl/fli/makefile deleted file mode 100755 index f144db7bfb..0000000000 --- a/Jpl/lib/classes/jpl/fli/makefile +++ /dev/null @@ -1,22 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -.PHONY: clean -clean: - rm -f *.class diff --git a/Jpl/lib/classes/jpl/makefile b/Jpl/lib/classes/jpl/makefile deleted file mode 100755 index 7056db54cb..0000000000 --- a/Jpl/lib/classes/jpl/makefile +++ /dev/null @@ -1,23 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -.PHONY: clean -clean: - $(MAKE) -C fli clean - rm -f *.class diff --git a/Jpl/lib/classes/makefile b/Jpl/lib/classes/makefile deleted file mode 100755 index 3632efaec1..0000000000 --- a/Jpl/lib/classes/makefile +++ /dev/null @@ -1,24 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -.PHONY: clean -clean: - $(MAKE) -C jpl clean - diff --git a/Jpl/lib/makefile b/Jpl/lib/makefile deleted file mode 100755 index 4a6de20236..0000000000 --- a/Jpl/lib/makefile +++ /dev/null @@ -1,23 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -.PHONY: clean -clean: - $(MAKE) -C classes clean - rm -f *.o diff --git a/Jpl/makefile b/Jpl/makefile deleted file mode 100755 index 7801c3604b..0000000000 --- a/Jpl/makefile +++ /dev/null @@ -1,39 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../makefile.env - -.PHONY: all -all: -ifndef JPL_JAR - $(MAKE) -C jsrc all -endif -ifndef JPL_DLL - $(MAKE) -C src all -endif - -.PHONY:doc -doc: - javadoc -classpath $(JPL_CLASS_TARGET) -sourcepath $(JPL_JAVA_SOURCES) -d $(JPL_DOC_TARGET) jpl jpl.fli - -.PHONY: clean -clean: - $(MAKE) -C lib clean - $(MAKE) -C src clean - rm -rf $$(find doc ! -path "*CVS*" ! -name "doc") diff --git a/Jpl/readme.txt b/Jpl/readme.txt deleted file mode 100755 index fa0f51b43d..0000000000 --- a/Jpl/readme.txt +++ /dev/null @@ -1,69 +0,0 @@ - -This directory contains two versions of JPL an interface -between Java and SWI prolog. The first version located in -the subdirectory 10 runs only with prolog versions less than -5.2.x. The other version runs with prolog versions greater or -equal to this version. - -The default setting is to use the 1.0.x version. -If a prolog version >= 5.2.x is installed, the environment -variable PL_VERSION is to set, e.g. to 50407 if prolog 5.4.7 -is the current prolog version. - -Some prolog installations come with precompiled versions of JPL. -In this case, jpl must not be build in the Secondo system. Instead, -the existing objects can be used. To do this, export the following -environments variables: - -JPL_JAR : pointing to the jar file containing jpl class files -JPL_DLL : the location of the jpl shared object -PL_DLL : the shared objects containing the prolog engine -PL_DLL_DIR : directory containing the prolog shared objects - -Note that on windows platforms with a prolog version >=5.2.x it is -necessary to set these variables because the jpl code cannot be -compiled on windows platforms using the gcc. - -It's recommended to set these variables in the ~/.secondo.rc -file. - -An example for a linux platform is: - -... -#SWI Prolog -export SWI_HOME_DIR="/usr/lib/pl-5.4.7" -export PL_INCLUDE_DIR=$SWI_HOME_DIR/include -export PL_LIB_DIR=$SWI_HOME_DIR/lib/i686-linux - -export PL_VERSION=50407 -export PL_DLL_DIR=PL_LIB_DIR -export JPL_JAR=$SWI_HOME_DIR/lib/jpl.jar -export JPL_DLL=$PL_DLL_DIR/libjpl.so - -# PL_DLL is not used on linux platforms - -...... - -An example for a windows platform is: - -#SWI Prolog libraries -export PL_INCLUDE_DIR="$SECONDO_SDK/pl/include" -export PL_LIB_DIR="$SECONDO_SDK/pl/lib" - -export PL_VERSION=50620 -export PL_DLL_DIR="$SECONDO_SDK/pl/bin" -export JPL_DLL=$PL_DLL_DIR/jpl.dll -export PL_DLL=$PL_DLL_DIR/libpl.dll -export JPL_JAR=$PL_LIB_DIR/jpl.jar - -...... - - -On windows platforms the variable PL_DLL has to be set -even if the jpl dll is build within the secondo system. - - - - - - diff --git a/Jpl/src/10/jpl.c b/Jpl/src/10/jpl.c deleted file mode 100755 index b163a267de..0000000000 --- a/Jpl/src/10/jpl.c +++ /dev/null @@ -1,1888 +0,0 @@ -/* tabstop=4 */ -/*********************************************************************** - * Project: jpl - * - * File: $Id$ - * Date: $Date$ - * Author: Fred Dushin - * - * - * Description: This file contains the implementations of all - * the static native methods in the class jpl.fli.Prolog. For - * the most part, the implementations are strightforward class - * to the corresponding C functions by the same signature. - * - * Conventions: - * - All java parameter names begin with the letter 'j' - * e.g, jint jsize - * - Java object instance names are all lower-case, _ separated - * e.g., jobject jstring_holder - * - Java class instance names are upper-case separated - * e.g., jclass jStringHolder - * - * --------------------------------------------------------------------- - * Copyright (C) 2004, University in Hagen, Department of Computer Science, - * Database Systems for New Applications. - - * Copyright (c) 1998 Fred Dushin - * All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details. - ***********************************************************************/ -#include -#include - -#include -#include - -typedef long pointer; - -/************************************************************************ - * Utility functions - ***********************************************************************/ - -/*----------------------------------------------------------------------- - * getLongValue - * - * Retrieves the value in a Java LongHolder class instance - * - * @param env Java environment - * @param jlong_holder the LongHolder class instance - * @return the LongHolder's value - *---------------------------------------------------------------------*/ -static long -getLongValue( - JNIEnv *env, - jobject jlong_holder ) -{ - jfieldID fid; - jclass jLongHolder; - - if ( jlong_holder == NULL ){ - return (long) NULL; - } - - jLongHolder = (*env)->FindClass( env, "jpl/fli/LongHolder" ); - fid = (*env)->GetFieldID( env, jLongHolder, "value", "J" ); - if ( fid == NULL ){ - fprintf( stderr, "getLongValue: Could not access fid for value field\n" ); - return; - } - - return (*env)->GetLongField( env, jlong_holder, fid ); -} - -/*----------------------------------------------------------------------- - * getPointerValue - * - * Retrieves the value in a Java Pointer class instance - * - * @param env Java environment - * @param jpointer the Pointer class instance - * @return the Pointer's value - *---------------------------------------------------------------------*/ -static pointer -getPointerValue( - JNIEnv *env, - jobject jpointer_holder ) -{ - jfieldID fid; - jclass jPointerHolder; - - if ( jpointer_holder == NULL ){ - return (pointer) NULL; - } - - jPointerHolder = (*env)->FindClass( env, "jpl/fli/PointerHolder" ); - fid = (*env)->GetFieldID( env, jPointerHolder, "value", "J" ); - if ( fid == NULL ){ - fprintf( stderr, "getPointerValue: Could not access fid for value field\n" ); - return; - } - - return (*env)->GetLongField( env, jpointer_holder, fid ); -} - - -/*----------------------------------------------------------------------- - * setPointerValue - * - * Sets the value in a Java Pointer class instance to the supplied value - * - * @param env Java environment - * @param jpointer the Pointer class instance - * @param value the new value - *---------------------------------------------------------------------*/ -static void -setPointerValue( - JNIEnv *env, - jobject jpointer_holder, - pointer value ) -{ - jfieldID fid = 0; - jclass jPointerHolder; - - if ( jpointer_holder == NULL ){ - return; - } - - jPointerHolder = (*env)->FindClass( env, "jpl/fli/PointerHolder" ); - fid = (*env)->GetFieldID( env, jPointerHolder, "value", "J" ); - if ( fid == NULL ){ - fprintf( stderr, "setPointerValue: Could not access fid for value field\n" ); - return; - } - (*env)->SetLongField( env, jpointer_holder, fid, value ); -} - -/*----------------------------------------------------------------------- - * setIntValue - * - * Sets the value in a Java IntHolder class instance to the supplied value - * - * @param env Java environment - * @param jint_holder the IntHolder class instance - * @param value the new value - *---------------------------------------------------------------------*/ -static void -setIntValue( - JNIEnv *env, - jobject jint_holder, - int value ) -{ - jfieldID fid = 0; - jclass jIntHolder; - - if ( jint_holder == NULL ){ - return; - } - - jIntHolder = (*env)->FindClass( env, "jpl/fli/IntHolder" ); - fid = (*env)->GetFieldID( env, jIntHolder, "value", "I" ); - if ( fid == NULL ){ - fprintf( stderr, "setIntValue: Could not access fid for value field\n" ); - return; - } - (*env)->SetIntField( env, jint_holder, fid, value ); -} - -/*----------------------------------------------------------------------- - * setLongValue - * - * Sets the value in a Java LongHolder class instance to the supplied value - * - * @param env Java environment - * @param jlong_holder the LongHolder class instance - * @param value the new value - *---------------------------------------------------------------------*/ -static void -setLongValue( - JNIEnv *env, - jobject jlong_holder, - long value ) -{ - jfieldID fid = 0; - jclass jLongHolder; - - if ( jlong_holder == NULL ){ - return; - } - - jLongHolder = (*env)->FindClass( env, "jpl/fli/LongHolder" ); - fid = (*env)->GetFieldID( env, jLongHolder, "value", "J" ); - if ( fid == NULL ){ - fprintf( stderr, "setLongValue: Could not access fid for value field\n" ); - return; - } - (*env)->SetLongField( env, jlong_holder, fid, value ); -} - -/*----------------------------------------------------------------------- - * setDoubleValue - * - * Sets the value in a Java DoubleHolder class instance to the supplied value - * - * @param env Java environment - * @param jdouble_holder the DoubleHolder class instance - * @param value the new value - *---------------------------------------------------------------------*/ -static void -setDoubleValue( - JNIEnv *env, - jobject jdouble_holder, - double value ) -{ - jfieldID fid = 0; - jclass jDoubleHolder; - - if ( jdouble_holder == NULL ){ - return; - } - - jDoubleHolder = (*env)->FindClass( env, "jpl/fli/DoubleHolder" ); - fid = (*env)->GetFieldID( env, jDoubleHolder, "value", "D" ); - if ( fid == NULL ){ - fprintf( stderr, "setDoubleValue: Could not access fid for value field\n" ); - return; - } - (*env)->SetDoubleField( env, jdouble_holder, fid, value ); -} - -/*----------------------------------------------------------------------- - * setStringValue - * - * Sets the value in a Java StringHolder class instance to the supplied value - * - * @param env Java environment - * @param jstring_holder the StringHolder class instance - * @param value the new value - *---------------------------------------------------------------------*/ -static void -setStringValue( - JNIEnv *env, - jobject jstring_holder, - jstring value ) -{ - jfieldID fid = 0; - jclass jStringHolder; - - if ( jstring_holder == NULL ){ - return; - } - - jStringHolder = (*env)->FindClass( env, "jpl/fli/StringHolder" ); - fid = (*env)->GetFieldID( env, jStringHolder, "value", "Ljava/lang/String;" ); - if ( fid == NULL ){ - fprintf( stderr, "setStringValue: Could not access fid for value field\n" ); - return; - } - (*env)->SetObjectField( env, jstring_holder, fid, value ); -} - - - -/************************************************************************ - * C implementations of the Java native methods - * - * NOTE: Many of these functions are still umimplemented. - ***********************************************************************/ - - - -/* - * Class: jpl_fli_PL - * Method: new_term_refs - * Signature: (I)Ljpl/fli/term_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1term_1refs( - JNIEnv *env, - jclass jProlog, - jint jn ) -{ - jobject rval; - term_t t0; - jclass jterm_t; - - /* create the prolog term_t references */ - t0 = PL_new_term_refs( (int)jn ); - - /* create the java term_t and set its value */ - jterm_t = (*env)->FindClass( env, "jpl/fli/term_t" ); - rval = (*env)->AllocObject( env, jterm_t ); - setLongValue( env, rval, (long)t0 ); - - return rval; -} - -/* - * Class: jpl_fli_PL - * Method: new_term_ref - * Signature: ()Ljpl/fli/term_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1term_1ref( - JNIEnv *env, - jclass jProlog ) -{ - jobject rval; - term_t term; - jclass jterm_t; - - /* create the prolog term_t reference */ - term = PL_new_term_ref(); - - /* create the java term_t and set its value */ - jterm_t = (*env)->FindClass( env, "jpl/fli/term_t" ); - rval = (*env)->AllocObject( env, jterm_t ); - setLongValue( env, rval, (long)term ); - - return rval; -} - -/* - * Class: jpl_fli_PL - * Method: copy_term_ref - * Signature: (Ljpl/fli/term_t;)Ljpl/fli/term_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_copy_1term_1ref( - JNIEnv *env, - jclass jProlog, - jobject jfrom ) -{ - jobject rval; - term_t term; - jclass jterm_t; - - /* create the prolog term_t reference */ - term = PL_copy_term_ref( getLongValue( env, jfrom ) ); - - /* create the java term_t and set its value */ - jterm_t = (*env)->FindClass( env, "jpl/fli/term_t" ); - rval = (*env)->AllocObject( env, jterm_t ); - setLongValue( env, rval, (long)term ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: reset_term_refs - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_reset_1term_1refs( - JNIEnv *env, - jclass jProlog, - jobject jafter ) -{ - PL_reset_term_refs( getLongValue( env, jafter ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: new_atom - * Signature: (Ljava/lang/String;)Ljpl/fli/atom_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1atom( - JNIEnv *env, - jclass jProlog, - jstring jname ) -{ - jobject rval = NULL; - atom_t atom; - const char *name; - jclass jatom_t; - - /* create the prolog atom_t */ - name = (*env)->GetStringUTFChars( env, jname, 0 ); - - atom = PL_new_atom( name ); - (*env)->ReleaseStringUTFChars( env, jname, name ); - - /* create the java atom_t and set its value */ - jatom_t = (*env)->FindClass( env, "jpl/fli/atom_t" ); - rval = (*env)->AllocObject( env, jatom_t ); - - setLongValue( env, rval, (long)atom ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: atom_chars - * Signature: (Ljpl/fli/atom_t;)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL -Java_jpl_fli_Prolog_atom_1chars( - JNIEnv *env, - jclass jProlog, - jobject jatom ) -{ - jstring rval; - const char *s; - - s = (const char *)PL_atom_chars( (atom_t) getLongValue( env, jatom ) ); - - rval = (*env)->NewStringUTF( env, s ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: new_functor - * Signature: (Ljpl/fli/atom_t;I)Ljpl/fli/functor_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1functor( - JNIEnv *env, - jclass jProlog, - jobject jatom, - jint arity ) -{ - jobject rval; - functor_t functor; - jclass jfunctor_t; - - /* create the prolog functor_t */ - functor = PL_new_functor( getLongValue( env, jatom ), (int)arity ); - - /* create the java functor_t and set its value */ - jfunctor_t = (*env)->FindClass( env, "jpl/fli/functor_t" ); - rval = (*env)->AllocObject( env, jfunctor_t ); - setLongValue( env, rval, (long)functor ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: functor_name - * Signature: (Ljpl/fli/functor_t;)Ljpl/fli/atom_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_functor_1name( - JNIEnv *env, - jclass jProlog, - jobject jfunctor ) -{ - jobject rval; - atom_t atom; - jclass jatom_t; - - /* get the prolog atom_t */ - atom = PL_functor_name( getLongValue( env, jfunctor ) ); - - /* create the java atom_t and set its value */ - jatom_t = (*env)->FindClass( env, "jpl/fli/atom_t" ); - rval = (*env)->AllocObject( env, jatom_t ); - setLongValue( env, rval, (long)atom ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: functor_arity - * Signature: (Ljpl/fli/functor_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_functor_1arity( - JNIEnv *env, - jclass jProlog, - jobject jfunctor ) -{ - int rval; - - /* get the prolog arity */ - rval = PL_functor_arity( getLongValue( env, jfunctor ) ); - - return (jint) rval; -} - - - - - -/* various *get* functions */ - - -/* - * Class: jpl_fli_PL - * Method: get_atom - * Signature: (Ljpl/fli/term_t;Ljpl/fli/atom_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1atom( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jatom ) -{ - jint rval = JNI_FALSE; - term_t term; - atom_t atom; - - term = (term_t)getLongValue( env, jterm ); - rval = PL_get_atom( term, &atom ); - setLongValue( env, jatom, (long)atom ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_atom_chars - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1atom_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jstring_holder ) -{ - jint rval = JNI_FALSE; - term_t term; - atom_t atom; - char *s; - jstring string; - - term = (term_t)getLongValue( env, jterm ); - rval = PL_get_atom_chars( term, &s ); - - string = (*env)->NewStringUTF( env, s ); - - setStringValue( env, jstring_holder, string ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_string - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;Ljpl/fli/IntHolder;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1string( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jstring_holder ) -{ - jint rval = JNI_FALSE; - term_t term; - char *s; - jstring string; - int length; - - term = (term_t)getLongValue( env, jterm ); - rval = PL_get_string( term, &s, &length ); - - string = (*env)->NewStringUTF( env, s ); - setStringValue( env, jstring_holder, string ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_list_chars - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;I)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1list_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jstring_holder, - jint jflags ) -{ - jint rval; - char *s; - jstring string; - - rval = - (int) PL_get_list_chars( - (term_t) getLongValue( env, jterm ), - &s, - (unsigned) jflags ); - - string = (*env)->NewStringUTF( env, s ); - setStringValue( env, jstring_holder, string ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_chars - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;I)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jstring_holder, - jint jflags ) -{ - jint rval; - char *s; - jstring string; - - rval = - (int) PL_get_chars( - (term_t) getLongValue( env, jterm ), - &s, - (unsigned) jflags ); - - string = (*env)->NewStringUTF( env, s ); - setStringValue( env, jstring_holder, string ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_integer - * Signature: (Ljpl/fli/term_t;Ljpl/fli/IntHolder;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1integer( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jint_holder ) -{ - jint rval; - int i; - - rval = - (int) PL_get_integer( - (term_t) getLongValue( env, jterm ), - &i ); - - setIntValue( env, jint_holder, i ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_long - * Signature: (Ljpl/fli/term_t;Ljpl/fli/LongHolder;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1long( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jlong_holder ) -{ - jint rval; - long l; - - rval = - (int) PL_get_long( - (term_t) getLongValue( env, jterm ), - &l ); - - setLongValue( env, jlong_holder, l ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_pointer - * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1pointer( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jpointer ) -{ - jint rval; - void *ptr; - - rval = - (int) PL_get_pointer( - (term_t) getLongValue( env, jterm ), - &ptr ); - - setPointerValue( env, jpointer, (pointer)ptr ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_float - * Signature: (Ljpl/fli/term_t;Ljpl/fli/DoubleHolder;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1float( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jdouble_holder ) -{ - jint rval; - double d; - - rval = - (int) PL_get_float( - (term_t) getLongValue( env, jterm ), - &d ); - - setDoubleValue( env, jdouble_holder, d ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_functor - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1functor( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor ) -{ - jint rval = JNI_FALSE; - term_t term; - functor_t functor; - - term = (term_t)getLongValue( env, jterm ); - rval = PL_get_functor( term, &functor ); - setLongValue( env, jfunctor, (long)functor ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_name_arity - * Signature: (Ljpl/fli/term_t;Ljpl/fli/atom_t;Ljpl/fli/IntHolder;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1name_1arity( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jatom, - jobject jint_holder ) -{ - jint rval = JNI_FALSE; - term_t term; - atom_t atom; - int arity; - - term = (term_t)getLongValue( env, jterm ); - rval = PL_get_name_arity( term, &atom, &arity ); - - setLongValue( env, jatom, (long)atom ); - setIntValue( env, jint_holder, arity ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_module - * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1module( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jmodule ) -{ - jint rval = JNI_FALSE; - term_t term; - module_t module; - - term = (term_t)getLongValue( env, jterm ); - rval = PL_get_module( term, &module ); - - setPointerValue( env, jmodule, (pointer)module ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_arg - * Signature: (ILjpl/fli/term_t;Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1arg( - JNIEnv *env, - jclass jProlog, - jint jindex, - jobject jterm, - jobject jarg ) -{ - jint rval = JNI_FALSE; - term_t term; - term_t arg; - - term = (term_t)getLongValue( env, jterm ); - arg = (term_t)getLongValue( env, jarg ); - rval = PL_get_arg( jindex, term, arg ); - setLongValue( env, jarg, (long)arg ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_list - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1list( - JNIEnv *env, - jclass jProlog, - jobject jlist, - jobject jhead, - jobject jtail ) -{ - jint rval; - - rval = - (int) PL_get_list( - (term_t) getLongValue( env, jlist ), - (term_t) getLongValue( env, jhead ), - (term_t) getLongValue( env, jtail ) ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_head - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1head( - JNIEnv *env, - jclass jProlog, - jobject jlist, - jobject jhead ) -{ - jint rval; - - rval = - (int) PL_get_head( - (term_t) getLongValue( env, jlist ), - (term_t) getLongValue( env, jhead ) ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_tail - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1tail( - JNIEnv *env, - jclass jProlog, - jobject jlist, - jobject jtail ) -{ - jint rval; - - rval = - (int) PL_get_tail( - (term_t) getLongValue( env, jlist ), - (term_t) getLongValue( env, jtail ) ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: get_nil - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_get_1nil( - JNIEnv *env, - jclass jProlog, - jobject jlist ) -{ - jint rval; - - rval = - (int) PL_get_nil( - (term_t) getLongValue( env, jlist ) ); - - return rval; -} - - - - - - - - -/* - * Class: jpl_fli_PL - * Method: term_type - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_term_1type( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_term_type( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_variable - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1variable( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_variable( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_atom - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1atom( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_variable( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_integer - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1integer( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_integer( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_string - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1string( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_string( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_float - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1float( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_float( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_compound - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1compound( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_compound( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_functor - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1functor( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor ) -{ - return (jint) PL_is_functor( getLongValue( env, jterm ), - getLongValue( env, jfunctor ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_list - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1list( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_list( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_atomic - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1atomic( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_atomic( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: is_number - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_is_1number( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - return (jint) PL_is_number( getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_variable - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1variable( - JNIEnv *env, - jclass jProlog, - jobject jterm ) -{ - PL_put_variable( - getLongValue( env, jterm ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_atom - * Signature: (Ljpl/fli/term_t;Ljpl/fli/atom_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1atom( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jatom ) -{ - PL_put_atom( - getLongValue( env, jterm ), - getLongValue( env, jatom ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_atom_chars - * Signature: (Ljpl/fli/term_t;Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1atom_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jstring jchars ) -{ - const char *chars; - - chars = (*env)->GetStringUTFChars( env, jchars, NULL ); - - PL_put_atom_chars( getLongValue( env, jterm ), chars ); - - (*env)->ReleaseStringUTFChars( env, jchars, chars ); - return; -} - - -/* - * Class: jpl_fli_PL - * Method: put_string_chars - * Signature: (Ljpl/fli/term_t;Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1string_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jstring jchars ) -{ - const char *chars; - - chars = (*env)->GetStringUTFChars( env, jchars, NULL ); - - PL_put_string_chars( getLongValue( env, jterm ), chars ); - - (*env)->ReleaseStringUTFChars( env, jchars, chars ); - return; -} - - -/* - * Class: jpl_fli_PL - * Method: put_list_chars - * Signature: (Ljpl/fli/term_t;Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1list_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jstring jchars ) -{ - const char *chars; - - chars = (*env)->GetStringUTFChars( env, jchars, NULL ); - - PL_put_string_chars( getLongValue( env, jterm ), chars ); - - (*env)->ReleaseStringUTFChars( env, jchars, chars ); - return; -} - - -/* - * Class: jpl_fli_PL - * Method: put_integer - * Signature: (Ljpl/fli/term_t;J)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1integer( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jlong ji ) -{ - PL_put_integer( - (term_t) getLongValue( env, jterm ), - (long) ji ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_pointer - * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1pointer( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jpointer ) -{ - PL_put_pointer( - (term_t) getLongValue( env, jterm ), - (void *) getPointerValue( env, jpointer ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_float - * Signature: (Ljpl/fli/term_t;D)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1float( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jdouble jf ) -{ - PL_put_float( - (term_t) getLongValue( env, jterm ), - (double) jf ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_functor - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1functor( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor ) -{ - PL_put_functor( - (term_t) getLongValue( env, jterm ), - (functor_t) getLongValue( env, jfunctor ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_list - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1list( - JNIEnv *env, - jclass jProlog, - jobject jlist ) -{ - PL_put_list( - (term_t) getLongValue( env, jlist ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_nil - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void -JNICALL Java_jpl_fli_Prolog_put_1nil( - JNIEnv *env, - jclass jProlog, - jobject jlist ) -{ - PL_put_nil( - (term_t) getLongValue( env, jlist ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: put_term - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1term( - JNIEnv *env, - jclass jProlog, - jobject jterm1, - jobject jterm2 ) -{ - PL_put_term( - getLongValue( env, jterm1 ), - getLongValue( env, jterm2 ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: cons_functor - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;[Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_cons_1functor( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor, - jobjectArray jterms ) -{ - jsize length; - term_t term0, term1, term2, term3, term4; - - length = (*env)->GetArrayLength( env, jterms ); - - switch ( length ){ - case 0: - PL_cons_functor( - getLongValue( env, jterm ), - getLongValue( env, jfunctor ) ); - break; - case 1: - term0 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 0 ) ); - PL_cons_functor( - getLongValue( env, jterm ), - getLongValue( env, jfunctor ), - term0 ); - break; - case 2: - term0 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 0 ) ); - term1 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 1 ) ); - - PL_cons_functor( - getLongValue( env, jterm ), - getLongValue( env, jfunctor ), - term0, - term1 ); - break; - case 3: - term0 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 0 ) ); - term1 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 1 ) ); - term2 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 2 ) ); - - PL_cons_functor( - getLongValue( env, jterm ), - getLongValue( env, jfunctor ), - term0, - term1, - term2 ); - break; - case 4: - term0 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 0 ) ); - term1 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 1 ) ); - term2 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 2 ) ); - term3 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 3 ) ); - - PL_cons_functor( - getLongValue( env, jterm ), - getLongValue( env, jfunctor ), - term0, - term1, - term2, - term3 ); - break; - case 5: - term0 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 0 ) ); - term1 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 1 ) ); - term2 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 2 ) ); - term3 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 3 ) ); - term4 = - getLongValue( - env, (*env)->GetObjectArrayElement( env, jterms, 4 ) ); - - PL_cons_functor( - getLongValue( env, jterm ), - getLongValue( env, jfunctor ), - term0, - term1, - term2, - term3, - term4 ); - break; - default: - printf( "Unsupported arg list list. You should not have access to this function anyway.\n" ); - } -} - - -/* - * Class: jpl_fli_PL - * Method: cons_functor_v - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_cons_1functor_1v( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor, - jobject jterm0 ) -{ - PL_cons_functor_v( - getLongValue( env, jterm ), - getLongValue( env, jfunctor ), - getLongValue( env, jterm0 ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: cons_list - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_cons_1list( - JNIEnv *env, - jclass jProlog, - jobject jlist, - jobject jhead, - jobject jtail ) -{ - PL_cons_list( - getLongValue( env, jlist ), - getLongValue( env, jhead ), - getLongValue( env, jtail ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: unify - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_unify( - JNIEnv *env, - jclass jProlog, - jobject jt1, - jobject jt2 ) -{ - PL_unify( - getLongValue( env, jt1 ), - getLongValue( env, jt2 ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: open_foreign_frame - * Signature: ()Ljpl/fli/fid_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_open_1foreign_1frame( - JNIEnv *env, - jclass jProlog ) -{ - jobject rval; - fid_t value; - jobject jfid_t; - - value = PL_open_foreign_frame(); - - /* create the java atom_t and set its value */ - jfid_t = (*env)->FindClass( env, "jpl/fli/fid_t" ); - rval = (*env)->AllocObject( env, jfid_t ); - setLongValue( env, rval, (long)value ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: close_foreign_frame - * Signature: (Ljpl/fli/fid_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_close_1foreign_1frame( - JNIEnv *env, - jclass jProlog, - jobject jfid ) -{ - PL_close_foreign_frame( - (fid_t) getLongValue( env, jfid ) ); -} - -/* - * Class: jpl_fli_PL - * Method: discard_foreign_frame - * Signature: (Ljpl/fli/fid_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_discard_1foreign_1frame( - JNIEnv *env, - jclass jProlog, - jobject jfid ) -{ - PL_discard_foreign_frame( - (fid_t) getLongValue( env, jfid ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: pred - * Signature: (Ljpl/fli/functor_t;Ljpl/fli/module_t;)Ljpl/fli/predicate_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_pred( - JNIEnv *env, - jclass jProlog, - jobject jfunctor, - jobject jmodule ) -{ - jobject rval; - predicate_t value; - jclass jpredicate_t; - - value = PL_pred( - (functor_t) getLongValue( env, jfunctor ), - (module_t) getPointerValue( env, jmodule ) ); - - jpredicate_t = (*env)->FindClass( env, "jpl/fli/predicate_t" ); - rval = (*env)->AllocObject( env, jpredicate_t ); - setPointerValue( env, rval, (pointer)value ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: predicate - * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljpl/fli/predicate_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_predicate( - JNIEnv *env, - jclass jProlog, - jstring jname, - jint jarity, - jstring jmodule ) -{ - jobject rval; - predicate_t value; - const char *name; - jclass jpredicate_t; - - name = (*env)->GetStringUTFChars( env, jname, 0 ); - value = PL_predicate( - name, - (int)jarity, - (module_t) getPointerValue( env, jmodule ) ); - (*env)->ReleaseStringUTFChars( env, jname, name ); - - jpredicate_t = (*env)->FindClass( env, "jpl/fli/predicate_t" ); - rval = (*env)->AllocObject( env, jpredicate_t ); - setPointerValue( env, rval, (pointer)value ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: predicate_info - * Signature: (Ljpl/fli/predicate_t;Ljpl/fli/atom_t;ILjpl/fli/module_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_predicate_1info( - JNIEnv *env, - jclass jProlog, - jobject jpredicate, - jobject jatom, - jobject jint_holder, - jobject jmodule ) -{ - jint rval = JNI_FALSE; - predicate_t predicate; - atom_t atom; - int arity; - module_t module; - jclass jIntHolder; - - predicate = (predicate_t) getPointerValue( env, jpredicate ); - rval = PL_predicate_info( predicate, &atom, &arity, &module ); - - setLongValue( env, jatom, (long)atom ); - setPointerValue( env, jmodule, (pointer) module ); - setIntValue( env, jint_holder, arity ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: open_query - * Signature: (Ljpl/fli/module_t;ILjpl/fli/predicate_t;Ljpl/fli/term_t;)Ljpl/fli/qid_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_open_1query( - JNIEnv *env, - jclass jProlog, - jobject jmodule, - jint jflags, - jobject jpredicate, - jobject jterm0 ) -{ - jobject rval; - qid_t qid; - jclass jqid_t; - - qid = PL_open_query( - (module_t) getPointerValue( env, jmodule ), - (int) jflags, - (predicate_t) getPointerValue( env, jpredicate ), - (term_t) getLongValue( env, jterm0 ) ); - - jqid_t = (*env)->FindClass( env, "jpl/fli/qid_t" ); - rval = (*env)->AllocObject( env, jqid_t ); - setLongValue( env, rval, (long)qid ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: next_solution - * Signature: (Ljpl/fli/qid_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_next_1solution( - JNIEnv *env, - jclass jProlog, - jobject jqid ) -{ - return PL_next_solution( getLongValue( env, jqid ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: close_query - * Signature: (Ljpl/fli/qid_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_close_1query( - JNIEnv *env, - jclass jProlog, - jobject jqid ) -{ - PL_close_query( getLongValue( env, jqid ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: cut_query - * Signature: (Ljpl/fli/qid_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_cut_1query( - JNIEnv *env, - jclass jProlog, - jobject jqid ) -{ - PL_cut_query( getLongValue( env, jqid ) ); -} - - -/* - * Class: jpl_fli_PL - * Method: call - * Signature: (Ljpl/fli/term_t;Ljpl/fli/module_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_call( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jmodule ) -{ - jint rval; - - rval = (jint) PL_call( - (term_t) getLongValue( env, jterm ), - (module_t) getPointerValue( env, jmodule ) ); - - return rval; -} - - -/* - * Class: jpl_fli_PL - * Method: call_predicate - * Signature: (Ljpl/fli/module_t;ILjpl/fli/predicate_t;Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_call_1predicate( - JNIEnv *env, - jclass jProlog, - jobject jmodule, - jint jdebug, - jobject jpredicate, - jobject jt0 ) -{ - jint rval; - - rval = (jint) PL_call_predicate( - (module_t) getPointerValue( env, jmodule ), - (int) jdebug, - (predicate_t) getPointerValue( env, jpredicate ), - (term_t) getLongValue( env, jt0 ) ); - - return rval; - -} - - -/* - * Class: jpl_fli_PL - * Method: exception - * Signature: (Ljpl/fli/qid_t;)Ljpl/fli/term_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_exception( - JNIEnv *env, - jclass jProlog, - jobject jqid ) -{ - jobject rval; - term_t term = PL_exception( getLongValue( env, jqid ) ); - - /* create the java term_t and set its value */ - jobject jterm_t = (*env)->FindClass( env, "jpl/fli/term_t" ); - rval = (*env)->AllocObject( env, jterm_t ); - setLongValue( env, rval, (long)term ); - - return rval; -} - - - -/* - * Class: jpl_fli_PL - * Method: initialise - * Signature: (I[Ljava/lang/String;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_initialise( - JNIEnv *env, - jclass jProlog, - jint jargc, - jobjectArray jargv ) -{ - jsize length; - const char **argv; - jboolean rval = JNI_TRUE; - int i; - - length = (*env)->GetArrayLength( env, jargv ); -/*printf( "initialize: length=%i\n", length ); */ - - argv = (const char **) malloc( length*sizeof( char * ) + 1 ); - if ( argv == NULL ){ - return JNI_FALSE; - } - - - for ( i = 0; i < length; ++i ){ - jstring jarg; - jarg = (jstring) (*env)->GetObjectArrayElement( env, jargv, i ); - argv[i] = (*env)->GetStringUTFChars( env, jarg, 0 ); -/*printf( "initialize: argv[%i]=%s\n", i, argv[i] );*/ - } - argv[length] = NULL; - - if ( ! PL_initialise( length, (char **)argv ) ){ - PL_halt( 1 ); - rval = JNI_FALSE; - } - - for ( i = 0; i < length; ++i ){ - jstring jarg; - jarg = (jstring) (*env)->GetObjectArrayElement( env, jargv, i ); - (*env)->ReleaseStringUTFChars( env, jarg, argv[i] ); - } - - free( argv ); - - return rval; -} - -/* - * Class: jpl_fli_PL - * Method: halt - * Signature: (I)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_halt( - JNIEnv *env, - jclass jProlog, - jint jstatus ) -{ - PL_halt( (int) jstatus ); -} - - - - diff --git a/Jpl/src/30/jpl.c b/Jpl/src/30/jpl.c deleted file mode 100644 index e3a4addfcb..0000000000 --- a/Jpl/src/30/jpl.c +++ /dev/null @@ -1,6515 +0,0 @@ -/* $Id$ - - Part of JPL -- SWI-Prolog/Java interface - - Author: Paul Singleton, Fred Dushin and Jan Wielemaker - E-mail: paul@jbgb.com - WWW: http://www.swi-prolog.org - Copyright (C): 1985-2004, Paul Singleton - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -// this source file (jpl.c) combines my Prolog-calls-Java stuff (mostly prefixed 'JNI' or 'jni' here) -// with my adaptation of Fred Dushin's Java-calls-Prolog stuff (mostly prefixed 'JPL' or 'jpl' here) - -// recent fixes: -// * using PL_get_pointer(), PL_put_pointer() consistently (?) -// -// still to do: -// * make it completely thread-safe -// (both to multiple Prolog (engine-enabled) threads and to multiple Java threads) -// * suss JVM 'abort' and 'exit' handling, and 'vfprintf' redirection -// * figure out why Java native methods have "Class: jpl_fli_PL" (and not jpl_fli_Prolog) -// * rationalise initialisation; perhaps support startup from C? - -// update this to distinguish releases of this C library: -#define JPL_C_LIB_VERSION "3.0.4-alpha" -#define JPL_C_LIB_VERSION_MAJOR 3 -#define JPL_C_LIB_VERSION_MINOR 0 -#define JPL_C_LIB_VERSION_PATCH 4 -#define JPL_C_LIB_VERSION_STATUS "alpha" - -#define DEBUG(n, g) ((void)0) - -//=== includes ===================================================================================== - -#ifdef WIN32 -// OS-specific header (SWI-Prolog FLI and Java Invocation API both seem to need this): -#include -#endif - -// SWI-Prolog headers: -#include -#include - -// Java Native Interface and Invocation Interface header: -#include - -// ANSI/ISO C library header (?): -#include -#include -#include -#include - -// POSIX 'pthreads' headers (initially for JPL's Prolog engine pool, useful for locking generally?): -#include -#include - - -//=== JNI constants ================================================================================ - -#define JNI_MIN_JCHAR 0 -#define JNI_MAX_JCHAR 65535 - -#define JNI_MIN_JBYTE -128 -#define JNI_MAX_JBYTE 127 - -#define JNI_MIN_JSHORT -32768 -#define JNI_MAX_JSHORT 32767 - - -#define JNI_XPUT_VOID 0 -#define JNI_XPUT_BOOLEAN 1 -#define JNI_XPUT_BYTE 2 -#define JNI_XPUT_CHAR 3 -#define JNI_XPUT_SHORT 4 -#define JNI_XPUT_INT 5 -#define JNI_XPUT_LONG 6 -#define JNI_XPUT_FLOAT 7 -#define JNI_XPUT_DOUBLE 8 -#define JNI_XPUT_FLOAT_TO_DOUBLE 9 -#define JNI_XPUT_LONG_TO_FLOAT 10 -#define JNI_XPUT_LONG_TO_DOUBLE 11 -#define JNI_XPUT_REF 12 -#define JNI_XPUT_ATOM 13 -#define JNI_XPUT_JVALUEP 14 -#define JNI_XPUT_JVALUE 15 - - -// JNI "hashed refs" constants - -#define JNI_HR_LOAD_FACTOR 0.75 - -// jni_hr_add() return codes: -#define JNI_HR_ADD_FAIL -1 -#define JNI_HR_ADD_NEW 0 -#define JNI_HR_ADD_OLD 1 - - -//=== JPL constants ================================================================================ - -// legit values for jpl_status_jpl_ini and jpl_status_pvm_ini -#define JPL_INIT_RAW 101 -#define JPL_INIT_PVM_MAYBE 102 -#define JPL_INIT_OK 103 -#define JPL_INIT_JPL_FAILED 104 -#define JPL_INIT_PVM_FAILED 105 - -#define JPL_MAX_POOL_ENGINES 10 /* max pooled Prolog engines */ -#define JPL_INITIAL_POOL_ENGINES 1 /* initially created ones */ - - -//=== JNI Prolog<->Java conversion macros ========================================================== - -// JNI (Prolog-calls-Java) conversion macros; mainly used in jni_{func|void}_{0|1|2|3|4}_plc -// for re-entrancy, ensure that any variables which they use are declared dynamically -// (e.g. or i.e. are local to the host function) -// beware of evaluating *expressions* passed as actual parameters more than once - -#define JNI_term_to_jboolean(T,JB) \ - ( PL_get_functor((T),&fn) \ - && fn==JNI_functor_at_1 \ - ? ( ( a1=PL_new_term_ref(), \ - PL_get_arg(1,(T),a1) \ - ) \ - && PL_get_atom(a1,&a) \ - ? ( a==JNI_atom_false \ - ? ( (JB)=0, TRUE) \ - : ( a==JNI_atom_true \ - ? ( (JB)=1, TRUE) \ - : FALSE \ - ) \ - ) \ - : FALSE \ - ) \ - : FALSE \ - ) - -#define JNI_term_to_jchar(T,J) \ - ( PL_get_integer((T),&(J)) \ - && (J) >= JNI_MIN_JCHAR \ - && (J) <= JNI_MAX_JCHAR \ - ) - -#define JNI_term_to_jbyte(T,J) \ - ( PL_get_integer((T),&(J)) \ - && (J) >= JNI_MIN_JBYTE \ - && (J) <= JNI_MAX_JBYTE \ - ) - -#define JNI_term_to_jshort(T,J) \ - ( PL_get_integer((T),&(J)) \ - && (J) >= JNI_MIN_JSHORT \ - && (J) <= JNI_MAX_JSHORT \ - ) - -#define JNI_term_to_jint(T,J) \ - ( PL_get_integer((T),&(J)) \ - ) - -#define JNI_term_to_non_neg_jint(T,J) \ - ( PL_get_integer((T),&(J)) \ - && (J) >= 0 \ - ) - -#define JNI_term_to_jlong(T,J) \ - ( PL_get_integer((T),&i) \ - ? ( (J)=(jlong)i, TRUE) \ - : JNI_jlong2_to_jlong(T,(J)) \ - ) - -#define JNI_jlong2_to_jlong(T,J) \ - ( PL_get_functor((T),&fn) \ - && fn==JNI_functor_jlong_2 \ - ? ( ( a1=PL_new_term_ref(), \ - PL_get_arg(1,(T),a1) \ - ) \ - && ( a2=PL_new_term_ref(), \ - PL_get_arg(2,(T),a2) \ - ) \ - && PL_get_integer(a1,&xhi) \ - && PL_get_integer(a2,&xlo) \ - ? ( ((int*)&(J))[1]=xhi, \ - ((int*)&(J))[0]=xlo, \ - TRUE \ - ) \ - : FALSE \ - ) \ - : FALSE \ - ) - -#define JNI_term_to_jfloat(T,J) \ - ( PL_get_float((T),&(J)) \ - ? TRUE \ - : ( PL_get_integer((T),&i) \ - ? ( (J)=(jfloat)i, TRUE) \ - : ( JNI_jlong2_to_jlong((T),jl) \ - ? ( (J)=(jfloat)jl, TRUE) \ - : FALSE \ - ) \ - ) \ - ) - -#define JNI_term_to_jdouble(T,J) \ - ( PL_get_float((T),&(J)) \ - ? TRUE \ - : ( PL_get_integer((T),&i) \ - ? ( (J)=(jdouble)i, TRUE) \ - : ( JNI_jlong2_to_jlong((T),jl) \ - ? ( (J)=(jdouble)jl, TRUE) \ - : FALSE \ - ) \ - ) \ - ) - -#define JNI_term_to_jfieldID(T,J) \ - ( PL_get_functor((T),&fn) \ - && fn==JNI_functor_jfieldID_1 \ - && ( a1=PL_new_term_ref(), \ - PL_get_arg(1,(T),a1) \ - ) \ - && PL_get_pointer(a1,(void**)&(J)) \ - ) - -#define JNI_term_to_jmethodID(T,J) \ - ( PL_get_functor((T),&fn) \ - && fn==JNI_functor_jmethodID_1 \ - && ( a1=PL_new_term_ref(), \ - PL_get_arg(1,(T),a1) \ - ) \ - && PL_get_pointer(a1,(void**)&(J)) \ - ) - -// converts: -// atom -> String -// @(null) -> NULL -// @(tag) -> obj -// (else fails) -// -#define JNI_term_to_ref(T,J) \ - ( PL_get_atom_chars((T),&cp) \ - ? ((J)=(*env)->NewStringUTF(env,cp))!=NULL \ - : PL_get_functor((T),&fn) \ - && fn==JNI_functor_at_1 \ - && ( a1=PL_new_term_ref(), \ - PL_get_arg(1,(T),a1) \ - ) \ - && PL_get_atom(a1,&a) \ - && ( a==JNI_atom_null \ - ? ( (J)=0, TRUE) \ - : jni_tag_to_iref(a,(int*)&(J)) \ - ) \ - ) - -// converts: -// atom -> String -// @tag -> obj -// (else fails) -// stricter than JNI_term_to_ref(T,J) -// -#define JNI_term_to_jobject(T,J) \ - ( PL_get_atom_chars((T),&cp) \ - ? ((J)=(*env)->NewStringUTF(env,cp))!=NULL \ - : PL_get_functor((T),&fn) \ - && fn==JNI_functor_at_1 \ - && ( a1=PL_new_term_ref(), \ - PL_get_arg(1,(T),a1) \ - ) \ - && PL_get_atom(a1,&a) \ - && a!=JNI_atom_null \ - && jni_tag_to_iref(a,(int*)&(J)) \ - ) - - -// for now, these specific test-and-convert macros -// are merely mapped to their nearest ancestor... - -#define JNI_term_to_jclass(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_throwable_jclass(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_non_array_jclass(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_throwable_jobject(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_jstring(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_object_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_boolean_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_byte_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_char_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_short_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_int_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_long_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_float_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_double_jarray(T,J) JNI_term_to_jobject(T,J) - -#define JNI_term_to_jbuf(T,J,TP) \ - ( PL_get_functor((T),&fn) \ - && fn==JNI_functor_jbuf_2 \ - && ( a2=PL_new_term_ref(), \ - PL_get_arg(2,(T),a2) \ - ) \ - && PL_get_atom(a2,&a) \ - && a==(TP) \ - && ( a1=PL_new_term_ref(), \ - PL_get_arg(1,(T),a1) \ - ) \ - && PL_get_pointer(a1,(void**)&(J)) \ - ) - -#define JNI_term_to_charP(T,J) \ - PL_get_atom_chars((T),&(J)) - -#define JNI_term_to_pointer(T,J) \ - PL_get_pointer((T),(void**)&(J)) - - -// JNI Java-to-Prolog conversion macros: - -#define JNI_unify_void(T) \ - PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_at_1, \ - PL_ATOM, JNI_atom_void \ - ) - -#define JNI_unify_false(T) \ - PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_at_1, \ - PL_ATOM, JNI_atom_false \ - ) - -#define JNI_unify_true(T) \ - PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_at_1, \ - PL_ATOM, JNI_atom_true \ - ) - -#define JNI_jboolean_to_term(J,T) \ - ( (J)==0 \ - ? JNI_unify_false((T)) \ - : JNI_unify_true((T)) \ - ) - -#define JNI_jchar_to_term(J,T) \ - PL_unify_integer((T),(int)(J)) - -#define JNI_jbyte_to_term(J,T) \ - PL_unify_integer((T),(int)(J)) - -#define JNI_jshort_to_term(J,T) \ - PL_unify_integer((T),(int)(J)) - -#define JNI_jint_to_term(J,T) \ - PL_unify_integer((T),(int)(J)) - -#define JNI_jlong_to_term(J,T) \ - ( ( jl=(J), \ - xhi=((int*)&jl)[1], \ - xlo=((int*)&jl)[0], \ - TRUE \ - ) \ - && ( ( xhi== 0 && xlo>=0 ) \ - || ( xhi==-1 && xlo< 0 ) \ - ) \ - ? PL_unify_integer((T),xlo) \ - : PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_jlong_2, \ - PL_INT, xhi, \ - PL_INT, xlo \ - ) \ - ) - -#define JNI_jfloat_to_term(J,T) \ - PL_unify_float((T),(double)(J)) - -#define JNI_jdouble_to_term(J,T) \ - PL_unify_float((T),(double)(J)) - -// J can be an *expression* parameter to this macro; -// we must evaluate it exactly once; hence we save its value -// in the variable j, which must be dynamic (e.g. local) -// if this macro is to be re-entrant -#define JNI_jobject_to_term(J,T) \ - ( ( j=(J), j==NULL ) \ - ? PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_at_1, \ - PL_ATOM, JNI_atom_null \ - ) \ - : ( (*env)->IsInstanceOf(env,j,str_class) \ - ? jni_string_to_atom(j,&a) \ - && PL_unify_term((T), \ - PL_ATOM, a \ - ) \ - : jni_object_to_iref(j,&i) \ - && jni_iref_to_tag(i,&a) \ - && PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_at_1, \ - PL_ATOM, a \ - ) \ - ) \ - ) - -#define JNI_jfieldID_to_term(J,T) \ - PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_jfieldID_1, \ - PL_POINTER, (void*)(J) \ - ) - -#define JNI_jmethodID_to_term(J,T) \ - PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_jmethodID_1, \ - PL_POINTER, (void*)(J) \ - ) - -#define JNI_jbuf_to_term(J,T,TP) \ - PL_unify_term((T), \ - PL_FUNCTOR, JNI_functor_jbuf_2, \ - PL_POINTER, (void*)(J), \ - PL_ATOM, (TP) \ - ) - -#define JNI_pointer_to_term(J,T) \ - PL_unify_pointer((T),(void*)(J)) - -#define JNI_charP_to_term(J,T) \ - PL_unify_atom_chars((T),(J)) - - - -//=== JNI initialisation macro (typically succeeds cheaply) ======================================== - -#define jni_ensure_jvm() ( ( jvm != NULL \ - || jni_create_default_jvm() \ - ) \ - && jni_get_env() \ - ) - - -//=== JPL initialisation macros (typically succeed cheaply) ======================================== - -// outcomes: -// fail to find jpl.*, jpl.fli.* classes or to convert init args to String[]: exception, FALSE -// JPL is (newly or already) out of RAW state: TRUE -#define jpl_ensure_jpl_init(e) ( jpl_status != JPL_INIT_RAW \ - || jpl_do_jpl_init(e) \ - ) -// outcomes: -// JPL or PVM init has already failed: FALSE -// JPL or PVM init fails while being necessarily attempted: exception -// JPL is (newly or already) fully initialised: TRUE -#define jpl_ensure_pvm_init(e) ( jpl_status == JPL_INIT_OK \ - || ( jpl_ensure_jpl_init(e) , FALSE ) \ - || jpl_test_pvm_init(e) \ - || jpl_do_pvm_init(e) \ - ) - - -//=== types (structs and typedefs) ================================================================= - -// types for "hashed refs": - -typedef struct Hr_Entry HrEntry; // enables circular definition... - -struct Hr_Entry { // a single interned reference - jobject obj; // a JNI global ref - int hash; // identityHashCode(obj) - HrEntry *next; // next entry in this chain, or NULL - }; - -typedef struct Hr_Table HrTable; - -struct Hr_Table { - int count; // current # entries - int threshold; // rehash on add when count==threshold - int length; // # slots in slot array - HrEntry **slots; // pointer to slot array - }; - -typedef long pointer; // for JPL (I reckon 'int' is enough on 32-bit systems) -typedef int bool; // for JNI/JPL functions returning only TRUE or FALSE - - - -//=== JNI "constants" ============================================================================== - -// sizes of JNI primitive types: - -int size[16] = { // NB relies on sequence of JNI_XPUT_* defs - 0, - sizeof(jboolean), // size[JNI_XPUT_BOOLEAN] - sizeof(jbyte), // size[JNI_XPUT_BYTE] - sizeof(jchar), // size[JNI_XPUT_CHAR] - sizeof(jshort), // size[JNI_XPUT_SHORT] - sizeof(jint), // size[JNI_XPUT_INT] - sizeof(jlong), // size[JNI_XPUT_LONG] - sizeof(jfloat), // size[JNI_XPUT_FLOAT] - sizeof(jdouble), // size[JNI_XPUT_DOUBLE] - 0, // n/a - JNI_FLOAT_TO_DOUBLE - 0, // n/a - JNI_LONG_TO_FLOAT - 0, // n/a - JNI_LONG_TO_DOUBLE - 0, // n/a - JNI_REF - 0, // n/a - JNI_ATOM - 0, // n/a - JNI_JVALUEP - sizeof(jvalue) // size[JNI_XPUT_JVALUE] - }; - - - -//=== JNI "constants", lazily initialised by jni_init() ============================================ - -static atom_t JNI_atom_false; // false -static atom_t JNI_atom_true; // true - -static atom_t JNI_atom_boolean; // boolean -static atom_t JNI_atom_char; // char -static atom_t JNI_atom_byte; // byte -static atom_t JNI_atom_short; // short -static atom_t JNI_atom_int; // int -static atom_t JNI_atom_long; // long -static atom_t JNI_atom_float; // float -static atom_t JNI_atom_double; // double - -static atom_t JNI_atom_null; // null -static atom_t JNI_atom_void; // void - -static functor_t JNI_functor_at_1; // @(_) -static functor_t JNI_functor_jbuf_2; // jbuf(_,_) -static functor_t JNI_functor_jlong_2; // jlong(_,_) -static functor_t JNI_functor_jfieldID_1; // jfieldID(_) -static functor_t JNI_functor_jmethodID_1; // jmethodID(_) -static functor_t JNI_functor_error_2; // error(_, _) -static functor_t JNI_functor_java_exception_1; // java_exception(_) -static functor_t JNI_functor_jpl_error_1; // jpl_error(_) - - -//=== JNI's static JVM references, lazily initialised by jni_init() ================================ - -static jclass c_class; // java.lang.Class (rename to jClass_c ?) -static jmethodID c_getName; // java.lang.Class' getName() (rename to jClassGetName_m ?) -static jclass str_class; // java.lang.String (this duplicates jString_c below) - -static jclass sys_class; // java.lang.System (rename to jSystem_c ?) -static jmethodID sys_ihc; // java.lang.System's identityHashCode() (rename to jSystemIdentityHashCode_m ?) - - -//=== JPL's reusable global class object refs, initialised by jpl_ensure_jpl_init() ================ - -static jclass jString_c; -static jclass jJPLException_c; -static jclass jTermT_c; -static jclass jAtomT_c; -static jclass jFunctorT_c; -static jclass jFidT_c; -static jclass jPredicateT_c; -static jclass jQidT_c; -static jclass jModuleT_c; -static jclass jEngineT_c; - -static jclass jLongHolder_c; -static jclass jPointerHolder_c; -static jclass jIntHolder_c; -static jclass jDoubleHolder_c; -static jclass jStringHolder_c; -static jclass jObjectHolder_c; -static jclass jBooleanHolder_c; - -static jclass jJRef_c; -static jclass jJBoolean_c; - - -//=== JPL's reusable constant field IDs, set before first use by jpl_ensure_jpl_init() ============= - -static jfieldID jLongHolderValue_f; -static jfieldID jPointerHolderValue_f; -static jfieldID jIntHolderValue_f; -static jfieldID jDoubleHolderValue_f; -static jfieldID jStringHolderValue_f; -static jfieldID jObjectHolderValue_f; -static jfieldID jBooleanHolderValue_f; - -static jfieldID jJRefRef_f; -static jfieldID jJBooleanValue_f; - - - -//=== JPL's default args for PL_initialise() (NB these are not really good enough) ================= - -const char *default_args[] = { "pl", - "-g", "true", - NULL - }; // *must* have final NULL - - -//=== JNI global state (initialised by jni_create_jvm_c) =========================================== - -static JavaVM *jvm = NULL; // non-null -> JVM successfully loaded & initialised -static JNIEnv *env; // if jvm is defined, then so will this be - - - -//=== JNI global state (hashed global refs) ======================================================== - -static HrTable *hr_table = NULL; // static handle to allocated-on-demand table -static int hr_add_count = 0; // cumulative total of new refs interned -static int hr_old_count = 0; // cumulative total of old refs reused -static int hr_del_count = 0; // cumulative total of dead refs released - - -//=== JPL global state, initialised by jpl_ensure_jpl_init() or jpl_ensure_jvm_init() ============== - -static int jpl_status = JPL_INIT_RAW; // neither JPL nor PVM initialisation has occurred -static jobject dia = NULL; // default init args (after jpl init, until pvm init) -static jobject aia = NULL; // actual init args (after pvm init) -static PL_engine_t *engines = NULL; // handles of the pooled Prolog engines -static int engines_allocated = 0; /* size of engines array */ -static pthread_mutex_t engines_mutex = PTHREAD_MUTEX_INITIALIZER; // for controlling pool access -static pthread_cond_t engines_cond = PTHREAD_COND_INITIALIZER; // for controlling pool access - - -//=== common functions ============================================================================= - -static char * -jpl_c_lib_version() - { - static char v[100]; // version string - static char *vp = NULL; // set to v at first call - - if ( vp != NULL ) // already set? - { - return vp; - } - sprintf( v, "%d.%d.%d-%s", JPL_C_LIB_VERSION_MAJOR, JPL_C_LIB_VERSION_MINOR, JPL_C_LIB_VERSION_PATCH, JPL_C_LIB_VERSION_STATUS); - vp = v; - return vp; - } - - -/* -%T jpl_c_lib_version( -atom) - */ - -// ... -// -static foreign_t -jpl_c_lib_version_1_plc( - term_t ta - ) - { - - return PL_unify_atom_chars(ta,jpl_c_lib_version()); - } - - -/* -%T jpl_c_lib_version( -integer, -integer, -integer, -atom) - */ - -// ... -// -static foreign_t -jpl_c_lib_version_4_plc( - term_t tmajor, - term_t tminor, - term_t tpatch, - term_t tstatus - ) - { - - return PL_unify_integer(tmajor,JPL_C_LIB_VERSION_MAJOR) - && PL_unify_integer(tminor,JPL_C_LIB_VERSION_MINOR) - && PL_unify_integer(tpatch,JPL_C_LIB_VERSION_PATCH) - && PL_unify_atom_chars(tstatus,JPL_C_LIB_VERSION_STATUS); - } - - -//=== JNI function prototypes (to resolve unavoidable forward references) ========================== - -static int jni_hr_add(jobject,int*); -static int jni_hr_del(int); - - -//=== JNI functions (NB first 6 are cited in macros used subsequently) ============================= - -// this now checks that the atom's name resembles a tag (PS 18/Jun/2004) -static bool -jni_tag_to_iref( - atom_t a, - int *iref - ) - { - const char *s = PL_atom_chars(a); - - return strlen(s) == 12 - && s[0] == 'J' - && s[1] == '#' - && isdigit(s[2]) - && isdigit(s[3]) - && isdigit(s[4]) - && isdigit(s[5]) - && isdigit(s[6]) - && isdigit(s[7]) - && isdigit(s[8]) - && isdigit(s[9]) - && isdigit(s[10]) - && isdigit(s[11]) // s is like 'J#0123456789' - && (*iref=atoi(&s[2])) != 0; - } - - -static bool -jni_iref_to_tag( - int iref, - atom_t *a - ) - { - char abuf[13]; - - sprintf( abuf, "J#%010u", iref); // oughta encapsulate this mapping... - *a = PL_new_atom(abuf); - PL_unregister_atom(*a); // empirically decrement reference count... - return TRUE; // can't fail (?!) - } - - -static bool -jni_object_to_iref( - jobject obj, // a newly returned JNI local ref - int *iref // gets an integerised, canonical, global equivalent - ) - { - int r; // temp for result code - - if ( (r=jni_hr_add(obj,iref)) == JNI_HR_ADD_NEW ) - { - hr_add_count++; // obj was novel, has been added to dict - return TRUE; - } - else - if ( r == JNI_HR_ADD_OLD ) - { - hr_old_count++; // obj was already in dict - return TRUE; - } - else - { - return FALSE; // r == JNI_HR_ADD_FAIL, presumably - } - } - - -// retract all jpl_iref_type_cache(Iref,_) facts -static bool -jni_tidy_iref_type_cache( - int iref - ) - { - term_t goal = PL_new_term_ref(); - - PL_unify_term( goal, - PL_FUNCTOR, PL_new_functor(PL_new_atom("jpl_tidy_iref_type_cache"),1), - PL_INT, iref - ); - return PL_call( - goal, - PL_new_module(PL_new_atom("user")) - ); - } - - -// could merge this into jni_hr_del() ? -static bool -jni_free_iref( // called indirectly from agc hook when a possible iref is unreachable - int iref - ) - { - - if ( jni_hr_del(iref) ) // iref matched a hashedref table entry? (in which case, was deleted) - { - if ( !jni_tidy_iref_type_cache(iref) ) - { - DEBUG(0, Sdprintf( "[JPL: jni_tidy_iref_type_cache(%u) failed]\n", iref)); - } - hr_del_count++; - return TRUE; - } - else - { - return FALSE; - } - } - - -static bool -jni_string_to_atom( // called from the JNI_jobject_to_term(J,T) macro - jobject obj, - atom_t *a - ) - { - const char *cp; - - return (cp=(*env)->GetStringUTFChars(env,obj,NULL)) != NULL - && ( *a=PL_new_atom(cp), TRUE) - && ( (*env)->ReleaseStringUTFChars(env,obj,cp), TRUE); - } - - -/* -%T jni_tag_to_iref( +atom, -integer) - */ - -// an FLI wrapper for jni_tag_to_iref() above -// with luck, this will be redundant when hybrid atom+int tag scheme is sorted -// is currently called by jpl_tag_to_type/2, jpl_cache_type_of_object/2 -// jpl_tag_to_type/2 is called by jpl_object_to_type/2, jpl_ref_to_type/2 -// -static foreign_t -jni_tag_to_iref_plc( - term_t tt, - term_t ti - ) - { - atom_t a; - int iref; - - return PL_get_atom(tt,&a) - && jni_tag_to_iref(a,&iref) - && PL_unify_integer(ti,iref); - } - - -// this will be hooked to SWI-Prolog's PL_agc_hook, -// and is called just before each redundant atom is expunged from the dict -// NB need to be able to switch this on and off from Prolog... -// -static bool -jni_atom_freed( - atom_t a - ) - { - const char *cp = PL_atom_chars(a); - int iref; - char cs[11]; - - if ( jni_tag_to_iref( a, &iref) ) // check format and convert digits to int if ok - { - sprintf( cs, "%010u", iref); // reconstruct digits part of tag in cs - if ( strcmp(&cp[2],cs) != 0 ) // original digits != reconstructed digits? - { - DEBUG(0, Sdprintf( "[JPL: garbage-collected tag '%s'=%u is bogus (not canonical)]\n", cp, iref)); - } - else - if ( !jni_free_iref(iref) ) // free it (iff it's in the hashedref table) - { - DEBUG(0, Sdprintf( "[JPL: garbage-collected tag '%s' is bogus (not in HashedRefs)]\n", cp)); - } - } - else - { - } - return TRUE; // means "go ahead and expunge the atom" (we do this regardless) - } - - -//=== "hashed ref" (canonical JNI global reference) support ======================================== - -/* -%T jni_hr_info( -term, -term, -term, -term) - */ - -static foreign_t -jni_hr_info_plc( // implements jni_hr_info/4 - term_t t1, // -integer: # object references currently in hash table - term_t t2, // -integer: total # object references so far added - term_t t3, // -integer: total # object references so far found to be already in table - term_t t4 // -integer: total # object references deleted from table (by atom GC) - ) - { - return PL_unify_integer(t1,(hr_table==NULL?0:hr_table->count)) // 0 was -1 (??) - && PL_unify_integer(t2,hr_add_count) - && PL_unify_integer(t3,hr_old_count) - && PL_unify_integer(t4,hr_del_count); - } - - -// unifies t2 with a Prolog term which represents the contents of the hashtable slot -// -static bool -jni_hr_table_slot( - term_t t2, - HrEntry *slot - ) - { - term_t tp = PL_new_term_ref(); - - if ( slot == NULL ) - { - return PL_unify_nil(t2); - } - else - { - return PL_unify_list(t2,tp,t2) - && PL_unify_term(tp, - PL_FUNCTOR, PL_new_functor(PL_new_atom("-"),2), - PL_INT, slot->hash, - PL_INT, (int)(slot->obj) - ) - && jni_hr_table_slot(t2,slot->next) - ; - } - } - - -/* -%T jni_hr_table( -term) - */ -// unifies t with a list of hash table slot representations -// -static foreign_t -jni_hr_table_plc( - term_t t - ) - { - term_t t1 = PL_copy_term_ref(t); - term_t t2 = PL_new_term_ref(); - int i; - - for ( i=0 ; ilength ; i++ ) - { - if ( !PL_unify_list(t1,t2,t1) || !jni_hr_table_slot(t2,hr_table->slots[i]) ) - { - return FALSE; - } - } - return PL_unify_nil(t1); - } - - -// an empty table of length is successfully created, where none was before -// -static bool -jni_hr_create( - int length // required # slots in table - ) - { - int i; // temp for iterative slot initialisation - - if ( hr_table != NULL ) - { - return FALSE; // table already exists (destroy before recreating) - } - if ( length <= 0 ) - { - return FALSE; // unsuitable length - } - if ( (hr_table=(HrTable*)malloc(sizeof(HrTable))) == NULL ) - { - return FALSE; // malloc failed (out of memory, presumably) - } - hr_table->length = length; - hr_table->threshold = (int)(hr_table->length*JNI_HR_LOAD_FACTOR); - if ( (hr_table->slots=(HrEntry**)malloc(length*sizeof(HrEntry*))) == NULL ) - { - return FALSE; // malloc failed: out of memory, presumably - } - for ( i=0 ; ilength ; i++ ) - { - hr_table->slots[i] = NULL; - } - hr_table->count = 0; - return TRUE; - } - - -// an empty table of some default length is successfully created, where none was before -// -static bool -jni_hr_create_default() - { - - return jni_hr_create( 101); - } - - -// ep must point to a chain of zero or more entries; they are freed -// -static void -jni_hr_free_chain_entries( - HrEntry *ep - ) - { - - if ( ep != NULL ) - { - jni_hr_free_chain_entries( ep->next); - free( ep); - } - } - - -// table t is emptied -// -static void -jni_hr_free_table_chains( - HrTable *t - ) - { - int index; - - for ( index=0 ; index<(t->length) ; index++ ) - { - jni_hr_free_chain_entries( t->slots[index]); - t->slots[index] = NULL; - } - t->count = 0; - } - - -// all dynamic space used by the pointed-to table is freed -// -static bool -jni_hr_free_table( - HrTable *t - ) - { - - if ( t == NULL ) - { - return FALSE; // table does not exist - } - else - { - jni_hr_free_table_chains( t); - free( t); - return TRUE; - } - } - - -// the current table is replaced by an equivalent one with more free space -// -static bool -jni_hr_rehash() - { - HrTable *t0; // old table while building new one from it - int i; // for iterating through slots in old table - HrEntry *ep1; // for iterating through all entries in old table - HrEntry *ep2; // an old table entry being relinked into new table - int index; // slot index in new table of entry being transferred - - t0 = hr_table; // temporarily hold onto former table - hr_table = NULL; // precondition for jni_hr_create - if ( !jni_hr_create(2*t0->length+1) ) // new bigger table in its place - { - hr_table = t0; // replace former table for tidiness - return FALSE; // failed to create replacement table during rehash - } - for ( i=0 ; ilength ; i++ ) // for each slot in *former* table - { - for ( ep1=t0->slots[i] ; ep1!=NULL ; ) - { // for each entry in that slot's chain - ep2 = ep1; // grab this entry - ep1 = ep1->next; // advance to next entry or NULL - index = (ep2->hash & 0x7fffffff) % hr_table->length; // new - ep2->next = hr_table->slots[index]; // relink into new array - hr_table->slots[index] = ep2; // " - } - t0->slots[i] = NULL; // tidy old array for generic freeing later - } - hr_table->count = t0->count; // new table's count is old table's count - jni_hr_free_table( t0); // free all space used by old table (NB no entries) - return TRUE; - } - - -static bool -jni_hr_hash( - jobject obj, // MUST BE a valid non-null reference to a Java object - int *hash // gets obj's System.identityHashCode() - ) - { - jobject e; // for possible (but unlikely?) exception - - *hash = (*env)->CallStaticIntMethod(env,sys_class,sys_ihc,obj,(int)obj); - return (e=(*env)->ExceptionOccurred(env))==NULL; - } - - -// returns -// JNI_HR_ADD_NEW -> referenced object is novel -// JNI_HR_ADD_OLD -> referenced object is already known -// JNI_HR_ADD_FAIL -> something went wrong -// and, in *iref, an integerised canonical global ref to the object -// -static int -jni_hr_add( - jobject lref, // new JNI local ref from a regular JNI call - int *iref // for integerised canonical global ref - ) - { - int hash; // System.identityHashCode of lref - int index; // lref's slot index, from hash - HrEntry *ep; // temp entry pointer for chain traversal - jobject gref; // iff lref is novel, will hold a global surrogate - - if ( hr_table==NULL && !jni_hr_create_default() ) - { - return JNI_HR_ADD_FAIL; // lazy table creation failed: oughta sort return codes - } - if ( !jni_hr_hash(lref,&hash) ) - { - return JNI_HR_ADD_FAIL; // System.identityHashCode() failed (?) - } - index = (hash & 0x7fffffff) % hr_table->length; // make this a macro? - for ( ep=hr_table->slots[index] ; ep!=NULL ; ep=ep->next ) - { - if ( ep->hash==hash ) - { - if ( (*env)->IsSameObject(env,ep->obj,lref) ) - { // newly referenced object is already interned - (*env)->DeleteLocalRef(env,lref); // free redundant new ref - *iref = (int)(ep->obj); // old, equivalent (global) ref - return JNI_HR_ADD_OLD; - } - } - } - if ( hr_table->count >= hr_table->threshold ) - { - (void)jni_hr_rehash(); // oughta check for failure, and return it... - return jni_hr_add(lref,iref); // try again with new, larger table - } - // referenced object is novel, and we can add it to table - if ( (gref=(*env)->NewGlobalRef(env,lref)) == NULL ) // derive a global ref - { - return JNI_HR_ADD_FAIL; - } - (*env)->DeleteLocalRef(env,lref); // free redundant (local) ref - ep = (HrEntry*)malloc(sizeof(HrEntry)); - ep->hash = hash; - ep->obj = gref; - ep->next = hr_table->slots[index]; // insert at front of chain - hr_table->slots[index] = ep; - hr_table->count++; - *iref = (int)gref; // pass back the (new) global ref - return JNI_HR_ADD_NEW; // obj was newly interned, under iref as supplied - } - - -// iref corresponded to an entry in the current HashedRef table; -// now that entry is gone, its space is recovered, counts are adjusted etc. -// -static bool -jni_hr_del( - int iref // a possibly spurious canonical global iref - ) - { - int index; // index to a HashedRef table slot - HrEntry *ep; // pointer to a HashedRef table entry - HrEntry **epp; // pointer to ep's handle, in case it needs updating - - DEBUG(1, Sdprintf( "[removing possible object reference %u]\n", obj)); - for ( index=0 ; indexlength ; index++ ) // for each slot - { - for ( epp=&(hr_table->slots[index]), ep=*epp ; ep!=NULL ; epp=&(ep->next), ep=*epp ) - { - if ( (int)(ep->obj) == iref ) // found the sought entry? - { - (*env)->DeleteGlobalRef( env, ep->obj); // free the global object reference - *epp = ep->next; // bypass the entry - free( ep); // free the now-redundant space - hr_table->count--; // adjust table's entry count - DEBUG(1, Sdprintf( "[found & removed hashtable entry for object reference %u]\n", iref)); - // should we do something with jni_iref_tidy_type_cache() here? - return TRUE; // entry found and removed - } - } - } - DEBUG(1, Sdprintf("[JPL: failed to find hashtable entry for (presumably bogus) object reference %u]\n", iref)); - return FALSE; - } - - -#if 0 /* These functions are not yet used */ - -static void -jni_hr_destroy() // tidily returns to consistent "table absent" state - { - - jni_hr_free_table( hr_table); - hr_table = NULL; - } - - -// this gets called OK, but I don't know the state of the JVM, -// or what happens to a pending JNI call -// -static void -jvm_exit( - jint code - ) - { - // term_t e = PL_new_term_ref(); - - // PL_unify_term( e, - // PL_FUNCTOR, JNI_functor_java_exception_2, - // PL_CHARS, "exited", - // PL_INT, code - // ); - // return PL_raise_exception(e); - DEBUG(0, Sdprintf( "[JPL: JVM exits: code=%d]\n", code)); - } - - -// this gets called OK, but I don't know the state of the JVM, -// or what happens to a pending JNI call -// -static void -jvm_abort() - { - // term_t e = PL_new_term_ref(); - - // PL_unify_term( e, - // PL_FUNCTOR, JNI_functor_java_exception_2, - // PL_CHARS, "aborted", - // PL_INT, 0 - // ); - // return PL_raise_exception(e); - DEBUG(0, Sdprintf( "[JPL: JVM aborts]\n")); - } - -#endif /*0*/ - - -// called once: after successful PVM & JVM creation/discovery, before any JNI calls -// -static int -jni_init() - { - jclass lref; // temporary local ref, replaced by global - - // these initialisations require an active PVM: - JNI_atom_false = PL_new_atom( "false"); - JNI_atom_true = PL_new_atom( "true"); - - JNI_atom_boolean = PL_new_atom( "boolean"); - JNI_atom_char = PL_new_atom( "char"); - JNI_atom_byte = PL_new_atom( "byte"); - JNI_atom_short = PL_new_atom( "short"); - JNI_atom_int = PL_new_atom( "int"); - JNI_atom_long = PL_new_atom( "long"); - JNI_atom_float = PL_new_atom( "float"); - JNI_atom_double = PL_new_atom( "double"); - - JNI_atom_null = PL_new_atom( "null"); - JNI_atom_void = PL_new_atom( "void"); // not yet used properly (?) - - JNI_functor_at_1 = PL_new_functor( PL_new_atom("@"), 1); - JNI_functor_jbuf_2 = PL_new_functor( PL_new_atom("jbuf"), 2); - JNI_functor_jlong_2 = PL_new_functor( PL_new_atom("jlong"), 2); - JNI_functor_jfieldID_1 = PL_new_functor( PL_new_atom("jfieldID"), 1); - JNI_functor_jmethodID_1 = PL_new_functor( PL_new_atom("jmethodID"), 1); - - JNI_functor_error_2 = PL_new_functor(PL_new_atom("error"), 2); - JNI_functor_java_exception_1 = PL_new_functor( PL_new_atom("java_exception"), 1); - JNI_functor_jpl_error_1 = PL_new_functor( PL_new_atom("jpl_error"), 1); - - (void)PL_agc_hook( jni_atom_freed); // link atom GC to object GC (cool:-) - - // these initialisations require an active JVM: - return ( (lref=(*env)->FindClass(env,"java/lang/Class")) != NULL - && (c_class=(*env)->NewGlobalRef(env,lref)) != NULL - && ( (*env)->DeleteLocalRef(env,lref), TRUE) - && (lref=(*env)->FindClass(env,"java/lang/String")) != NULL - && (str_class=(*env)->NewGlobalRef(env,lref)) != NULL - && ( (*env)->DeleteLocalRef(env,lref), TRUE) - && (c_getName=(*env)->GetMethodID(env,c_class,"getName","()Ljava/lang/String;")) != NULL - && (lref=(*env)->FindClass(env,"java/lang/System")) != NULL - && (sys_class=(*env)->NewGlobalRef(env,lref)) != NULL - && ( (*env)->DeleteLocalRef(env,lref), TRUE) - && (sys_ihc=(*env)->GetStaticMethodID(env,sys_class,"identityHashCode","(Ljava/lang/Object;)I")) != NULL - ? 0 - : -7 // NB #define this? - ) - ; - } - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -jni_new_java_exception(char *comment, atom_t ex) - -Throw a java exception as error(java_exception(@ex), comment) -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -static term_t -jni_new_java_exception( // construct a Prolog exception structure java_exception/2 - const char *m, // to represent a caught Java exception - atom_t a - ) - { - term_t e = PL_new_term_ref(); - - PL_unify_term(e, - PL_FUNCTOR, JNI_functor_error_2, - PL_FUNCTOR, JNI_functor_java_exception_1, - PL_FUNCTOR, JNI_functor_at_1, - PL_ATOM, a, - PL_CHARS, m); - return e; - } - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -jni_new_jpl_error(char *comment, atom_t ex) - -As above, but used for internal JPL errors -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -static term_t -jni_new_jpl_error( // construct a Prolog exception structure jpl_error/2 - const char *m, // to represent an exceptional condition within JSP - atom_t a - ) - { - term_t e = PL_new_term_ref(); - - PL_unify_term(e, - PL_FUNCTOR, JNI_functor_error_2, - PL_FUNCTOR, JNI_functor_jpl_error_1, - PL_FUNCTOR, JNI_functor_at_1, - PL_ATOM, a, - PL_CHARS, m); - return e; - } - - -// test for a raised exception; clear and report it if found -// -static bool -jni_check_exception() - { - jobject ej; // the pending Java exception, if any - jobject c; // its class - jobject s; // its class name as a JVM String, for the report - const char *cp; // its class name as a C string - term_t ep; // a newly created Prolog exception - int i; // temp for an iref denoting a Java exception - atom_t a; // temp for a tag denoting a Java exception - - if ( (ej=(*env)->ExceptionOccurred(env)) == NULL ) - { - return TRUE; - } - else - { - (*env)->ExceptionClear(env); // clear "exception-pending" state so we can do JNI calls - if ( (c=(*env)->GetObjectClass(env,ej)) != NULL ) - { // we've got its class - if ( (s=(*env)->CallObjectMethod(env,c,c_getName)) != NULL ) - { // we've got its name as a String - if ( jni_object_to_iref(ej,&i) ) - { - if ( jni_iref_to_tag(i,&a) ) - { - if ( (cp=(*env)->GetStringUTFChars(env,s,NULL)) != NULL ) - { - DEBUG(1, Sdprintf( "[#JNI exception occurred: %s]\n", cp)); - ep = jni_new_java_exception(cp,a); - (*env)->ReleaseStringUTFChars(env,s,cp); - } - else - { - ep = jni_new_jpl_error("FailedToGetUTFCharsOfNameOfClassOfException",a); - } - } - else - { - ep = jni_new_jpl_error("FailedToConvertExceptionIrefToTagatom",JNI_atom_null); - } - } - else - { - ep = jni_new_jpl_error("FailedToConvertExceptionObjectToIref",JNI_atom_null); - } - (*env)->DeleteLocalRef(env,s); - } - else - { - ep = jni_new_jpl_error("FailedToGetNameOfClassOfException",JNI_atom_null); - } - (*env)->DeleteLocalRef(env,c); - } - else - { - ep = jni_new_jpl_error("FailedToGetClassOfException",JNI_atom_null); - } - return PL_raise_exception(ep); - } - } - - -//=== buffer and method param transput ============================================================= - -/* -%T jni_byte_buf_length_to_codes( +integer, +integer, -term) - */ - -static foreign_t -jni_byte_buf_length_to_codes_plc( // carefully s/chars/codes/ :-( - term_t tbb, - term_t tlen, - term_t tcs - ) - { - functor_t fn; - term_t a1; - atom_t a; - term_t a2; - jbyte *bb; - int len; - int i; - term_t tl = PL_copy_term_ref( tcs); - term_t ta = PL_new_term_ref(); - void *ptr; - - if ( !( PL_get_functor(tbb,&fn) - && fn==JNI_functor_jbuf_2 - && ( a2=PL_new_term_ref(), - PL_get_arg(2,tbb,a2) - ) - && PL_get_atom(a2,&a) - && a==JNI_atom_byte - && ( a1=PL_new_term_ref(), - PL_get_arg(1,tbb,a1) - ) - && PL_get_pointer(a1,&ptr) - ) - || !PL_get_integer(tlen,&len) - ) - { - return FALSE; - } - bb = ptr; - - for ( i=0 ; i first) - term_t txc, // transput code, as Prolog integer, appropriate to this param - term_t tt, // param value as datum (value or ref) - term_t tjvp // param buffer (allocated just for this call) - ) - { - int n; // got from tn (see above) - int xc; // got from txc (see above) - jvalue *jvp; // got from tjvp (see above) - functor_t fn; // temp for conversion macros - term_t a1; // " - term_t a2; // " - atom_t a; // " - char *cp; // " - int i; // " - int xhi; // " - int xlo; // " - // jobject j; // " - jlong jl; // " - int ix; // temp for conversion - double dx; // " - long lx; // " - void *ptr; - - if ( !PL_get_integer(tn,&n) || - !PL_get_integer(txc,&xc) || - !PL_get_pointer(tjvp,&ptr) ) - { - return FALSE; - } - jvp = ptr; - - switch ( xc ) - { - case JNI_XPUT_BOOLEAN: - return JNI_term_to_jboolean(tt,jvp[n].z); - - case JNI_XPUT_BYTE: - return PL_get_integer(tt,&ix) - && ix >= JNI_MIN_JBYTE - && ix <= JNI_MAX_JBYTE - && ( (jvp[n].b=(jboolean)ix) , TRUE ); - - case JNI_XPUT_CHAR: - return PL_get_integer(tt,&ix) - && ix >= JNI_MIN_JCHAR - && ix <= JNI_MAX_JCHAR - && ( (jvp[n].c=(jchar)ix) , TRUE ); - - case JNI_XPUT_SHORT: - return PL_get_integer(tt,&ix) - && ix >= JNI_MIN_JSHORT - && ix <= JNI_MAX_JSHORT - && ( (jvp[n].s=(jshort)ix) , TRUE ); - - case JNI_XPUT_INT: - return JNI_term_to_jint(tt,jvp[n].i); - - case JNI_XPUT_LONG: - return JNI_term_to_jlong(tt,jvp[n].j); - - case JNI_XPUT_FLOAT: - return ( PL_get_float(tt,&dx) - ? ( jvp[n].f=(jfloat)dx, TRUE) - : ( PL_get_integer(tt,&ix) - ? ( jvp[n].f=(jfloat)ix, TRUE) - : ( JNI_jlong2_to_jlong(tt,lx) - ? ( jvp[n].f=(jfloat)lx, TRUE) - : FALSE - ) - ) - ); - - case JNI_XPUT_DOUBLE: - return JNI_term_to_jdouble(tt,jvp[n].d); - - case JNI_XPUT_REF: - return JNI_term_to_ref(tt,jvp[n].l); - - default: - return FALSE; // unknown or inappropriate JNI_XPUT_* code - } - } - - -/* -%T jni_alloc_buffer( +integer, +integer, -integer) - */ - -// for completeness, allocates zero-length buffers too, -// while avoiding malloc() problems -// -static foreign_t -jni_alloc_buffer_plc( - term_t txc, // +transput code - term_t tlen, // +required length (# items) - term_t tbp // -PL_POINTER to newly allocated buffer - ) - { - int xc; - int len; - void *bp; - - return PL_get_integer(txc,&xc) - && ( ( xc>=JNI_XPUT_BOOLEAN && xc<=JNI_XPUT_DOUBLE ) || xc==JNI_XPUT_JVALUE ) - && PL_get_integer(tlen,&len) - && len >= 0 - && (bp=malloc((len==0?1:len)*size[xc])) != NULL // avoid (unsafe) malloc(0) - && ( PL_unify_pointer(tbp,(void*)bp) - ? TRUE - : ( free(bp), FALSE) - ) - ; - } - - -/* -%T jni_free_buffer( +integer) - */ - -static foreign_t -jni_free_buffer_plc( - term_t tbp // +pointer: a redundant buffer - ) - { - void *bp; - - return PL_get_pointer(tbp,&bp) - && ( free(bp), TRUE); - } - - -/* -%T jni_fetch_buffer_value( +integer, +integer, +integer, -integer, -term) - */ - -// NB simplify this routine as done for jni_params_put -// -static foreign_t -jni_fetch_buffer_value_plc( - term_t tbp, // +pointer: an active buffer from jni_alloc_buffer/3 - term_t ti, // +integer: index into buffer; 0 <= i < length - term_t tv2, // -integer: hi int of value, or 0 - term_t tv1, // -integer|-float: lo int of value, or float - term_t txc // +integer: transput code (one of JNI_XPUT_*) - ) - { - void *bp; // buffer address (trusted to be valid) - int i; // buffer index (trusted to be valid) - int xc; // transput code (range-checked by switch statement) - - if ( !PL_get_pointer(tbp,&bp) || !PL_get_integer(ti,&i) || !PL_get_integer(txc,&xc) ) - { - return FALSE; - } - - switch ( xc ) - { - case JNI_XPUT_BOOLEAN: - return PL_unify_integer(tv2,0) - && PL_unify_integer(tv1,((jboolean*)bp)[i]); - - case JNI_XPUT_CHAR: - return PL_unify_integer(tv2,0) - && PL_unify_integer(tv1,((jchar*)bp)[i]); - - case JNI_XPUT_BYTE: - return PL_unify_integer(tv2,0) - && PL_unify_integer(tv1,((jbyte*)bp)[i]); - - case JNI_XPUT_SHORT: - return PL_unify_integer(tv2,0) - && PL_unify_integer(tv1,((jshort*)bp)[i]); - - case JNI_XPUT_INT: - return PL_unify_integer(tv2,0) - && PL_unify_integer(tv1,((jint*)bp)[i]); - - case JNI_XPUT_LONG: - return PL_unify_integer(tv2,((int*)&((jlong*)bp)[i])[1]) - && PL_unify_integer(tv1,((int*)&((jlong*)bp)[i])[0]); - - case JNI_XPUT_FLOAT: - return PL_unify_integer(tv2,0) - && PL_unify_float(tv1,((jfloat*)bp)[i]); - - case JNI_XPUT_DOUBLE: - return PL_unify_integer(tv2,((int*)&((jdouble*)bp)[i])[1]) - && PL_unify_integer(tv1,((int*)&((jdouble*)bp)[i])[0]); - default: - return FALSE; - } - } - - -/* -%T jni_stash_buffer_value( +integer, +integer, +integer, +term, +integer) - */ - -static foreign_t -jni_stash_buffer_value_plc( - term_t tbp, - term_t ti, - term_t tv2, - term_t tv1, - term_t txc - ) - { - void *bp; - int i; - int xc; - // int v1; - // int v2; - jlong vjl; - double vd; - - if ( !PL_get_pointer(tbp,&bp) - || !PL_get_integer(ti,&i) - || !PL_get_integer(txc,&xc) - ) - { - return FALSE; - } - - switch ( xc ) - { - case JNI_XPUT_BOOLEAN: - return PL_get_integer(tv1,(int*)&((jboolean*)bp)[i]); // NB not &(int) - - case JNI_XPUT_CHAR: - return PL_get_integer(tv1,(int*)&((jchar*)bp)[i]); // NB not &(int) - - case JNI_XPUT_BYTE: - return PL_get_integer(tv1,(int*)&((jbyte*)bp)[i]); // NB not &(int) - - case JNI_XPUT_SHORT: - return PL_get_integer(tv1,(int*)&((jshort*)bp)[i]); // NB not &(int) - - case JNI_XPUT_INT: - return PL_get_integer(tv1,(int*)&((jint*)bp)[i]); - - case JNI_XPUT_LONG: - return PL_get_integer(tv2,&((int*)&((jlong*)bp)[i])[1]) - && PL_get_integer(tv1,&((int*)&((jlong*)bp)[i])[0]); - - case JNI_XPUT_FLOAT: - return PL_get_float(tv1,&vd) - && ( ((jfloat*)bp)[i]=(jfloat)vd, TRUE); - - case JNI_XPUT_DOUBLE: - return PL_get_integer(tv2,&((int*)&((jdouble*)bp)[i])[1]) - && PL_get_integer(tv2,&((int*)&((jdouble*)bp)[i])[0]); - - case JNI_XPUT_FLOAT_TO_DOUBLE: - return PL_get_float(tv1,&((jdouble*)bp)[i]); - - case JNI_XPUT_LONG_TO_FLOAT: - return PL_get_integer(tv2,&((int*)&vjl)[1]) - && PL_get_integer(tv1,&((int*)&vjl)[0]) - && ( ((jfloat*)bp)[i]=(jfloat)vjl, TRUE); - - case JNI_XPUT_LONG_TO_DOUBLE: - return PL_get_integer(tv2,&((int*)&vjl)[1]) - && PL_get_integer(tv1,&((int*)&vjl)[0]) - && ( ((jdouble*)bp)[i]=(jdouble)vjl, TRUE); - - default: - return FALSE; - } - } - - -//=== JVM initialisation, startup etc. ============================================================= - -// this isn't much use; it can't discover JDK 1.2 support... -static int -jni_supported_jvm_version( - int major, - int minor - ) - { - JDK1_1InitArgs vm_args; - int mhi; - int mlo; - - vm_args.version = ((major&0xFFFF)<<16) + (minor&0xFFFF); - JNI_GetDefaultJavaVMInitArgs( &vm_args); - mhi = (vm_args.version>>16)&0xFFFF; - mlo = (vm_args.version)&0xFFFF; - DEBUG(1, Sdprintf( "JNI_GetDefaultJavaVMInitArgs() returns %d,%d\n", mhi, mlo)); - return major == mhi - && minor == mlo - ; - } - - -static int -jni_get_created_jvm_count() - { - int n; - - return ( JNI_GetCreatedJavaVMs(NULL,0,&n) == 0 // what does the '0' arg mean? - ? n - : -1 - ) - ; - } - - -// this could be inlined, or made into a macro? -static int -jni_get_env() - { - JNIEnv *env0 = env; - int r; - - r = (*jvm)->GetEnv(jvm,(void**)&env,JNI_VERSION_1_2) == JNI_OK; - if ( env != env0 ) - { - DEBUG(1, Sdprintf( "[new env=%u]\n", (void*)env)); - } - return r; - } - - -#define MAX_JVM_OPTIONS 10 - -static int -jni_create_jvm_c( - char *classpath - ) - { - JavaVMInitArgs vm_args; - char cpopt[1000]; - JavaVMOption opt[MAX_JVM_OPTIONS]; - int r; - int n; - int optn = 0; - - DEBUG(1, Sdprintf( "[creating JVM with 'java.class.path=%s']\n", classpath)); - vm_args.version = JNI_VERSION_1_2; // "Java 1.2 please" - if ( classpath ) - { strcpy( cpopt, "-Djava.class.path="); - strcat( cpopt, classpath); // oughta check length... - vm_args.options = opt; - opt[optn].optionString = cpopt; - optn++; - } - // opt[optn++].optionString = "-Djava.compiler=NONE"; - // opt[optn].optionString = "exit"; // I don't understand this yet... - // opt[optn++].extraInfo = jvm_exit; - // opt[optn].optionString = "abort"; // I don't understand this yet... - // opt[optn++].extraInfo = jvm_abort; - // opt[optn++].optionString = "-Xcheck:jni"; // extra checking of JNI calls - // opt[optn++].optionString = "-Xnoclassgc"; // so method/field IDs remain valid (?) - // opt[optn].optionString = "vfprintf"; - // opt[optn++].extraInfo = fprintf; // no O/P, then SEGV - // opt[optn++].extraInfo = xprintf; // one message, then SEGV - // opt[optn++].optionString = "-verbose:jni"; - vm_args.nOptions = optn; - // vm_args.ignoreUnrecognized = TRUE; - - return - ( JNI_GetCreatedJavaVMs(&jvm,1,&n) == 0 // what does the '1' arg mean? - && n == 1 - // && (r=(*jvm)->GetEnv(jvm,(void**)&env,JNI_VERSION_1_2)) == JNI_OK - && jni_get_env((void**)&env) - ? 2 // success (JVM already available) - : ( (r=JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args)) == 0 - ? 0 // success (JVM created OK) - : ( jvm=NULL, r) // -ve, i.e. some create error - ) - ); - } - - -static foreign_t -jni_supported_jvm_version_plc( // not as useful as I'd hoped... - term_t t1, - term_t t2 - ) - { - int major; - int minor; - - return PL_get_integer(t1,&major) - && PL_get_integer(t2,&minor) - && jni_supported_jvm_version(major,minor) - ; - } - - -static foreign_t -jni_get_created_jvm_count_plc( - term_t t1 - ) - { - - return PL_unify_integer(t1,jni_get_created_jvm_count()); - } - - -static int -jni_create_jvm( - char *cp - ) - { - int r1; - int r2; - - DEBUG(1, Sdprintf("[JPL: checking for Java VM...]\n")); - return - ( jvm != NULL - ? 1 // already initialised - : ( (r1=jni_create_jvm_c(cp)) < 0 - ? r1 // err code from JVM-specific routine - : ( (r2=jni_init()) < 0 - ? r2 // err code from jni_init() - : ( r1 == 0 // success code from JVM-specific routine - ? ( DEBUG(0, Sdprintf("[JPL: Java VM created]\n")), r1) - : ( DEBUG(0, Sdprintf("[JPL: Java VM found]\n")), r1) - ) - ) - ) - ); - } - - -/* -%T jni_create_jvm( +string, -integer) - */ -// is this useful? dangerous? redundant? -// -static foreign_t -jni_create_jvm_plc( // maps jni_create_jvm() into Prolog - term_t a1, - term_t a2 - ) - { - char *classpath; - - return PL_get_atom_chars( a1, &classpath) - && PL_unify_integer(a2,jni_create_jvm(classpath)); - } - - -int -jni_create_default_jvm() - { - char *cp; - - cp = getenv("CLASSPATH"); - return jni_create_jvm(cp) >= 0; // e.g. 2 -> "JVM already available" - } - - -/* -%T jni_ensure_jvm - */ -static foreign_t -jni_ensure_jvm_plc() - { - - return jni_ensure_jvm(); - } - - -// NB after any JNI call which clearly indicates success, -// it is unnecessary to check for an exception -// (potential for slight economy here...) - -/* -%T jni_void( +integer) - */ -static foreign_t -jni_void_0_plc( // C identifiers distinguished _0_ etc, Prolog name is overloaded - term_t tn - ) - { - int n; // JNI function index - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() // ought this either succeed or throw a JPL error? - || !PL_get_integer(tn,&n) // ought this either succeed or throw a Prolog type error? - ) - { - return FALSE; - } - - switch ( n ) - { - case 17: - r = ( (*env)->ExceptionClear(env) , TRUE ); // could just return... - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - return jni_check_exception() && r; - } - - -/* -%T jni_void( +integer, +term) - */ -static foreign_t -jni_void_1_plc( - term_t tn, // +FuncIndex - term_t ta1 // +Arg1 - ) - { - int n; // JNI function index - // functor_t fn; // temp for conversion macros - // term_t a1; // " - // term_t a2; // " - // atom_t a; // " - // char *cp; // " - // int i; // " - // int xhi; // " - // int xlo; // " - // jobject j; // " - // jlong jl; // " - // void *p1; // temp for converted (JVM) arg - char *c1; // " - // int i1; // " - // jlong l1; // " - // double d1; // " - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 18: - r = JNI_term_to_charP(ta1,c1) - && ( (*env)->FatalError(env,(char*)c1) , TRUE ); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - return jni_check_exception() && r; - } - - -/* -%T jni_void( +integer, +term, +term) - */ -static foreign_t -jni_void_2_plc( - term_t tn, // +FuncIndex - term_t ta1, // +Arg1 - term_t ta2 // +Arg2 - ) - { - int n; // JNI function index - functor_t fn; // temp for conversion macros - term_t a1; // " - term_t a2; // " - atom_t a; // " - char *cp; // " - // int i; // " - // int xhi; // " - // int xlo; // " - // jobject j; // " - // jlong jl; // " - void *p1; // temp for converted (JVM) arg - void *p2; // " - // char *c1; // " - char *c2; // " - // int i1; // " - // int i2; // " - // jlong l1; // " - // jlong l2; // " - // double d1; // " - // double d2; // " - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 166: - r = JNI_term_to_jstring(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_char) - && ( (*env)->ReleaseStringChars(env,(jstring)p1,(jchar*)p2) , TRUE ); - break; - case 170: - r = JNI_term_to_jstring(ta1,p1) - && JNI_term_to_jbuf(ta2,c2,JNI_atom_byte) - && ( (*env)->ReleaseStringUTFChars(env,(jstring)p1,(char*)c2) , TRUE ); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - return jni_check_exception() && r; - } - - -/* -%T jni_void( +integer, +term, +term, +term) - */ -static foreign_t -jni_void_3_plc( - term_t tn, // +FuncIndex - term_t ta1, // +Arg1 - term_t ta2, // +Arg2 - term_t ta3 // +Arg3 - ) - { - int n; // JNI function index - functor_t fn; // temp for conversion macros - term_t a1; // " - term_t a2; // " - atom_t a; // " - char *cp; // " - int i; // " - int xhi; // " - int xlo; // " - // jobject j; // " - jlong jl; // " - void *p1; // temp for converted (JVM) arg - void *p2; // " - void *p3; // " - // char *c1; // " - // char *c2; // " - // char *c3; // " - // int i1; // " - int i2; // " - int i3; // " - // jlong l1; // " - // jlong l2; // " - jlong l3; // " - // double d1; // " - // double d2; // " - double d3; // " - jvalue *jvp = NULL; // if this is given a buffer, it will be freed after the call - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 63: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && ( (*env)->CallVoidMethodA(env,(jobject)p1,(jmethodID)p2,jvp) , TRUE ); - break; - case 143: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && ( (*env)->CallStaticVoidMethodA(env,(jclass)p1,(jmethodID)p2,jvp) , TRUE ); - break; - case 104: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_ref(ta3,p3) - && ( (*env)->SetObjectField(env,(jobject)p1,(jfieldID)p2,(jobject)p3) , TRUE ); - break; - case 105: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jboolean(ta3,i3) - && ( (*env)->SetBooleanField(env,(jobject)p1,(jfieldID)p2,(jboolean)i3) , TRUE ); - break; - case 106: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jbyte(ta3,i3) - && ( (*env)->SetByteField(env,(jobject)p1,(jfieldID)p2,(jbyte)i3) , TRUE ); - break; - case 107: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jchar(ta3,i3) - && ( (*env)->SetCharField(env,(jobject)p1,(jfieldID)p2,(jchar)i3) , TRUE ); - break; - case 108: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jshort(ta3,i3) - && ( (*env)->SetShortField(env,(jobject)p1,(jfieldID)p2,(jshort)i3) , TRUE ); - break; - case 109: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->SetIntField(env,(jobject)p1,(jfieldID)p2,(jint)i3) , TRUE ); - break; - case 110: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jlong(ta3,l3) - && ( (*env)->SetLongField(env,(jobject)p1,(jfieldID)p2,(jlong)l3) , TRUE ); - break; - case 111: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jfloat(ta3,d3) - && ( (*env)->SetFloatField(env,(jobject)p1,(jfieldID)p2,(jfloat)d3) , TRUE ); - break; - case 112: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jdouble(ta3,d3) - && ( (*env)->SetDoubleField(env,(jobject)p1,(jfieldID)p2,(jdouble)d3) , TRUE ); - break; - case 154: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_ref(ta3,p3) - && ( (*env)->SetStaticObjectField(env,(jclass)p1,(jfieldID)p2,(jobject)p3) , TRUE ); - break; - case 155: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jboolean(ta3,i3) - && ( (*env)->SetStaticBooleanField(env,(jclass)p1,(jfieldID)p2,(jboolean)i3) , TRUE ); - break; - case 156: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jbyte(ta3,i3) - && ( (*env)->SetStaticByteField(env,(jclass)p1,(jfieldID)p2,(jbyte)i3) , TRUE ); - break; - case 157: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jchar(ta3,i3) - && ( (*env)->SetStaticCharField(env,(jclass)p1,(jfieldID)p2,(jchar)i3) , TRUE ); - break; - case 158: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jshort(ta3,i3) - && ( (*env)->SetStaticShortField(env,(jclass)p1,(jfieldID)p2,(jshort)i3) , TRUE ); - break; - case 159: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->SetStaticIntField(env,(jclass)p1,(jfieldID)p2,(jint)i3) , TRUE ); - break; - case 160: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jlong(ta3,l3) - && ( (*env)->SetStaticLongField(env,(jclass)p1,(jfieldID)p2,(jlong)l3) , TRUE ); - break; - case 161: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jfloat(ta3,d3) - && ( (*env)->SetStaticFloatField(env,(jclass)p1,(jfieldID)p2,(jfloat)d3) , TRUE ); - break; - case 162: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_term_to_jdouble(ta3,d3) - && ( (*env)->SetStaticDoubleField(env,(jclass)p1,(jfieldID)p2,(jdouble)d3) , TRUE ); - break; - case 174: - r = JNI_term_to_object_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_ref(ta3,p3) - && ( (*env)->SetObjectArrayElement(env,(jobjectArray)p1,(jsize)i2,(jobject)p3) , TRUE ); - break; - case 191: - r = JNI_term_to_boolean_jarray(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_boolean) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->ReleaseBooleanArrayElements(env,(jbooleanArray)p1,(jboolean*)p2,(jint)i3) , TRUE ); - break; - case 192: - r = JNI_term_to_byte_jarray(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_byte) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->ReleaseByteArrayElements(env,(jbyteArray)p1,(jbyte*)p2,(jint)i3) , TRUE ); - break; - case 193: - r = JNI_term_to_char_jarray(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_char) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->ReleaseCharArrayElements(env,(jcharArray)p1,(jchar*)p2,(jint)i3) , TRUE ); - break; - case 194: - r = JNI_term_to_short_jarray(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_short) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->ReleaseShortArrayElements(env,(jshortArray)p1,(jshort*)p2,(jint)i3) , TRUE ); - break; - case 195: - r = JNI_term_to_int_jarray(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_int) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->ReleaseIntArrayElements(env,(jintArray)p1,(jint*)p2,(jint)i3) , TRUE ); - break; - case 196: - r = JNI_term_to_long_jarray(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_long) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->ReleaseLongArrayElements(env,(jlongArray)p1,(jlong*)p2,(jint)i3) , TRUE ); - break; - case 197: - r = JNI_term_to_float_jarray(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_float) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->ReleaseFloatArrayElements(env,(jfloatArray)p1,(jfloat*)p2,(jint)i3) , TRUE ); - break; - case 198: - r = JNI_term_to_double_jarray(ta1,p1) - && JNI_term_to_jbuf(ta2,p2,JNI_atom_double) - && JNI_term_to_jint(ta3,i3) - && ( (*env)->ReleaseDoubleArrayElements(env,(jdoubleArray)p1,(jdouble*)p2,(jint)i3) , TRUE ); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - if ( jvp != NULL ) - { - free( jvp); - } - - return jni_check_exception() && r; - } - - -/* -%T jni_void( +integer, +term, +term, +term, +term) - */ -static foreign_t -jni_void_4_plc( - term_t tn, // +FuncIndex - term_t ta1, // +Arg1 - term_t ta2, // +Arg2 - term_t ta3, // +Arg3 - term_t ta4 // +Arg4 - ) - { - int n; // JNI function index - functor_t fn; // temp for conversion macros - term_t a1; // " - term_t a2; // " - atom_t a; // " - char *cp; // " - // int i; // " - // int xhi; // " - // int xlo; // " - // jobject j; // " - // jlong jl; // " - void *p1; // temp for converted (JVM) arg - void *p2; // " - void *p3; // " - void *p4; // " - // char *c1; // " - // char *c2; // " - // char *c3; // " - // char *c4; // " - // int i1; // " - int i2; // " - int i3; // " - // int i4; // " - // jlong l1; // " - // jlong l2; // " - // jlong l3; // " - // jlong l4; // " - // double d1; // " - // double d2; // " - // double d3; // " - // double d4; // " - jvalue *jvp = NULL; // if this is given a buffer, it will be freed after the call - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 93: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jclass(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && ( (*env)->CallNonvirtualVoidMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp) , TRUE ); - break; - case 199: - r = JNI_term_to_boolean_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_boolean) - && ( (*env)->GetBooleanArrayRegion(env,(jbooleanArray)p1,(jsize)i2,(jsize)i3,(jboolean*)p4) , TRUE ); - break; - case 200: - r = JNI_term_to_byte_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_byte) - && ( (*env)->GetByteArrayRegion(env,(jbyteArray)p1,(jsize)i2,(jsize)i3,(jbyte*)p4) , TRUE ); - break; - case 201: - r = JNI_term_to_char_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_char) - && ( (*env)->GetCharArrayRegion(env,(jcharArray)p1,(jsize)i2,(jsize)i3,(jchar*)p4) , TRUE ); - break; - case 202: - r = JNI_term_to_short_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_short) - && ( (*env)->GetShortArrayRegion(env,(jshortArray)p1,(jsize)i2,(jsize)i3,(jshort*)p4) , TRUE ); - break; - case 203: - r = JNI_term_to_int_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_int) - && ( (*env)->GetIntArrayRegion(env,(jintArray)p1,(jsize)i2,(jsize)i3,(jint*)p4) , TRUE ); - break; - case 204: - r = JNI_term_to_long_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_long) - && ( (*env)->GetLongArrayRegion(env,(jlongArray)p1,(jsize)i2,(jsize)i3,(jlong*)p4) , TRUE ); - break; - case 205: - r = JNI_term_to_float_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_float) - && ( (*env)->GetFloatArrayRegion(env,(jfloatArray)p1,(jsize)i2,(jsize)i3,(jfloat*)p4) , TRUE ); - break; - case 206: - r = JNI_term_to_double_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_double) - && ( (*env)->GetDoubleArrayRegion(env,(jdoubleArray)p1,(jsize)i2,(jsize)i3,(jdouble*)p4) , TRUE ); - break; - case 207: - r = JNI_term_to_boolean_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_boolean) - && ( (*env)->SetBooleanArrayRegion(env,(jbooleanArray)p1,(jsize)i2,(jsize)i3,(jboolean*)p4) , TRUE ); - break; - case 208: - r = JNI_term_to_byte_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_byte) - && ( (*env)->SetByteArrayRegion(env,(jbyteArray)p1,(jsize)i2,(jsize)i3,(jbyte*)p4) , TRUE ); - break; - case 209: - r = JNI_term_to_char_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_char) - && ( (*env)->SetCharArrayRegion(env,(jcharArray)p1,(jsize)i2,(jsize)i3,(jchar*)p4) , TRUE ); - break; - case 210: - r = JNI_term_to_short_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_short) - && ( (*env)->SetShortArrayRegion(env,(jshortArray)p1,(jsize)i2,(jsize)i3,(jshort*)p4) , TRUE ); - break; - case 211: - r = JNI_term_to_int_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_int) - && ( (*env)->SetIntArrayRegion(env,(jintArray)p1,(jsize)i2,(jsize)i3,(jint*)p4) , TRUE ); - break; - case 212: - r = JNI_term_to_long_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_long) - && ( (*env)->SetLongArrayRegion(env,(jlongArray)p1,(jsize)i2,(jsize)i3,(jlong*)p4) , TRUE ); - break; - case 213: - r = JNI_term_to_float_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_float) - && ( (*env)->SetFloatArrayRegion(env,(jfloatArray)p1,(jsize)i2,(jsize)i3,(jfloat*)p4) , TRUE ); - break; - case 214: - r = JNI_term_to_double_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_term_to_jint(ta3,i3) - && JNI_term_to_jbuf(ta4,p4,JNI_atom_double) - && ( (*env)->SetDoubleArrayRegion(env,(jdoubleArray)p1,(jsize)i2,(jsize)i3,(jdouble*)p4) , TRUE ); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - if ( jvp != NULL ) - { - free( jvp); - } - - return jni_check_exception() && r; - } - - -/* -%T jni_func( +integer, -term) - */ -static foreign_t -jni_func_0_plc( - term_t tn, // +FuncIndex - term_t tr // -Result - ) - { - int n; // JNI function index - // functor_t fn; // temp for conversion macros - // term_t a1; // " - // term_t a2; // " - atom_t a; // " - // char *cp; // " - int i; // " - // int xhi; // " - // int xlo; // " - jobject j; // " - // jlong jl; // " - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 4: - r = JNI_jint_to_term((*env)->GetVersion(env),tr); - break; - case 15: - r = JNI_jobject_to_term((*env)->ExceptionOccurred(env),tr); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - return jni_check_exception() && r; // surely NEITHER of these throws an exception! - } - - -/* -%T jni_func( +integer, +term, -term) - */ -static foreign_t -jni_func_1_plc( - term_t tn, // +FuncIndex - term_t ta1, // +Arg1 - term_t tr // -Result - ) - { - int n; // JNI function index - functor_t fn; // temp for conversion macros - term_t a1; // " - // term_t a2; // " - atom_t a; // " - char *cp; // " - int i; // " - // int xhi; // " - // int xlo; // " - jobject j; // " - // jlong jl; // " - void *p1; // temp for converted (JVM) arg - char *c1; // " - int i1; // " - // jlong l1; // " - // double d1; // " - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 6: - r = JNI_term_to_charP(ta1,c1) - && JNI_jobject_to_term((*env)->FindClass(env,(char*)c1),tr); - break; - case 10: - r = JNI_term_to_jclass(ta1,p1) - && JNI_jobject_to_term((*env)->GetSuperclass(env,(jclass)p1),tr); - break; - case 13: - r = JNI_term_to_throwable_jobject(ta1,p1) - && JNI_jint_to_term((*env)->Throw(env,(jthrowable)p1),tr); - break; - case 27: - r = JNI_term_to_non_array_jclass(ta1,p1) - && JNI_jobject_to_term((*env)->AllocObject(env,(jclass)p1),tr); - break; - case 31: - r = JNI_term_to_jobject(ta1,p1) - && JNI_jobject_to_term((*env)->GetObjectClass(env,(jobject)p1),tr); - break; - case 164: - r = JNI_term_to_jstring(ta1,p1) - && JNI_jint_to_term((*env)->GetStringLength(env,(jstring)p1),tr); - break; - case 167: - r = JNI_term_to_charP(ta1,c1) - && JNI_jobject_to_term((*env)->NewStringUTF(env,(char*)c1),tr); - break; - case 168: - r = JNI_term_to_jstring(ta1,p1) - && JNI_jint_to_term((*env)->GetStringUTFLength(env,(jstring)p1),tr); - break; - case 171: - r = JNI_term_to_jarray(ta1,p1) - && JNI_jint_to_term((*env)->GetArrayLength(env,(jarray)p1),tr); - break; - case 175: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_jobject_to_term((*env)->NewBooleanArray(env,(jsize)i1),tr); - break; - case 176: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_jobject_to_term((*env)->NewByteArray(env,(jsize)i1),tr); - break; - case 177: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_jobject_to_term((*env)->NewCharArray(env,(jsize)i1),tr); - break; - case 178: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_jobject_to_term((*env)->NewShortArray(env,(jsize)i1),tr); - break; - case 179: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_jobject_to_term((*env)->NewIntArray(env,(jsize)i1),tr); - break; - case 180: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_jobject_to_term((*env)->NewLongArray(env,(jsize)i1),tr); - break; - case 181: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_jobject_to_term((*env)->NewFloatArray(env,(jsize)i1),tr); - break; - case 182: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_jobject_to_term((*env)->NewDoubleArray(env,(jsize)i1),tr); - break; - case 217: - r = JNI_term_to_jobject(ta1,p1) - && JNI_jint_to_term((*env)->MonitorEnter(env,(jobject)p1),tr); - break; - case 218: - r = JNI_term_to_jobject(ta1,p1) - && JNI_jint_to_term((*env)->MonitorExit(env,(jobject)p1),tr); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - return jni_check_exception() && r; - } - - -/* -%T jni_func( +integer, +term, +term, -term) - */ -static foreign_t -jni_func_2_plc( - term_t tn, // +FuncIndex - term_t ta1, // +Arg1 - term_t ta2, // +Arg2 - term_t tr // -Result - ) - { - int n; // JNI function index - functor_t fn; // temp for conversion macros - term_t a1; // " - // term_t a2; // " - atom_t a; // " - char *cp; // " - int i; // " - int xhi; // " - int xlo; // " - jobject j; // " - jlong jl; // " - void *p1; // temp for converted (JVM) arg - void *p2; // " - char *c1; // " - char *c2; // " - // int i1; // " - int i2; // " - // jlong l1; // " - // jlong l2; // " - // double d1; // " - // double d2; // " - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 11: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jclass(ta2,p2) - && JNI_jboolean_to_term((*env)->IsAssignableFrom(env,(jclass)p1,(jclass)p2),tr); - break; - case 14: - r = JNI_term_to_throwable_jclass(ta1,p1) - && JNI_term_to_charP(ta2,c2) - && JNI_jint_to_term((*env)->ThrowNew(env,(jclass)p1,(char*)c2),tr); - break; - case 24: - r = JNI_term_to_ref(ta1,p1) - && JNI_term_to_ref(ta2,p2) - && JNI_jboolean_to_term((*env)->IsSameObject(env,(jobject)p1,(jobject)p2),tr); - break; - case 32: - r = JNI_term_to_ref(ta1,p1) - && JNI_term_to_jclass(ta2,p2) - && JNI_jboolean_to_term((*env)->IsInstanceOf(env,(jobject)p1,(jclass)p2),tr); - break; - case 95: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jobject_to_term((*env)->GetObjectField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 96: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jboolean_to_term((*env)->GetBooleanField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 97: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jbyte_to_term((*env)->GetByteField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 98: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jchar_to_term((*env)->GetCharField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 99: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jshort_to_term((*env)->GetShortField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 100: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jint_to_term((*env)->GetIntField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 101: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jlong_to_term((*env)->GetLongField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 102: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jfloat_to_term((*env)->GetFloatField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 103: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jdouble_to_term((*env)->GetDoubleField(env,(jobject)p1,(jfieldID)p2),tr); - break; - case 145: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jobject_to_term((*env)->GetStaticObjectField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 146: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jboolean_to_term((*env)->GetStaticBooleanField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 147: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jbyte_to_term((*env)->GetStaticByteField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 148: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jchar_to_term((*env)->GetStaticCharField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 149: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jshort_to_term((*env)->GetStaticShortField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 150: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jint_to_term((*env)->GetStaticIntField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 151: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jlong_to_term((*env)->GetStaticLongField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 152: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jfloat_to_term((*env)->GetStaticFloatField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 153: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jfieldID(ta2,p2) - && JNI_jdouble_to_term((*env)->GetStaticDoubleField(env,(jclass)p1,(jfieldID)p2),tr); - break; - case 163: - r = JNI_term_to_charP(ta1,c1) // oughta be _jcharP, i.e. Unicode - && JNI_term_to_non_neg_jint(ta2,i2) - && JNI_jobject_to_term((*env)->NewString(env,(jchar*)c1,(jsize)i2),tr); - break; - case 165: - r = JNI_term_to_jstring(ta1,p1) - && JNI_jbuf_to_term((*env)->GetStringChars(env,(jstring)p1,(jboolean*)&i2),tr,JNI_atom_boolean) - && JNI_jboolean_to_term(i2,ta2); - break; - case 169: - r = JNI_term_to_jstring(ta1,p1) - && JNI_jbuf_to_term((*env)->GetStringUTFChars(env,(jstring)p1,(jboolean*)&i2),tr,JNI_atom_byte) - && JNI_jboolean_to_term(i2,ta2); - break; - case 173: - r = JNI_term_to_object_jarray(ta1,p1) - && JNI_term_to_jint(ta2,i2) - && JNI_jobject_to_term((*env)->GetObjectArrayElement(env,(jobjectArray)p1,(jsize)i2),tr); - break; - case 183: - r = JNI_term_to_boolean_jarray(ta1,p1) - && JNI_jbuf_to_term((*env)->GetBooleanArrayElements(env,(jbooleanArray)p1,(jboolean*)&i2),tr,JNI_atom_boolean) - && JNI_jboolean_to_term(i2,ta2); - break; - case 184: - r = JNI_term_to_byte_jarray(ta1,p1) - && JNI_jbuf_to_term((*env)->GetByteArrayElements(env,(jbyteArray)p1,(jboolean*)&i2),tr,JNI_atom_byte) - && JNI_jboolean_to_term(i2,ta2); - break; - case 185: - r = JNI_term_to_char_jarray(ta1,p1) - && JNI_jbuf_to_term((*env)->GetCharArrayElements(env,(jcharArray)p1,(jboolean*)&i2),tr,JNI_atom_char) - && JNI_jboolean_to_term(i2,ta2); - break; - case 186: - r = JNI_term_to_short_jarray(ta1,p1) - && JNI_jbuf_to_term((*env)->GetShortArrayElements(env,(jshortArray)p1,(jboolean*)&i2),tr,JNI_atom_short) - && JNI_jboolean_to_term(i2,ta2); - break; - case 187: - r = JNI_term_to_int_jarray(ta1,p1) - && JNI_jbuf_to_term((*env)->GetIntArrayElements(env,(jintArray)p1,(jboolean*)&i2),tr,JNI_atom_int) - && JNI_jboolean_to_term(i2,ta2); - break; - case 188: - r = JNI_term_to_long_jarray(ta1,p1) - && JNI_jbuf_to_term((*env)->GetLongArrayElements(env,(jlongArray)p1,(jboolean*)&i2),tr,JNI_atom_long) - && JNI_jboolean_to_term(i2,ta2); - break; - case 189: - r = JNI_term_to_float_jarray(ta1,p1) - && JNI_jbuf_to_term((*env)->GetFloatArrayElements(env,(jfloatArray)p1,(jboolean*)&i2),tr,JNI_atom_float) - && JNI_jboolean_to_term(i2,ta2); - break; - case 190: - r = JNI_term_to_double_jarray(ta1,p1) - && JNI_jbuf_to_term((*env)->GetDoubleArrayElements(env,(jdoubleArray)p1,(jboolean*)&i2),tr,JNI_atom_double) - && JNI_jboolean_to_term(i2,ta2); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - return jni_check_exception() && r; - } - - -/* -%T jni_func( +integer, +term, +term, +term, -term) - */ -static foreign_t -jni_func_3_plc( - term_t tn, // +FuncIndex - term_t ta1, // +Arg1 - term_t ta2, // +Arg2 - term_t ta3, // +Arg3 - term_t tr // -Result - ) - { - int n; // JNI function index - functor_t fn; // temp for conversion macros - term_t a1; // " - // term_t a2; // " - atom_t a; // " - char *cp; // " - int i; // " - int xhi; // " - int xlo; // " - jobject j; // " - jlong jl; // " - void *p1; // temp for converted (JVM) arg - void *p2; // " - void *p3; // " - // char *c1; // " - char *c2; // " - char *c3; // " - int i1; // " - // int i2; // " - // int i3; // " - // jlong l1; // " - // jlong l2; // " - // jlong l3; // " - // double d1; // " - // double d2; // " - // double d3; // " - jvalue *jvp = NULL; // if this is given a buffer, it will be freed after the call - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 30: - r = JNI_term_to_non_array_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jobject_to_term((*env)->NewObjectA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 36: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jobject_to_term((*env)->CallObjectMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 39: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jboolean_to_term((*env)->CallBooleanMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 42: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jbyte_to_term((*env)->CallByteMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 45: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jchar_to_term((*env)->CallCharMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 48: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jshort_to_term((*env)->CallShortMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 51: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jint_to_term((*env)->CallIntMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 54: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jlong_to_term((*env)->CallLongMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 57: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jfloat_to_term((*env)->CallFloatMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 60: - r = JNI_term_to_jobject(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jdouble_to_term((*env)->CallDoubleMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); - break; - case 116: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jobject_to_term((*env)->CallStaticObjectMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 119: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jboolean_to_term((*env)->CallStaticBooleanMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 122: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jbyte_to_term((*env)->CallStaticByteMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 125: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jchar_to_term((*env)->CallStaticCharMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 128: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jshort_to_term((*env)->CallStaticShortMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 131: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jint_to_term((*env)->CallStaticIntMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 134: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jlong_to_term((*env)->CallStaticLongMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 137: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jfloat_to_term((*env)->CallStaticFloatMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 140: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jmethodID(ta2,p2) - && JNI_term_to_pointer(ta3,jvp) - && JNI_jdouble_to_term((*env)->CallStaticDoubleMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); - break; - case 33: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_charP(ta2,c2) - && JNI_term_to_charP(ta3,c3) - && JNI_jmethodID_to_term((*env)->GetMethodID(env,(jclass)p1,(char*)c2,(char*)c3),tr); - break; - case 94: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_charP(ta2,c2) - && JNI_term_to_charP(ta3,c3) - && JNI_jfieldID_to_term((*env)->GetFieldID(env,(jclass)p1,(char*)c2,(char*)c3),tr); - break; - case 113: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_charP(ta2,c2) - && JNI_term_to_charP(ta3,c3) - && JNI_jmethodID_to_term((*env)->GetStaticMethodID(env,(jclass)p1,(char*)c2,(char*)c3),tr); - break; - case 144: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_charP(ta2,c2) - && JNI_term_to_charP(ta3,c3) - && JNI_jfieldID_to_term((*env)->GetStaticFieldID(env,(jclass)p1,(char*)c2,(char*)c3),tr); - break; - case 172: - r = JNI_term_to_non_neg_jint(ta1,i1) - && JNI_term_to_jclass(ta2,p2) - && JNI_term_to_ref(ta3,p3) - && JNI_jobject_to_term((*env)->NewObjectArray(env,(jsize)i1,(jclass)p2,(jobject)p3),tr); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - if ( jvp != NULL ) - { - free( jvp); - } - - return jni_check_exception() && r; - } - - -/* -%T jni_func( +integer, +term, +term, +term, +term, -term) - */ -static foreign_t -jni_func_4_plc( - term_t tn, // +FuncIndex - term_t ta1, // +Arg1 - term_t ta2, // +Arg2 - term_t ta3, // +Arg3 - term_t ta4, // +Arg4 - term_t tr // -Result - ) - { - int n; // JNI function index - functor_t fn; // temp for conversion macros - term_t a1; // " - term_t a2; // " - atom_t a; // " - char *cp; // " - int i; // " - int xhi; // " - int xlo; // " - jobject j; // " - jlong jl; // " - void *p1; // temp for converted (JVM) arg - void *p2; // " - void *p3; // " - // void *p4; // " - char *c1; // " - // char *c2; // " - // char *c3; // " - // char *c4; // " - // int i1; // " - // int i2; // " - // int i3; // " - int i4; // " - // jlong l1; // " - // jlong l2; // " - // jlong l3; // " - // jlong l4; // " - // double d1; // " - // double d2; // " - // double d3; // " - // double d4; // " - jvalue *jvp = NULL; // if this is given a buffer, it will be freed after the call - jboolean r; // Prolog exit/fail outcome - - if ( !jni_ensure_jvm() - || !PL_get_integer(tn,&n) - ) - { - return FALSE; - } - - switch ( n ) - { - case 66: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jobject_to_term((*env)->CallNonvirtualObjectMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 69: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jboolean_to_term((*env)->CallNonvirtualBooleanMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 72: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jbyte_to_term((*env)->CallNonvirtualByteMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 75: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jchar_to_term((*env)->CallNonvirtualCharMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 78: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jshort_to_term((*env)->CallNonvirtualShortMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 81: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jint_to_term((*env)->CallNonvirtualIntMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 84: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jlong_to_term((*env)->CallNonvirtualLongMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 87: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jfloat_to_term((*env)->CallNonvirtualFloatMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 90: - r = JNI_term_to_jclass(ta1,p1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jmethodID(ta3,p3) - && JNI_term_to_pointer(ta4,jvp) - && JNI_jdouble_to_term((*env)->CallNonvirtualDoubleMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); - break; - case 5: - r = JNI_term_to_charP(ta1,c1) - && JNI_term_to_jobject(ta2,p2) - && JNI_term_to_jbuf(ta3,p3,JNI_atom_byte) - && JNI_term_to_jint(ta4,i4) - && JNI_jobject_to_term((*env)->DefineClass(env,(char*)c1,(jobject)p2,(jbyte*)p3,(jsize)i4),tr); - break; - default: - return FALSE; // oughta throw exception (design-time error :-) - break; - } - - if ( jvp != NULL ) - { - free( jvp); - } - - return jni_check_exception() && r; - } - - -// would it be better style to have this at the end of the file? -static -PL_extension predspecs[] = - { { "jni_create_jvm", 2, jni_create_jvm_plc, 0 }, - { "jni_supported_jvm_version", 2, jni_supported_jvm_version_plc, 0 }, - { "jni_get_created_jvm_count", 1, jni_get_created_jvm_count_plc, 0 }, - { "jni_ensure_jvm", 0, jni_ensure_jvm_plc, 0 }, - { "jni_tag_to_iref", 2, jni_tag_to_iref_plc, 0 }, - { "jni_hr_info", 4, jni_hr_info_plc, 0 }, - { "jni_hr_table", 1, jni_hr_table_plc, 0 }, - { "jni_byte_buf_length_to_codes", 3, jni_byte_buf_length_to_codes_plc, 0 }, - { "jni_param_put", 4, jni_param_put_plc, 0 }, - { "jni_alloc_buffer", 3, jni_alloc_buffer_plc, 0 }, - { "jni_free_buffer", 1, jni_free_buffer_plc, 0 }, - { "jni_fetch_buffer_value", 5, jni_fetch_buffer_value_plc, 0 }, - { "jni_stash_buffer_value", 5, jni_stash_buffer_value_plc, 0 }, - { "jni_void", 1, jni_void_0_plc, 0 }, - { "jni_void", 2, jni_void_1_plc, 0 }, - { "jni_void", 3, jni_void_2_plc, 0 }, - { "jni_void", 4, jni_void_3_plc, 0 }, - { "jni_void", 5, jni_void_4_plc, 0 }, - { "jni_func", 2, jni_func_0_plc, 0 }, - { "jni_func", 3, jni_func_1_plc, 0 }, - { "jni_func", 4, jni_func_2_plc, 0 }, - { "jni_func", 5, jni_func_3_plc, 0 }, - { "jni_func", 6, jni_func_4_plc, 0 }, - { "jpl_c_lib_version", 1, jpl_c_lib_version_1_plc, 0 }, - { "jpl_c_lib_version", 4, jpl_c_lib_version_4_plc, 0 }, - { NULL, 0, NULL, 0 } - }; - - -install_t -install() - { - PL_register_extensions( predspecs); - } - - -//=== JPL functions ================================================================================ - -static int create_pool_engines(); - -static int -jpl_num_initial_default_args() // used only once, by jpl_do_jpl_init() - { - int i; - - for ( i=0 ; default_args[i]!=NULL ; i++ ) - { - } - return i; - } - - -// outcomes: -// fail to find jpl.*, jpl.fli.* classes or to convert init args to String[]: exception, FALSE -// all OK: TRUE -// -static bool -jpl_do_jpl_init( // to be called once only, after PL init, before any JPL calls - JNIEnv *env - ) - { - jclass tc; // temporary class ref - jobject ta; // temporary array ref - char *msg; // error message for exceptions thrown here - int i; // loop counter - jobject to; // temporary (String) object ref - - if ( jpl_status != JPL_INIT_RAW ) // jpl init already attempted? (shouldn't happen) - { - DEBUG(1, Sdprintf( "[JPL: jpl_do_jpl_init() called AGAIN (skipping...)]\n")); - return TRUE; - } - - // prerequisites for setting initial default args into String[] dia: - if ( (tc=(*env)->FindClass(env,"java/lang/String")) == NULL - || (jString_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (ta=(*env)->NewObjectArray(env,jpl_num_initial_default_args(),jString_c,NULL)) == NULL - || (dia=(*env)->NewGlobalRef(env,ta)) == NULL - || ( (*env)->DeleteLocalRef(env,ta), FALSE) - ) - { - msg = "jpl_do_jpl_init(): failed to find java.lang.String or create String[] dia"; - goto err; - } - - // copy the initial default args into String[] dia: - for ( i=0 ; default_args[i]!=NULL ; i++ ) - { - if ( (to=(*env)->NewStringUTF(env,default_args[i])) == NULL ) - { - msg = "jpl_do_jpl_init(): failed to convert an initial default arg to a String"; - goto err; - } - (*env)->SetObjectArrayElement(env,dia,i,to); // any errors/exceptions to be handled here? - } - - if ( (tc=(*env)->FindClass(env,"jpl/JPLException")) == NULL - || (jJPLException_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/term_t")) == NULL - || (jTermT_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/atom_t")) == NULL - || (jAtomT_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/functor_t")) == NULL - || (jFunctorT_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/fid_t")) == NULL - || (jFidT_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/predicate_t")) == NULL - || (jPredicateT_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/qid_t")) == NULL - || (jQidT_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/module_t")) == NULL - || (jModuleT_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/engine_t")) == NULL - || (jEngineT_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/LongHolder")) == NULL - || (jLongHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/PointerHolder")) == NULL - || (jPointerHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/IntHolder")) == NULL - || (jIntHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/DoubleHolder")) == NULL - || (jDoubleHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/StringHolder")) == NULL - || (jStringHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/ObjectHolder")) == NULL - || (jObjectHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/fli/BooleanHolder")) == NULL - || (jBooleanHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/JRef")) == NULL - || (jJRef_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (tc=(*env)->FindClass(env,"jpl/JBoolean")) == NULL - || (jJBoolean_c=(*env)->NewGlobalRef(env,tc)) == NULL - || ( (*env)->DeleteLocalRef(env,tc), FALSE) - - || (jLongHolderValue_f=(*env)->GetFieldID(env,jLongHolder_c,"value","J")) == NULL - - || (jPointerHolderValue_f=(*env)->GetFieldID(env,jPointerHolder_c,"value","J")) == NULL - - || (jIntHolderValue_f=(*env)->GetFieldID(env,jIntHolder_c,"value","I")) == NULL - - || (jDoubleHolderValue_f=(*env)->GetFieldID(env,jDoubleHolder_c,"value","D")) == NULL - - || (jStringHolderValue_f=(*env)->GetFieldID(env,jStringHolder_c,"value","Ljava/lang/String;")) == NULL - - || (jObjectHolderValue_f=(*env)->GetFieldID(env,jObjectHolder_c,"value","Ljava/lang/Object;")) == NULL - - || (jBooleanHolderValue_f=(*env)->GetFieldID(env,jBooleanHolder_c,"value","Z")) == NULL - - || (jJRefRef_f=(*env)->GetFieldID(env,jJRef_c,"ref","Ljava/lang/Object;")) == NULL - - || (jJBooleanValue_f=(*env)->GetFieldID(env,jJBoolean_c,"value","Z")) == NULL - ) - { - msg = "jpl_do_jpl_init(): failed to find jpl.* or jpl.fli.* classes"; - goto err; - } - - DEBUG(1, Sdprintf( "[jpl_do_jpl_init() sets jpl_status = JPL_INIT_PVM_MAYBE, returns TRUE]\n")); - jpl_status = JPL_INIT_PVM_MAYBE; - return TRUE; - -err: - jpl_status = JPL_INIT_JPL_FAILED; - (*env)->ThrowNew(env,jJPLException_c,msg); - return FALSE; - } - - -// prerequisite: -// called only from jpl_test_pvm_init() and jpl_do_pvm_init() -// outcomes: -// error setting up post-PVM-init JPL state: throws exception, sets status = PVM_FAILED, returns FALSE -// OK: sets status = OK, returns TRUE -// -static bool -jpl_post_pvm_init( - JNIEnv *env, - int argc, - char **argv - ) - { - char *msg; - jobject ta; - int i; - - // Prolog VM is already initialised (by us or by other party) - // retire default init args and set up actual init args: - dia = NULL; // probably oughta delete (global) ref to former args... - if ( (ta=(*env)->NewObjectArray(env,argc,jString_c,NULL)) == NULL - || (aia=(*env)->NewGlobalRef(env,ta)) == NULL - || ( (*env)->DeleteLocalRef(env,ta), FALSE) - ) - { - msg = "jpl_post_pvm_init(): failed to copy actual init args"; - goto err; - } - for ( i=0 ; iNewStringUTF(env,argv[i]); - if ( to == NULL ) - { - msg = "jpl_post_pvm_init(): failed to convert actual PL init arg to String"; - goto err; - } - (*env)->SetObjectArrayElement(env,aia,i,to); - } - - if ( create_pool_engines() != 0 ) - { - msg = "jpl_post_pvm_init(): failed to create Prolog engine pool"; - goto err; - } - - jpl_status = JPL_INIT_OK; - return TRUE; - -err: - (*env)->ThrowNew( env, jJPLException_c, msg); - jpl_status = JPL_INIT_PVM_FAILED; - return FALSE; - } - - -// prerequisite: jpl_status != JPL_INIT_RAW -// outcomes: -// PVM is not (already) initialised -> FALSE -// PVM is (already) initialised -> TRUE -// error setting up post-PVM-init JPL state -> exception -// -static bool -jpl_test_pvm_init( - JNIEnv *env - ) - { - char *msg; - int argc; - char **argv; - // jobject ta; - // int i; - - if ( jpl_status == JPL_INIT_RAW ) - { - msg = "jpl_test_pvm_init(): called while jpl_status == JPL_INIT_RAW"; - goto err; - } - - if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) - { - msg = "jpl_test_pvm_init(): initialisation has already failed"; - goto err; - } - - if ( jpl_status == JPL_INIT_OK ) - { - return TRUE; - } - - if ( jpl_status == JPL_INIT_PVM_MAYBE ) - { - // we test this each time (if not already initialised) in case other foreign code inits the PVM: - if ( !PL_is_initialised(&argc,&argv) ) // PVM not ready? - { - // jpl_status remains = JPL_INIT_PVM_MAYBE - DEBUG(1, Sdprintf( "[pl_test_pvm_init(): PL is not yet initialised: returning FALSE]\n")); - return FALSE; // already-active Prolog VM not found (NB not an exceptional condition) - } - else - { - DEBUG(1, Sdprintf( "[pl_test_pvm_init(): PL is already initialised: proceeding to jpl_post_pvm_init()]\n")); - return jpl_post_pvm_init(env,argc,argv); // TRUE, FALSE or exception - } - } - - msg = "jpl_test_pvm_init(): unknown jpl_status value"; - goto err; - -err: - (*env)->ThrowNew( env, jJPLException_c, msg); - jpl_status = JPL_INIT_PVM_FAILED; - return FALSE; - } - - -// prerequisite: -// jpl_status == JPL_INIT_PVM_MAYBE -// outcomes: -// successful PVM initialisation and subsequent JPL state setup -> TRUE -// any error -> exception -// -static bool -jpl_do_pvm_init( - JNIEnv *env - ) - { - char *msg; - int argc; - char **argv; - int i; - jstring arg; - char *cp; - - // redundant prerequisites check: - if ( jpl_status != JPL_INIT_PVM_MAYBE ) - { - msg = "jpl_do_pvm_init(): called while jpl_status != JPL_INIT_PVM_MAYBE"; - goto err; - } - - // copy current default init args into suitable form for PL_initialise(): - if ( dia == NULL ) - { - msg = "jpl_do_pvm_init(): dia == NULL"; - goto err; - } - argc = (*env)->GetArrayLength(env,dia); - if ( argc <= 0 ) - { - msg = "jpl_do_pvm_init(): there are fewer than 1 default init args"; - goto err; - } - if ( (argv=(char**)malloc((argc+1)*sizeof(char*))) == NULL ) - { - msg = "jpl_do_pvm_init(): malloc() failed for argv"; - goto err; - } - for ( i=0 ; iGetObjectArrayElement(env,dia,i); - cp = (char*)(*env)->GetStringUTFChars(env,arg,0); - argv[i] = (char*)malloc(strlen(cp)+1); - strcpy( argv[i], cp); - DEBUG(1, Sdprintf( " argv[%d] = %s\n", i, argv[i])); - (*env)->ReleaseStringUTFChars( env, arg, cp); - } - DEBUG(1, Sdprintf( " argv[%d] = NULL\n", argc)); - argv[argc] = NULL; - if ( !PL_initialise(argc,(char**)argv) ) // NB not (const char**) - { - msg = "jpl_do_pvm_init(): PL_initialise() failed"; - goto err; - } - // *don't* free argv (must exist for lifetime of Prolog VM) - - return jpl_post_pvm_init(env,argc,argv); // TRUE, FALSE or exception - -err: - jpl_status = JPL_INIT_PVM_FAILED; - (*env)->ThrowNew( env, jJPLException_c, msg); - return FALSE; - } - - -//=== initialisation-related native Java methods of jpl.fli.Prolog ================================= - -/* - * Class: jpl_fli_PL - * Method: get_default_init_args - * Signature: ()[Ljava/lang/String; - */ -// -// if not yet init then return default init args as String[] -// if already init then return NULL -// if already failed to init then throw an exception -// -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_get_1default_1init_1args( - JNIEnv *env, - jclass jProlog - ) - { - char *msg; - - jpl_ensure_jpl_init( env); // lazily do "local" initialisations iff necessary - - if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) - { - msg = "jpl.fli.Prolog.set_default_init_args(): initialisation has already failed"; - goto err; - } - - return ( jpl_test_pvm_init(env) // if Prolog VM is initialised - ? NULL // then default init args are no longer defined - : dia // else here they are - ) - ; -err: - (*env)->ThrowNew( env, jJPLException_c, msg); - return FALSE; - } - - -/* - * Class: jpl_fli_PL - * Method: set_default_init_args - * Signature: ([Ljava/lang/String;)Z - */ -// -// if the given jargs are null then throw an exception -// if already failed to init then throw an exception -// if not yet init then set default init args from jargs and return TRUE -// if already init then return FALSE -// -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_set_1default_1init_1args( - JNIEnv *env, - jclass jProlog, - jobject jargs // oughta be proper array, perhaps zero-length - ) - { - char *msg; - - jpl_ensure_jpl_init( env); // lazily do "local" initialisations iff necessary - - if ( jargs == NULL ) // improper call - { - msg = "jpl.fli.Prolog.set_default_init_args() called with NULL arg"; - goto err; - } - - if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) - { - msg = "jpl.fli.Prolog.set_default_init_args(): initialisation has already failed"; - goto err; - } - - if ( jpl_test_pvm_init(env) ) // if Prolog VM is initialised - { - return FALSE; // unable to set default init args (too late: PVM is already initialised) - } - else - { - dia = NULL; // probably oughta delete (global) (?) ref of former args... - dia = (*env)->NewGlobalRef(env,jargs); - return TRUE; // OK: default init args set to those provided - } - -err: - (*env)->ThrowNew( env, jJPLException_c, msg); - return FALSE; - } - - -/* - * Class: jpl_fli_PL - * Method: get_actual_init_args - * Signature: ()[Ljava/lang/String; - */ -// -// if not yet init then return null -// if already init then return actual init args as String[] -// if already failed to init then throw an exception -// -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_get_1actual_1init_1args( - JNIEnv *env, - jclass jProlog - ) - { - char *msg; - - jpl_ensure_jpl_init( env); // lazily do "local" initialisations iff necessary - - if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) - { - msg = "jpl.fli.Prolog.get_actual_init_args(): initialisation has already failed"; - goto err; - } - - return ( jpl_test_pvm_init(env) // check PL_initialise() and update local state as appropriate - ? aia // here they are - : NULL // PVM not (yet) initialised - ); - -err: - (*env)->ThrowNew( env, jJPLException_c, msg); - return NULL; - } - - -/* - * Class: jpl_fli_PL - * Method: initialise - * Signature: ()Z - */ -// -// if already init then return FALSE -// if already failed to init then throw an exception -// else attempt to init and if success then return TRUE else throw an exception -// -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_initialise( - JNIEnv *env, - jclass jProlog - ) - { - char *msg; - - jpl_ensure_jpl_init( env); // lazily do "local" initialisations iff necessary - - if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) - { - msg = "jpl.fli.Prolog.initialise(): initialisation has already failed"; - goto err; - } - - if ( jpl_test_pvm_init(env) ) - { - return FALSE; // PVM is already initialised - } - else - { - jpl_do_pvm_init( env); - return jpl_test_pvm_init(env); - } - -err: - (*env)->ThrowNew( env, jJPLException_c, msg); - return FALSE; - } - - -/* - * Class: jpl_fli_PL - * Method: halt - * Signature: (I)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_halt( - JNIEnv *env, - jclass jProlog, - jint jstatus - ) - { - - jpl_ensure_pvm_init(env); - PL_halt( (int)jstatus); - } - - -//=== JPL utility functions ======================================================================== - -/*----------------------------------------------------------------------- - * getLongValue - * - * Retrieves the value in a jpl.fli.LongHolder (or subclass) instance - * - * @param env Java environment - * @param jlong_holder the LongHolder class instance, or null - * @param lv address to write the retrieved (long) value - * @return success? (the LongHolder was not null) - *---------------------------------------------------------------------*/ -static -bool -getLongValue( - JNIEnv *env, - jobject jlong_holder, - long *lv - ) - { - - if ( jlong_holder == NULL ) - { - *lv = 0L; - return FALSE; - } - else // Java compilation ensures it's a jpl.fli.LongHolder instance - { - *lv = (long)(*env)->GetLongField(env,jlong_holder,jLongHolderValue_f); - return TRUE; - } - } - - -/*----------------------------------------------------------------------- - * getPointerValue - * - * Retrieves the value in a jpl.fli.PointerHolder instance - * - * @param env Java environment - * @param jpointer_holder the PointerHolder class instance, or null - * @param pv address to write the retrieved (pointer) value - * @return success? (the PointerHolder was not null) - *---------------------------------------------------------------------*/ -static -bool -getPointerValue( // sets pv to jpointer_holder's .value_ (and succeeds), else sets it to NULL (and fails) - JNIEnv *env, - jobject jpointer_holder, - pointer *pv - ) - { - - if ( jpointer_holder == NULL ) - { - *pv = (pointer)NULL; - return FALSE; - } - else // Java compilation ensures it's a jpl.fli.PointerHolder instance - { - *pv = (pointer)(*env)->GetLongField(env,jpointer_holder,jPointerHolderValue_f); - return TRUE; - } - } - - -/*----------------------------------------------------------------------- - * setPointerValue - * - * Sets the value in a jpl.fli.Pointer class instance (unless it's null) - * to the supplied value (maybe 0L) - * - * @param env Java environment - * @param jpointer_holder the PointerHolder class instance, or null - * @param pv the new (pointer) value - *---------------------------------------------------------------------*/ -static -bool -setPointerValue( - JNIEnv *env, - jobject jpointer_holder, - pointer pv - ) - { - - return jpointer_holder != NULL - && ( (*env)->SetLongField(env,jpointer_holder,jPointerHolderValue_f,(long)pv), - TRUE - ) - ; - } - - -/*----------------------------------------------------------------------- - * setIntValue - * - * Sets the value in a Java IntHolder class instance (unless it's null) - * to the supplied value - * - * @param env Java environment - * @param jint_holder the IntHolder class instance, or null - * @param iv the new (int) value - *---------------------------------------------------------------------*/ -static -bool -setIntValue( - JNIEnv *env, - jobject jint_holder, - int iv - ) - { - - return jint_holder != NULL - && ( (*env)->SetIntField(env,jint_holder,jIntHolderValue_f,iv), - TRUE - ) - ; - } - - -/*----------------------------------------------------------------------- - * setLongValue - * - * Sets the value in a Java LongHolder class instance (unless it's null) - * to the supplied value (maybe 0L) - * - * @param env Java environment - * @param jlong_holder the LongHolder class instance, or null - * @param lv the new (long) value - *---------------------------------------------------------------------*/ -static -bool -setLongValue( - JNIEnv *env, - jobject jlong_holder, - long lv - ) - { - - return jlong_holder != NULL - && ( (*env)->SetLongField(env,jlong_holder,jLongHolderValue_f,lv), - TRUE - ) - ; - } - - -/*----------------------------------------------------------------------- - * setDoubleValue - * - * Sets the value in a Java DoubleHolder class instance (unless it's null) - * to the supplied value - * - * @param env Java environment - * @param jdouble_holder the DoubleHolder class instance, or null - * @param dv the new (double) value - *---------------------------------------------------------------------*/ -static -bool -setDoubleValue( - JNIEnv *env, - jobject jdouble_holder, - double dv - ) - { - - return jdouble_holder != NULL - && ( (*env)->SetDoubleField(env,jdouble_holder,jDoubleHolderValue_f,dv), - TRUE - ) - ; - } - - -/*----------------------------------------------------------------------- - * setStringValue - * - * Sets the value in a Java StringHolder class instance (unless it's null) - * to the supplied value (maybe null) - * - * @param env Java environment - * @param jstring_holder the StringHolder class instance, or null - * @param sv the new (jstring) value - *---------------------------------------------------------------------*/ -static -bool -setStringValue( - JNIEnv *env, - jobject jstring_holder, - jstring sv - ) - { - - return jstring_holder != NULL - && ( (*env)->SetObjectField(env,jstring_holder,jStringHolderValue_f,sv), - TRUE - ) - ; - } - - -/*----------------------------------------------------------------------- - * setObjectValue - * - * Sets the value in a Java ObjectHolder class instance (unless it's null) - * to the supplied value (maybe null) - * - * @param env Java environment - * @param jobject_holder the ObjectHolder class instance, or null - * @param ref the new (jobject) value - *---------------------------------------------------------------------*/ -static -bool -setObjectValue( - JNIEnv *env, - jobject jobject_holder, - jobject ref - ) - { - - return jobject_holder != NULL - && ( (*env)->SetObjectField(env,jobject_holder,jObjectHolderValue_f,ref), - TRUE - ) - ; - } - - -/*----------------------------------------------------------------------- - * setBooleanValue - * - * Sets the .value field of a Java BooleanHolder class instance (unless it's null) - * to the supplied jboolean value - * - * @param env Java environment - * @param jboolean_holder the BooleanHolder class instance, or null - * @param jb the new (jboolean) value - *---------------------------------------------------------------------*/ -static -bool -setBooleanValue( - JNIEnv *env, - jobject jboolean_holder, - jboolean jb - ) - { - - return jboolean_holder != NULL - && ( (*env)->SetBooleanField(env,jboolean_holder,jBooleanHolderValue_f,jb), - TRUE - ) - ; - } - - -/*----------------------------------------------------------------------- - * updateAtomValue - * - * Updates the value in a Java atom_t class instance (unless it's null) - * to the supplied value (maybe 0L); unregisters and registers old and new - * atom references as appropriate. NB atom_t extends LongHolder. - * - * @param env Java environment - * @param jatom_holder the atom_t class instance, or null - * @param atom2 the new atom reference - *---------------------------------------------------------------------*/ -static -bool -updateAtomValue( - JNIEnv *env, - jobject jatom_holder, - atom_t atom2 // new value (perhaps 0L (?)) - ) - { - atom_t atom1; // old value (perhaps 0L (?)) - - if ( jatom_holder == NULL ) - { - return FALSE; - } - else - { - atom1 = (atom_t)(*env)->GetLongField(env,jatom_holder,jLongHolderValue_f); - if ( atom1 != 0L ) - { - PL_unregister_atom( atom1); - } - (*env)->SetLongField(env,jatom_holder,jLongHolderValue_f,(long)atom2); - if ( atom2 != 0L ) - { - PL_register_atom( atom2); - } - return TRUE; - } - } - - - -//=== Java-wrapped SWI-Prolog FLI functions ======================================================== - -/* - * Class: jpl_fli_PL - * Method: new_term_ref - * Signature: ()Ljpl/fli/term_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1term_1ref( - JNIEnv *env, - jclass jProlog - ) - { - jobject rval; - - return ( jpl_ensure_pvm_init(env) - && (rval=(*env)->AllocObject(env,jTermT_c)) != NULL - && setLongValue(env,rval,(long)PL_new_term_ref()) - ? rval - : NULL - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: new_term_refs - * Signature: (I)Ljpl/fli/term_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1term_1refs( - JNIEnv *env, - jclass jProlog, - jint jn - ) - { - jobject rval; - term_t trefs; - - DEBUG(1, Sdprintf( ">new_term_refs(env=%lu,jProlog=%lu,jn=%lu)...\n", (long)env, (long)jProlog, (long)jn)); - - return ( jpl_ensure_pvm_init(env) - && jn >= 0 // I hope PL_new_term_refs(0) is defined [ISSUE] - && (rval=(*env)->AllocObject(env,jTermT_c)) != NULL - && ( trefs=PL_new_term_refs((int)jn), TRUE ) - && setLongValue(env,rval,(long)trefs) - && ( DEBUG(1, Sdprintf(" ok: stashed trefs=%ld into new term_t object\n",(long)trefs)), TRUE ) - ? rval - : NULL - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: copy_term_ref - * Signature: (Ljpl/fli/term_t;)Ljpl/fli/term_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_copy_1term_1ref( - JNIEnv *env, - jclass jProlog, - jobject jfrom - ) - { - jobject rval; - term_t term; - term_t term2; - - return ( jpl_ensure_pvm_init(env) - // && jfrom != NULL // redundant: getLongValue checks this - && getLongValue(env,jfrom,(long*)&term) // SWI RM implies must be non-null - && (rval=(*env)->AllocObject(env,jTermT_c)) != NULL - && ( (term2=PL_copy_term_ref(term)) , TRUE ) // SWI RM -> always succeeds - && setLongValue(env,rval,(long)term2) - ? rval - : NULL // oughta warn of failure? - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: reset_term_refs - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_reset_1term_1refs( - JNIEnv *env, - jclass jProlog, - jobject jafter - ) - { - term_t term; - - if ( jpl_ensure_pvm_init(env) - // && jafter != NULL // redundant: getLongValue checks this - && getLongValue(env,jafter,&term) // SWI RM -> oughta be non-null - ) - { - PL_reset_term_refs( term); // void; SWI RM -> "always succeeds" - } - } - - -/* - * Class: jpl_fli_PL - * Method: new_atom - * Signature: (Ljava/lang/String;)Ljpl/fli/atom_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1atom( - JNIEnv *env, - jclass jProlog, - jstring jname - ) - { - const char *name; - atom_t atom; - jobject rval; - - return ( jpl_ensure_pvm_init(env) - && jname != NULL - && (name=(*env)->GetStringUTFChars(env,jname,NULL)) != NULL // no exceptions - && ( (atom=PL_new_atom(name)) , TRUE ) // SWI RM p138 -> "always succeeds"; incs ref count - && ( (*env)->ReleaseStringUTFChars(env,jname,name) , TRUE ) // void; no exceptions - && (rval=(*env)->AllocObject(env,jAtomT_c)) != NULL // doesn't call any constructor - && setLongValue(env,rval,(long)atom) - ? rval - : NULL // oughta warn of failure? - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: atom_chars - * Signature: (Ljpl/fli/atom_t;)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL // the local ref goes out of scope, -Java_jpl_fli_Prolog_atom_1chars( // but the string itself doesn't - JNIEnv *env, - jclass jProlog, - jobject jatom - ) - { - atom_t atom; - jstring lref; - // jstring gref; - const char *s; - - return ( jpl_ensure_pvm_init(env) - && getLongValue(env,jatom,(long*)&atom) // checks jatom != null - && (s=PL_atom_chars(atom)) != NULL // SWI RM -> "always succeeds" - && (lref=(*env)->NewStringUTF(env,s)) != NULL // out-of-memory -> NULL, exception - ? lref - : NULL - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: new_functor - * Signature: (Ljpl/fli/atom_t;I)Ljpl/fli/functor_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1functor( - JNIEnv *env, - jclass jProlog, - jobject jatom, // read-only - jint jarity - ) - { - term_t atom; - functor_t functor; - jobject rval; - - return ( jpl_ensure_pvm_init(env) - && jarity >= 0 - && getLongValue(env,jatom,(long*)&atom) // checks jatom isn't null - && (rval=(*env)->AllocObject(env,jFunctorT_c)) != NULL - && (functor=PL_new_functor(atom,(int)jarity)) != 0L - && setLongValue(env,rval,(long)functor) - ? rval - : NULL // oughta warn of failure? - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: functor_name - * Signature: (Ljpl/fli/functor_t;)Ljpl/fli/atom_t; - */ -JNIEXPORT jobject JNICALL // returns a new atom_t, containing a newly-registered atom ref -Java_jpl_fli_Prolog_functor_1name( - JNIEnv *env, - jclass jProlog, - jobject jfunctor - ) - { - functor_t functor; - atom_t atom; - jobject rval; - - return ( jpl_ensure_pvm_init(env) - && getLongValue(env,jfunctor,(long*)&functor) // SWI RM -> must be a real functor - && (atom=PL_functor_name(functor)) != 0L // unlike PL_new_atom, doesn't register the ref - && (rval=(*env)->AllocObject(env,jAtomT_c)) != NULL // doesn't call any constructor - && setLongValue(env,rval,(long)atom) - && ( PL_register_atom(atom), TRUE ) // register this reference - ? rval - : NULL // oughta warn of failure? - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: functor_arity - * Signature: (Ljpl/fli/functor_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_functor_1arity( - JNIEnv *env, - jclass jProlog, - jobject jfunctor - ) - { - functor_t functor; - - return ( jpl_ensure_pvm_init(env) - && getLongValue(env,jfunctor,(long*)&functor) // checks jfunctor isn't null - ? PL_functor_arity(functor) - : -1 // oughta warn of failure? - ) - ; - } - - -//=== from "5.6.3 Analysing terms via the foreign interface", "Testing the Type of a term" ======== - -// not needed: -// PL_register_atom() - -/* - * Class: jpl_fli_PL - * Method: term_type - * Signature: (Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_term_1type( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return ( jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - ? PL_term_type(term) - : -1 // i.e. when jterm is null - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_variable - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1variable( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && PL_is_variable(term) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_atom - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1atom( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && PL_is_atom(term) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_integer - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1integer( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && PL_is_integer(term) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_float - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1float( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && PL_is_float(term) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_compound - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1compound( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && PL_is_compound(term) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_functor - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1functor( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor - ) - { - term_t term; - functor_t functor; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && getLongValue(env,jfunctor,(long*)&functor) // checks jfunctor isn't null - && PL_is_functor(term,functor) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_list - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1list( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && PL_is_list(term) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_atomic - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1atomic( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && PL_is_atomic(term) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: is_number - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_is_1number( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null - && PL_is_number(term) - ; - } - - - -//=== from "5.6.3 Analysing Terms via the Foreign Interface: Reading data from a term" ============ - -// not yet mapped: register_atom() -// unregister_atom() - -/* - * Class: jpl_fli_PL - * Method: get_atom - * Signature: (Ljpl/fli/term_t;Ljpl/fli/atom_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1atom( - JNIEnv *env, - jclass jProlog, - jobject jterm, // read - jobject jatom // update - ) - { - term_t term; - atom_t atom; - - return jpl_ensure_pvm_init(env) - && jatom != NULL // don't call PL_get_atom if jatom is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL - && PL_get_atom(term,&atom) // iff term is an atom; doesn't register the ref - && updateAtomValue(env,jatom,atom) // unreg old ref (if any); reg new ref (if any) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_atom_chars - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1atom_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jstring_holder - ) - { - term_t term; - char *s; - jstring string; - - return jpl_ensure_pvm_init(env) - && jstring_holder != NULL // don't call PL_get_atom_chars if this is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL - && PL_get_atom_chars(term,&s) // fails (usefully) if term is not an atom - && (string=(*env)->NewStringUTF(env,s)) != NULL // OK as local ref... - && setStringValue(env,jstring_holder,string) // ...when sent straight back to JVM - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_string_chars - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1string_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jstring_holder - ) - { - term_t term; - char *s; - int n; - jstring string; - - return jpl_ensure_pvm_init(env) - && jstring_holder != NULL // don't call PL_get_atom_chars if this is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL - && PL_get_string_chars(term,&s,&n) // fails (usefully) if term is not a string - && (string=(*env)->NewStringUTF(env,s)) != NULL // OK as local ref... - && setStringValue(env,jstring_holder,string) // ...when sent straight back to JVM - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_chars - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;I)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1chars( // withdraw this? - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jstring_holder, - jint jflags - ) - { - term_t term; - char *s; - jstring string; - - return jpl_ensure_pvm_init(env) - && jstring_holder != NULL - && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL - && PL_get_chars(term,&s,(unsigned)jflags) - && (string=(*env)->NewStringUTF(env,s)) != NULL - && setStringValue(env,jstring_holder,string) // OK as local ref? - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_list_chars - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;I)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1list_1chars( // withdraw this? - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jstring_holder, - jint jflags - ) - { - term_t term; - char *s; - jstring string; - - return jpl_ensure_pvm_init(env) - && jstring_holder != NULL // don't call PL_get_list_chars if this is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && PL_get_list_chars(term,&s,(unsigned)jflags) - && (string=(*env)->NewStringUTF(env,s)) != NULL - && setStringValue(env,jstring_holder,string) // OK as local ref? - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_integer - * Signature: (Ljpl/fli/term_t;Ljpl/fli/IntHolder;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1integer( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jint_holder - ) - { - term_t term; - int i; - - return jpl_ensure_pvm_init(env) - && jint_holder != NULL // don't call PL_get_integer if this is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && PL_get_integer(term,&i) - && setIntValue(env,jint_holder,i) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_pointer - * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1pointer( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jpointer - ) - { - term_t term; - pointer ptr; - - return jpl_ensure_pvm_init(env) - && jpointer != NULL - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && PL_get_pointer(term,(void**)&ptr) - && setPointerValue(env,jpointer,ptr) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_float - * Signature: (Ljpl/fli/term_t;Ljpl/fli/DoubleHolder;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1float( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jdouble_holder - ) - { - term_t term; - double d; - - return jpl_ensure_pvm_init(env) - && jdouble_holder != NULL - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && PL_get_float(term,&d) - && setDoubleValue(env,jdouble_holder,d) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_jref - * Signature: (Ljpl/fli/term_t;Ljpl/fli/ObjectHolder;)Z - */ -// added 26/Jan/2004 untested... -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1jref( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jobject_holder - ) - { - term_t term; - jobject ref; - char *cp; - functor_t fn; - term_t a1; - atom_t a; - - return jpl_ensure_pvm_init(env) - && jobject_holder != NULL - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && JNI_term_to_ref(term,ref) - && setObjectValue(env,jobject_holder,ref) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_jboolean - * Signature: (Ljpl/fli/term_t;Ljpl/fli/BooleanHolder;)Z - */ -// called with a term_t holder and a boolean holder; -// if the term_t is @(false) or @(true), sets the boolean value accordingly and succeeds, -// else fails -// added 26/Jan/2004 untested... -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1jboolean( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jboolean_holder - ) - { - term_t term; // temp for term ref extracted from the passed-in "term_t holder" - jboolean b; // temp for boolean by-ref result from JNI_term_to_jboolean(+,-) - functor_t fn; // temp for JNI_term_to_jboolean(+,-) - term_t a1; // " - atom_t a; // " - - return jpl_ensure_pvm_init(env) // merge these please - && jni_ensure_jvm() // " - && jboolean_holder != NULL // fail if no boolean holder is passed - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && JNI_term_to_jboolean(term,b) - && setBooleanValue(env,jboolean_holder,b) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_jpl_term - * Signature: (Ljpl/fli/term_t;Ljpl/fli/ObjectHolder;)Z - */ -// -// added 18/Jun/2004 PS untested... -// succeeds iff jterm is one of the special JPL terms, -// i.e. @(false), @(true), @(null) or @(Tag) e.g. @('J#0123456789'), -// stashing a corresponding jpl.JBoolean or jpl.JRef into the object holder -// -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1jpl_1term( - JNIEnv *env, - jclass jProlog, - jobject jterm, // a jpl.fli.term_t instance - jobject jobject_holder // a jpl.fli.ObjectHolder instance - ) - { - term_t term; // the Prolog term referred to by jterm - functor_t fn; // the term's functor - term_t a1; // the term's first & only arg, if it has one - atom_t a; // the atom which is the term's only arg - jobject obj; // a JBoolean or JRef to be returned - jobject ref; // the object referred to by Tag - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) - && PL_get_functor(term,&fn) // succeeds iff jterm is atom or compound - && fn == JNI_functor_at_1 // jterm is @(Something) - && ( a1 = PL_new_term_ref(), - PL_get_arg(1,term,a1) // a1 is that Something - ) - && PL_get_atom(a1,&a) // succeeds iff a1 is an atom - && ( a == JNI_atom_null // Something == null - ? (obj=(*env)->AllocObject(env,jJRef_c)) != NULL - && ((*env)->SetObjectField(env,obj,jJRefRef_f,NULL), TRUE) - && setObjectValue(env,jobject_holder,obj) - : a == JNI_atom_true // Something == true - ? (obj=(*env)->AllocObject(env,jJBoolean_c)) != NULL - && ((*env)->SetBooleanField(env,obj,jJBooleanValue_f,TRUE), TRUE) - && setObjectValue(env,jobject_holder,obj) - : a == JNI_atom_false // Something == false - ? (obj=(*env)->AllocObject(env,jJBoolean_c)) != NULL - && ((*env)->SetBooleanField(env,obj,jJBooleanValue_f,FALSE), TRUE) - && setObjectValue(env,jobject_holder,obj) - : jni_tag_to_iref(a,(int*)&ref) // convert digits to int - ? (obj=(*env)->AllocObject(env,jJRef_c)) != NULL - && ((*env)->SetObjectField(env,obj,jJRefRef_f,ref), TRUE) - && setObjectValue(env,jobject_holder,obj) - : FALSE // jterm is not a special JPL structure - ); - } - - -/* - * Class: jpl_fli_PL - * Method: get_functor - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1functor( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor - ) - { - term_t term; - functor_t functor; - - return jpl_ensure_pvm_init(env) - && jfunctor != NULL - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && PL_get_functor(term,&functor) - && setLongValue(env,jfunctor,(long)functor) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_name_arity - * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;Ljpl/fli/IntHolder;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1name_1arity( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jname_holder, // was atom_t, now StringHolder - jobject jarity_holder - ) - { - term_t term; - atom_t atom; - int arity; - char *name; - jstring jname; - - return jpl_ensure_pvm_init(env) - && jname_holder != NULL // don't proceed if this holder is null - && jarity_holder != NULL // don't proceed if this holder is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && PL_get_name_arity(term,&atom,&arity) // no need to register transient atom ref - && ( name=(char*)PL_atom_chars(atom) , TRUE ) // from const char* - && (jname=(*env)->NewStringUTF(env,name)) != NULL - && setStringValue(env,jname_holder,jname) // stash String ref in holder - && setIntValue(env,jarity_holder,arity) // stash arity value in holder - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_module - * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1module( - JNIEnv *env, - jclass jProlog, - jobject jterm, // read - jobject jmodule // update - ) - { - term_t term; - module_t module; - - return jpl_ensure_pvm_init(env) - && jmodule != NULL // don't proceed if this holder is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && PL_get_module(term,&module) - && setPointerValue(env,jmodule,(pointer)module) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_arg - * Signature: (ILjpl/fli/term_t;Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1arg( - JNIEnv *env, - jclass jProlog, - jint jindex, - jobject jterm, - jobject jarg - ) - { - term_t term; - term_t arg; - - return jpl_ensure_pvm_init(env) - && jarg != NULL // don't proceed if this holder is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && ( arg=PL_new_term_ref() , TRUE ) // Fred used jarg's original term ref (?) - && PL_get_arg(jindex,term,arg) - && setLongValue(env,jarg,(long)arg) - ; - } - - -//=== from "5.6.3 Analysing Terms via the Foreign Interface: Reading a list" ====================== - -// not yet mapped: -// get_atom_nchars() -// get_atom_nchars() -// get_list_nchars() -// get_nchars() -// put_atom_nchars() -// put_list_ncodes() -// put_list_nchars() -// unify_atom_nchars() -// unify_list_ncodes() -// unify_list_nchars() - -/* - * Class: jpl_fli_PL - * Method: get_list - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1list( - JNIEnv *env, - jclass jProlog, - jobject jlist, - jobject jhead, - jobject jtail - ) - { - term_t list; - term_t head = PL_new_term_ref(); - term_t tail = PL_new_term_ref(); - - return jpl_ensure_pvm_init(env) - && jhead != NULL - && jtail != NULL - && getLongValue(env,jlist,(long*)&list) // checks that jlist isn't null - && PL_get_list(list,head,tail) - && setLongValue(env,jhead,(long)head) - && setLongValue(env,jtail,(long)tail) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_head - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1head( - JNIEnv *env, - jclass jProlog, - jobject jlist, - jobject jhead - ) - { - term_t list; - term_t head = PL_new_term_ref(); - - return jpl_ensure_pvm_init(env) - && jhead != NULL - && getLongValue(env,jlist,(long*)&list) // checks that jlist isn't null - && PL_get_head(list,head) - && setLongValue(env,jhead,(long)head) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_tail - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1tail( - JNIEnv *env, - jclass jProlog, - jobject jlist, - jobject jtail - ) - { - term_t list; - term_t tail = PL_new_term_ref(); - - return jpl_ensure_pvm_init(env) - && jtail != NULL - && getLongValue(env,jlist,(long*)&list) // checks that jlist isn't null - && PL_get_tail(list,tail) - && setLongValue(env,jtail,(long)tail) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_nil - * Signature: (Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_get_1nil( // redundant: tests term == '[]' - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - return jpl_ensure_pvm_init(env) - && jterm != NULL - && getLongValue(env,jterm,(long*)&term) - && PL_get_nil(term) - ; - } - - -//=== from "5.6.4 Constructing terms" ============================================================== -// these methods perhaps oughta return jboolean, false iff given object is null... - -/* - * Class: jpl_fli_PL - * Method: put_variable - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1variable( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; - - if ( jpl_ensure_pvm_init(env) // may throw exception but cannot fail - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - ) - { - PL_put_variable(term); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_atom - * Signature: (Ljpl/fli/term_t;Ljpl/fli/atom_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1atom( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jatom - ) - { - term_t term; - atom_t atom; - - if ( jpl_ensure_pvm_init(env) - && jatom != NULL // don't proceed if this holder is null - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - ) - { - getLongValue( env, jterm, (long*)&term); - getLongValue( env, jatom, (long*)&atom); // no need to register this transient atom ref - PL_put_atom( term, atom); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_atom_chars - * Signature: (Ljpl/fli/term_t;Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1atom_1chars( // no atom refs involved here - JNIEnv *env, - jclass jProlog, - jobject jterm, - jstring jchars - ) - { - term_t term; - const char *chars; - - if ( jpl_ensure_pvm_init(env) - && jchars != NULL - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && (chars=(*env)->GetStringUTFChars(env,jchars,NULL)) != NULL // is this return idiom OK? [ISSUE] - ) - { - PL_put_atom_chars( term, chars); - (*env)->ReleaseStringUTFChars( env, jchars, chars); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_list_chars - * Signature: (Ljpl/fli/term_t;Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1list_1chars( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jstring jchars - ) - { - term_t term; - const char *chars; - - if ( jpl_ensure_pvm_init(env) - && jchars != NULL - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && (chars=(*env)->GetStringUTFChars(env,jchars,NULL)) != NULL // is this return idiom OK? [ISSUE] - ) - { - PL_put_list_chars( term, chars); - (*env)->ReleaseStringUTFChars( env, jchars, chars); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_integer - * Signature: (Ljpl/fli/term_t;J)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1integer( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jlong ji // why jlong? - ) - { - term_t term; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - ) - { - PL_put_integer( term, (int)ji); // ??? - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_pointer - * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1pointer( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jpointer - ) - { - term_t term; - pointer ptr; - - if ( jpl_ensure_pvm_init(env) - && jpointer != NULL - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && getPointerValue(env,jpointer,&ptr) - ) - { - PL_put_pointer( term, (void*)ptr); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_float - * Signature: (Ljpl/fli/term_t;D)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1float( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jdouble jf - ) - { - term_t term; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - ) - { - PL_put_float( term, jf); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_functor - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1functor( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor - ) - { - term_t term; - functor_t functor; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && getLongValue(env,jfunctor,(long*)&functor) // checks that jfunctor isn't null - ) - { - PL_put_functor( term, functor); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_list - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1list( - JNIEnv *env, - jclass jProlog, - jobject jlist - ) - { - term_t term; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jlist,(long*)&term) // checks that jlist isn't null - ) - { - PL_put_list( term); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_nil - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void -JNICALL Java_jpl_fli_Prolog_put_1nil( - JNIEnv *env, - jclass jProlog, - jobject jlist - ) - { - term_t term; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jlist,(long*)&term) // checks that jlist isn't null - ) - { - PL_put_nil( term); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_term - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1term( - JNIEnv *env, - jclass jProlog, - jobject jterm1, - jobject jterm2 - ) - { - term_t term1; - term_t term2; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jterm1,(long*)&term1) // checks that jterm1 isn't null - && getLongValue(env,jterm2,(long*)&term2) // checks that jterm2 isn't null - ) - { - PL_put_term( term1, term2); - } - } - - -/* - * Class: jpl_fli_PL - * Method: put_jref - * Signature: (Ljpl/fli/term_t;Ljava/lang/Object;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1jref( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jref - ) - { - term_t term; - jobject j; // temp for JNI_jobject_to_term(+,-) - atom_t a; // " - int i; // " - - DEBUG(1, Sdprintf( ">put_ref(env=%lu,jProlog=%lu,jterm=%lu,jref=%lu)...\n", env, jProlog, jterm, jref)); - - ( jpl_ensure_pvm_init(env) // combine these two please - && jni_ensure_jvm() // " - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && JNI_jobject_to_term(jref,term) // assumes term is var; OK if jref == null - ); - } - - -/* - * Class: jpl_fli_PL - * Method: put_jboolean - * Signature: (Ljpl/fli/term_t;Z)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1jboolean( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jboolean jbool - ) - { - term_t term; // temp for term ref from within the passed "term holder" - - DEBUG(1, Sdprintf( ">put_jboolean(env=%lu,jProlog=%lu,jterm=%lu,jbool=%u)...\n", env, jProlog, jterm, jbool)); - - ( jpl_ensure_pvm_init(env) // combine these two please - && jni_ensure_jvm() // " - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && JNI_jboolean_to_term(jbool,term) // assumes term is var - ); - } - - -/* - * Class: jpl_fli_PL - * Method: put_jvoid - * Signature: (Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_put_1jvoid( - JNIEnv *env, - jclass jProlog, - jobject jterm - ) - { - term_t term; // temp for term ref from within the passed "term holder" - - DEBUG(1, Sdprintf( ">put_jvoid(env=%lu,jProlog=%lu,jterm=%lu)...\n", env, jProlog, jterm)); - - ( jpl_ensure_pvm_init(env) // combine these two please - && jni_ensure_jvm() // " - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && JNI_unify_void(term) // assumes term is var - ); - } - - -/* - * Class: jpl_fli_PL - * Method: cons_functor_v - * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_cons_1functor_1v( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jfunctor, - jobject jterm0 - ) - { - term_t term; - functor_t functor; - term_t term0; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null - && getLongValue(env,jfunctor,(long*)&functor) // checks that jfunctor isn't null - && getLongValue(env,jterm0,(long*)&term0) // checks that jterm0 isn't null - ) - { - PL_cons_functor_v( term, functor, term0); - } - } - - -/* - * Class: jpl_fli_PL - * Method: cons_list - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;Ljpl/fli/term_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_cons_1list( - JNIEnv *env, - jclass jProlog, - jobject jlist, - jobject jhead, - jobject jtail ) - { - term_t list; - term_t head; - term_t tail; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jlist,(long*)&list) // checks that jlist isn't null - && getLongValue(env,jhead,(long*)&head) // checks that jhead isn't null - && getLongValue(env,jtail,(long*)&tail) // checks that jtail isn't null - ) - { - PL_cons_list( list, head, tail); - } - } - - -//=== from "5.6.5 Unifying data" ================================================================== - -// not yet mapped: -// unify_atom() -// unify_atom_chars() -// unify_list_chars() -// unify_integer() -// unify_float() -// unify_pointer() -// unify_functor() -// unify_list() -// unify_nil() -// unify_arg() -// unify_term() -// chars_to_term() -// quote() - -// /* -// * Class: jpl_fli_PL -// * Method: unify -// * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)I -// */ -// JNIEXPORT jint JNICALL -// Java_jpl_fli_Prolog_unify( -// JNIEnv *env, -// jclass jProlog, -// jobject jterm1, -// jobject jterm2 -// ) -// { -// term_t term1; -// term_t term2; -// -// if ( jpl_ensure_pvm_init(env) -// && getLongValue(env,jterm1,(long*)&term1) // checks that jterm1 isn't null -// && getLongValue(env,jterm2,(long*)&term2) // checks that jterm2 isn't null -// ) -// { -// PL_unify( term1, term2); -// } -// } - - -//=== from "5.6.7 Discarding data" (none of these are (yet) used in LLI or HLI) =================== - -/* - * Class: jpl_fli_PL - * Method: open_foreign_frame - * Signature: ()Ljpl/fli/fid_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_open_1foreign_1frame( - JNIEnv *env, - jclass jProlog - ) - { - jobject rval; - - if ( jpl_ensure_pvm_init(env) - && (rval=(*env)->AllocObject(env,jFidT_c)) != NULL // get a new fid_t object - && setLongValue(env,rval,(long)PL_open_foreign_frame()) // open a frame only if alloc succeeds - ) - { - return rval; - } - else - { - return NULL; - } - } - - -/* - * Class: jpl_fli_PL - * Method: close_foreign_frame - * Signature: (Ljpl/fli/fid_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_close_1foreign_1frame( - JNIEnv *env, - jclass jProlog, - jobject jfid - ) - { - fid_t fid; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jfid,(long*)&fid) // checks that jfid isn't null - ) - { - PL_close_foreign_frame(fid); - } - } - - -/* - * Class: jpl_fli_PL - * Method: discard_foreign_frame - * Signature: (Ljpl/fli/fid_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_discard_1foreign_1frame( - JNIEnv *env, - jclass jProlog, - jobject jfid - ) - { - fid_t fid; - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jfid,(long*)&fid) // checks that jfid isn't null - ) - { - PL_discard_foreign_frame(fid); - } - } - - -//=== from "5.6.6 Calling Prolog from C: Predicate references" ==================================== - -/* - * Class: jpl_fli_PL - * Method: pred - * Signature: (Ljpl/fli/functor_t;Ljpl/fli/module_t;)Ljpl/fli/predicate_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_pred( - JNIEnv *env, - jclass jProlog, - jobject jfunctor, - jobject jmodule - ) - { - functor_t functor; - module_t module; - predicate_t predicate; - jobject rval; - - return ( jpl_ensure_pvm_init(env) - && getLongValue(env,jfunctor,(long*)&functor) // checks that jfunctor isn't null - && ( getPointerValue(env,jmodule,(pointer*)&module) , TRUE ) // if jmodule is null then module = NULL - && ( (predicate=PL_pred(functor,module)) , TRUE ) // module==NULL is OK (?) [ISSUE] - && (rval=(*env)->AllocObject(env,jPredicateT_c)) != NULL - && setPointerValue(env,rval,(pointer)predicate) - && ( DEBUG(1, Sdprintf("[pred module = %s]\n",(module==NULL?"(null)":PL_atom_chars(PL_module_name(module))))), TRUE ) - ? rval - : NULL // oughta warn of failure? - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: predicate - * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljpl/fli/predicate_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_predicate( - JNIEnv *env, - jclass jProlog, - jstring jname, - jint jarity, - jstring jmodule - ) - { - const char *name; - const char *module; // NOT module_t as in JPL 1.0.1 - predicate_t predicate; - jobject rval; - - DEBUG(1, Sdprintf(">predicate(env=%lu,jProlog=%lu,jname=%lu,jarity=%lu,jmodule=%lu)...\n", - (long)env, (long)jProlog, (long)jname, (long)jarity, (long)jmodule)); - return ( jpl_ensure_pvm_init(env) - && jname != NULL - && jarity >= 0 - && (name=(*env)->GetStringUTFChars(env,jname,0)) != NULL - && ( jmodule != NULL - ? (module=(*env)->GetStringUTFChars(env,jmodule,0)) != NULL - : ( module=NULL, TRUE ) - ) - && ( (predicate=PL_predicate(name,jarity,module)) , TRUE ) - && ( (*env)->ReleaseStringUTFChars(env,jname,name) , TRUE ) - && ( jmodule != NULL - ? ( (*env)->ReleaseStringUTFChars(env,jmodule,module), TRUE ) - : TRUE - ) - && (rval=(*env)->AllocObject(env,jPredicateT_c)) != NULL - && setPointerValue(env,rval,(pointer)predicate) - ? ( - DEBUG(1, Sdprintf("[predicate() module=%s\n",(module==NULL?"(null)":module))), - rval - ) - : NULL // oughta warn of failure? - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: predicate_info - * Signature: (Ljpl/fli/predicate_t;Ljpl/fli/atom_t;ILjpl/fli/module_t;)I - */ -// -// perhaps this oughta return a jboolean instead? -// -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_predicate_1info( - JNIEnv *env, - jclass jProlog, - jobject jpredicate, - jobject jatom, // this Atom instance will have its value field destructively updated - jobject jarity_holder, - jobject jmodule - ) - { - predicate_t predicate; - atom_t atom; // update - int arity; // update - module_t module; // update - - return jpl_ensure_pvm_init(env) - && jatom != NULL // must have an atom holder object - && jarity_holder != NULL // must have an arity holder object - && jmodule != NULL // must have a module holder object - && getPointerValue(env,jpredicate,(pointer*)&predicate) // checks that jpredicate isn't null - && ( PL_predicate_info(predicate,&atom,&arity,&module) , TRUE ) // "always succeeds"; returns void - && updateAtomValue(env,jatom,atom) // unreg old ref, if any; reg new ref - && setIntValue(env,jarity_holder,arity) // stash arity in holder - && setPointerValue(env,jmodule,(pointer)module) // stash module ref in holder - ; - } - - -//=== from "5.6.6 Calling Prolog from C: Initiating a query from C" =============================== - -/* - * Class: jpl_fli_PL - * Method: open_query - * Signature: (Ljpl/fli/module_t;ILjpl/fli/predicate_t;Ljpl/fli/term_t;)Ljpl/fli/qid_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_open_1query( - JNIEnv *env, - jclass jProlog, - jobject jmodule, // read - jint jflags, // read - jobject jpredicate, // read - jobject jterm0 // read - ) - { - module_t module; - predicate_t predicate; - term_t term0; - qid_t qid; - jobject jqid; // for returned new QidT object - - DEBUG(1, Sdprintf( ">open_query(env=%lu,jProlog=%lu,jmodule=%lu,jflags=%lu,jpredicate=%lu,jterm0=%lu)...\n", - (long)env, (long)jProlog, (long)jmodule, (long)jflags, (long)jpredicate, (long)jterm0)); - return ( jpl_ensure_pvm_init(env) - && ( getPointerValue(env,jmodule,(pointer*)&module) , TRUE ) // NULL module is OK below... - && ( DEBUG(1, Sdprintf(" ok: getPointerValue(env,jmodule=%lu,&(pointer)module=%lu)\n",(long)jmodule,(long)module)), TRUE ) - && getPointerValue(env,jpredicate,(pointer*)&predicate) // checks that jpredicate != NULL - && ( DEBUG(1, Sdprintf(" ok: getPointerValue(env,jpredicate=%lu,&(pointer)predicate=%lu)\n",(long)jpredicate,(long)predicate)), TRUE ) - && getLongValue(env,jterm0,(long*)&term0) // jterm0!=NULL - && ( (qid=PL_open_query(module,jflags,predicate,term0)) , TRUE ) // NULL module is OK (?) [ISSUE] - && ( DEBUG(1, Sdprintf(" ok: PL_open_query(module=%lu,jflags=%u,predicate=%lu,term0=%lu)=%lu\n",(long)module,jflags,(long)predicate,(long)term0,(long)qid)), TRUE ) - && (jqid=(*env)->AllocObject(env,jQidT_c)) != NULL - && ( DEBUG(1, Sdprintf(" ok: AllocObject(env,jQidT_c)=%lu\n",(long)jqid)), TRUE ) - && setLongValue(env,jqid,(long)qid) - && ( DEBUG(1, Sdprintf(" ok: setLongValue(env,%lu,%lu)\n",(long)jqid,(long)qid)), TRUE ) - && ( DEBUG(1, Sdprintf("[open_query module = %s]\n", (module==NULL?"(null)":PL_atom_chars(PL_module_name(module))))), TRUE ) - ? ( - DEBUG(1, Sdprintf(" =%lu\n",(long)jqid)), - jqid - ) - : NULL // oughta diagnose failure? raise JPL exception? - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: next_solution - * Signature: (Ljpl/fli/qid_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_next_1solution( - JNIEnv *env, - jclass jProlog, - jobject jqid // read - ) - { - qid_t qid; - int rval; // for boolean return value - - DEBUG(1, Sdprintf( ">next_solution(env=%lu,jProlog=%lu,jqid=%lu)...\n", (long)env, (long)jProlog, (long)jqid)); - return jpl_ensure_pvm_init(env) - && getLongValue(env,jqid,(long*)&qid) // checks that jqid isn't null - && ( DEBUG(1, Sdprintf( " ok: getLongValue(env,jqid,(long*)&qid(%lu))\n",(long)qid)), TRUE ) - && ( rval=PL_next_solution(qid), TRUE ) // can call this until it returns FALSE - && ( DEBUG(1, Sdprintf( " ok: PL_next_solution(qid=%lu)=%u\n",(long)qid,rval)), TRUE ) - && ( - DEBUG(1, Sdprintf(" =%lu\n",(long)rval)), - rval - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: cut_query - * Signature: (Ljpl/fli/qid_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_cut_1query( - JNIEnv *env, - jclass jProlog, - jobject jqid - ) - { - qid_t qid; - - DEBUG(1, Sdprintf( ">cut_query(env=%lu,jProlog=%lu,jquid=%u)...\n", (long)env, (long)jProlog, (long)jqid)); - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jqid,(long*)&qid) // checks that jqid != NULL - ) - { - PL_cut_query( qid); // void - DEBUG(1, Sdprintf( " ok: PL_cut_query(%lu)\n", (long)qid)); - } - } - - -/* - * Class: jpl_fli_PL - * Method: close_query - * Signature: (Ljpl/fli/qid_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_close_1query( - JNIEnv *env, - jclass jProlog, - jobject jqid - ) - { - qid_t qid; - - DEBUG(1, Sdprintf( ">close_query(env=%lu,jProlog=%lu,jquid=%u)...\n", (long)env, (long)jProlog, (long)jqid)); - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jqid,(long*)&qid) // checks that jqid != NULL - ) - { - PL_close_query( qid); // void - DEBUG(1, Sdprintf( " ok: PL_close_query(%lu)\n", (long)qid)); - } - } - - -/* - * Class: jpl_fli_PL - * Method: call_predicate - * Signature: (Ljpl/fli/module_t;ILjpl/fli/predicate_t;Ljpl/fli/term_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_call_1predicate( - JNIEnv *env, - jclass jProlog, - jobject jmodule, // null is OK - jint jflags, - jobject jpredicate, - jobject jterm0 - ) - { - module_t module; - predicate_t predicate; - term_t term0; - - return jpl_ensure_pvm_init(env) - && ( getPointerValue(env,jmodule,(pointer*)&module) , TRUE ) // if jmodule is null then module = NULL - && getPointerValue(env,jpredicate,(pointer*)&predicate) // checks that jpredicate isn't null - && getLongValue(env,jterm0,(long*)&term0) // checks that jterm0 isn't null - && PL_call_predicate(module,jflags,predicate,term0) // assumes module == NULL is OK [ISSUE] - ; - } - - -/* - * Class: jpl_fli_PL - * Method: call - * Signature: (Ljpl/fli/term_t;Ljpl/fli/module_t;)Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_call( - JNIEnv *env, - jclass jProlog, - jobject jterm, - jobject jmodule // null is OK - ) - { - term_t term; - module_t module; - - return jpl_ensure_pvm_init(env) - && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL - && ( getPointerValue(env,jmodule,(pointer*)&module) , TRUE ) // if jmodule is null then module = NULL - && PL_call(term,module) // assumes module == NULL is OK [ISSUE] - ; - } - - -//=== from "5.6.9 Prolog exceptions in foreign code" ============================================== - -// not yet mapped: -// raise_exception() -// throw() - -/* - * Class: jpl_fli_PL - * Method: exception - * Signature: (Ljpl/fli/qid_t;)Ljpl/fli/term_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_exception( - JNIEnv *env, - jclass jProlog, - jobject jqid - ) - { - qid_t qid; - term_t term; - jobject term_t; // return value - - DEBUG(1, Sdprintf( ">exception(jqid=%lu)\n", (long)jqid)); - return ( jpl_ensure_pvm_init(env) - && ( DEBUG(1, Sdprintf( " ok: jpl_ensure_pvm_init(env)\n")), TRUE ) - // && jqid != NULL // redundant - && ( DEBUG(1, Sdprintf( " ok: jqid != NULL\n")), TRUE ) - && getLongValue(env,jqid,(long*)&qid) // checks that jqid isn't null - && ( DEBUG(1, Sdprintf( " ok: getLongValue(env,jqid,(long*)&qid)\n")), TRUE ) - && ( (term=PL_exception(qid)) , TRUE ) // we'll build a term_t object regardless - && ( DEBUG(1, Spdrintf(" ok: ( (term=PL_exception(qid)), TRUE)\n")), TRUE ) - && (term_t=(*env)->AllocObject(env,jTermT_c)) != NULL - && ( DEBUG(1, Sdprintf( " ok: (term_t=(*env)->AllocObject(env,jTermT_c)) != NULL\n")), TRUE ) - && setLongValue(env,term_t,(long)term) - && ( DEBUG(1, Sdprintf( " ok: setLongValue(env,term_t,(long)term)\n")), TRUE ) - ? ( - DEBUG(1, Sdprintf(" =%lu\n",(long)term_t)), - term_t - ) - : NULL // oughta diagnose failure? - ) - ; - } - - -//=== from "5.6.1 Miscellaneous" ================================================================== - -// not yet mapped (these might actually be useful as native methods, although they can be called via Prolog): -// record() -// reorded() -// erase() - -/* - * Class: jpl_fli_PL - * Method: compare - * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)I - */ -JNIEXPORT jint JNICALL // returns -1, 0 or 1 (or -2 for error) -Java_jpl_fli_Prolog_compare( - JNIEnv *env, - jclass jProlog, - jobject jterm1, - jobject jterm2 - ) - { - term_t term1; - term_t term2; - - DEBUG(1, Sdprintf( ">compare(term1=%lu,term2=%lu)\n", (long)jterm1, (long)jterm2)); - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jterm1,(long*)&term1) // checks jterm1 isn't null - && getLongValue(env,jterm2,(long*)&term2) // checks jterm2 isn't null - ) - { - DEBUG(1, Sdprintf( "> PL_compare( %u, %u)", term1, term2)); - return PL_compare(term1,term2); // returns -1, 0 or 1 - } - else - { - return -2; // oughta throw an exception... - } - } - - -/* - * Class: jpl_fli_PL - * Method: unregister_atom - * Signature: (Ljpl/fli/atom_t;)V - */ -JNIEXPORT void JNICALL -Java_jpl_fli_Prolog_unregister_1atom( - JNIEnv *env, - jclass jProlog, - jobject jatom - ) - { - atom_t atom; - - DEBUG(1, Sdprintf( ">unregister_atom(env=%lu,jProlog=%lu,jatom=%u)...\n", (long)env, (long)jProlog, (long)jatom)); - - if ( jpl_ensure_pvm_init(env) - && getLongValue(env,jatom,(long*)&atom) // checks that jatom isn't null - ) - { - PL_unregister_atom( atom); // void - DEBUG(1, Sdprintf( " ok: PL_unregister_atom(%lu)\n", (long)atom)); - } - } - - -/* - * Class: jpl_fli_PL - * Method: new_module - * Signature: (Ljpl/fli/atom_t;)Ljpl/fli/module_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_new_1module( - JNIEnv *env, - jclass jProlog, - jobject jatom - ) - { - atom_t atom; - module_t module; - jobject rval; - - return ( jpl_ensure_pvm_init(env) - && getLongValue(env,jatom,(long*)&atom) // checks that jatom isn't null - && ( (module=PL_new_module(atom)) , TRUE ) - && (rval=(*env)->AllocObject(env,jModuleT_c)) != NULL - && setPointerValue(env,rval,(pointer)module) - ? rval - : NULL // oughta warn of failure? - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: action_abort - * Signature: ()I - */ -JNIEXPORT int JNICALL -Java_jpl_fli_Prolog_action_1abort( - JNIEnv *env, - jclass jProlog - ) - { - - if ( jpl_ensure_pvm_init(env) ) - { - return PL_action(PL_ACTION_ABORT); - } - else - { - return -2; // oughta throw exception? - } - } - - -//=== JPL's Prolog engine pool and thread management =============================================== - -/* - * Class: jpl_fli_PL - * Method: thread_self - * Signature: ()I - */ -JNIEXPORT jint JNICALL -Java_jpl_fli_Prolog_thread_1self( - JNIEnv *env, - jclass jProlog - ) - { - - if ( jpl_ensure_pvm_init(env) ) - { - return PL_thread_self(); - } - else - { - return -2; - } - } - - -static int -create_pool_engines() - { - int i; - - DEBUG(1, Sdprintf( "JPL creating engine pool:\n")); - if ( (engines=malloc(sizeof(PL_engine_t)*JPL_MAX_POOL_ENGINES)) == NULL ) - { - return -1; /* malloc failed */ - } - engines_allocated = JPL_MAX_POOL_ENGINES; - memset(engines, 0, sizeof(PL_engine_t)*engines_allocated); - - DEBUG(1, Sdprintf( "JPL stashing default engine as [0]\n")); - PL_set_engine( PL_ENGINE_CURRENT, &engines[0]); - - DEBUG(1, Sdprintf( "JPL detaching default engine\n")); - // PL_set_engine( NULL, NULL); - - for ( i=1 ; iAllocObject(env,jEngineT_c)) != NULL - && setPointerValue(env,rval,(pointer)engines[i]) - ? rval - : NULL - ); - } - if ( rc != PL_ENGINE_INUSE ) - { - DEBUG(1, Sdprintf( "JPL PL_set_engine fails with %d\n", rc)); - pthread_mutex_unlock( &engines_mutex); - return NULL; // bad engine status: oughta throw exception - } - } - - for ( i=0 ; i 0 ) - { DEBUG(1, Sdprintf("JPL releasing engine[%d]=%p\n", i, e)); - PL_set_engine(NULL, NULL); - pthread_cond_signal(&engines_cond); // alert waiters - } - return i; - } - else - { - return -2; - } - } - - -/* - * Class: jpl_fli_PL - * Method: current_engine_is_pool - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL -Java_jpl_fli_Prolog_current_1engine_1is_1pool( - JNIEnv *env, - jclass jProlog - ) - { - - if ( jpl_ensure_pvm_init(env) ) - { - return current_pool_engine() >= 0; - } - else - { - return FALSE; // libpl could not be initialised: oughta throw exception - } - } - - -/* - * Class: jpl_fli_PL - * Method: current_engine - * Signature: ()Ljpl/fli/engine_t; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_current_1engine( - JNIEnv *env, - jclass jProlog - ) - { - PL_engine_t engine; - jobject rval; - - return ( jpl_ensure_pvm_init(env) - && PL_thread_self() != -1 - && ( current_pool_engine_handle(&engine) , TRUE ) - && (rval=(*env)->AllocObject(env,jEngineT_c)) != NULL - && setPointerValue(env,rval,(pointer)engine) - ? rval - : NULL - ) - ; - } - - -/* - * Class: jpl_fli_PL - * Method: get_c_lib_version - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jobject JNICALL -Java_jpl_fli_Prolog_get_1c_1lib_1version( - JNIEnv *env, - jclass jProlog - ) - { - - return (*env)->NewStringUTF(env,JPL_C_LIB_VERSION); - } - - -//=== end of jpl.c ================================================================================= - diff --git a/Jpl/src/makefile b/Jpl/src/makefile deleted file mode 100755 index 8abaea6fb2..0000000000 --- a/Jpl/src/makefile +++ /dev/null @@ -1,83 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../makefile.env -include ../../makefile.jni -include ../../makefile.optimizer - -INCLUDEFLAGS := -I. $(JNIINCLUDE) $(PLINCLUDEFLAGS) -I$(INCLUDEDIR) - - - -CCOBJECTS := $(JPL_LIB)/jpl.o -OBJECTS := $(CCOBJECTS) -ifeq ($(platform),win32) - DEF += jpl.def - OBJECTS += $(DEF) -endif - -JPLDLL := $(OPTDIR)/$(DLLPREF)jpl.$(JNI_DLLEXT) - -LD := g++ - -# Some optional switches used for providing a prolog -# predicate which maximizes the entropy. For details -# refer to "SecondoPL.cpp" and the subdirectory "Optimizer/Entropy" - -.PHONY: all -all: compile build - -.PHONY:compile -compile: $(OBJECTS) - -.PHONY:build -build: $(JPLDLL) - - -ifneq (, $(filter 1.6 1.7 1.8,$(JAVAVER))) - INITDEF := -DJDK1_1InitArgs=JavaVMInitArgs -endif - - -$(JPL_LIB)/jpl.o: $(JPLVER)/jpl.c - $(CC) -c -fPIC -g -o $@ $(INCLUDEFLAGS) $(INITDEF) $< - - -LINK_FLAGS := $(JNI_CCFLAGS) $(PLLDFLAGS) $(JPLDEF) -L$(SECONDO_BUILD_DIR)/lib -lrt - -ifeq ($(platform),win32) -$(JPLDLL): $(CCOBJECTS) - $(CC) $(DLLFLAGS) -Wl,-soname,jpl.$(JNI_DLLEXT) -o $@ \ - $^ $(LINK_FLAGS) jpl.def - -jpl.def: $(JPL_LIB)/jpl.o - dlltool -z $@.tmp $^ - sed -e "s#\(.*\)@\(.*\)@.*#\1 = \1@\2#g" $@.tmp > $@ - rm $@.tmp - -else -$(JPLDLL): $(CCOBJECTS) - $(LD) $(DLLFLAGS) $(EXEFLAGS) $(LDFLAGS) -o $@ $^ $(LINK_FLAGS) - - -endif - -.PHONY:clean -clean: - rm -f $(OBJECTS) $(JPLDLL) diff --git a/OptParser/OptSecUtils.cpp b/OptParser/OptSecUtils.cpp index dd6ac78603..0714cb1e40 100644 --- a/OptParser/OptSecUtils.cpp +++ b/OptParser/OptSecUtils.cpp @@ -45,6 +45,7 @@ is in kind data). At this place these checks are not nessecary. #include "SecondoInterface.h" #include "SecondoInterfaceTTY.h" #include "OptSecUtils.h" +#include "SQLLanguage.h" #include #include @@ -133,7 +134,7 @@ bool isDatabaseOpen(string& name, string& errorMsg) int errorCode = 0; int errorPos = 0; - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); @@ -433,7 +434,7 @@ bool isObject(const string& name, string& realName, ListExpr& type) int errorPos = 0; string errorMsg; // query the database for every object in the database and test if it - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); @@ -569,7 +570,7 @@ bool isValidID(const string& id) int errorCode = 0; int errorPos = 0; string errorMsg; - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); @@ -612,7 +613,7 @@ bool checkKind(const string& type, const string& kind) int errorCode = 0; int errorPos = 0; string errorMsg; - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); @@ -655,7 +656,7 @@ void getDatabaseObjectNames(set& names) int errorCode = 0; int errorPos = 0; string errorMsg; - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); @@ -712,7 +713,7 @@ bool checkOperator(string op, list& parameters) int errorCode = 0; int errorPos = 0; string errorMsg; - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); @@ -753,7 +754,7 @@ string getOperatorType(string operatorname, list& parameters) int errorCode = 0; int errorPos = 0; string errorMsg; - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); @@ -801,7 +802,7 @@ string getAttributeType(string attribute, string relation) int errorCode = 0; int errorPos = 0; string errorMsg; - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); @@ -858,7 +859,7 @@ bool isOperator(string operatorname) int errorCode = 0; int errorPos = 0; string errorMsg; - si->Secondo(command, plnl->TheEmptyList(), 1, // command level + si->Secondo(command, plnl->TheEmptyList(), CMD_LEVEL_TEXT, true, // command as text false, // result as text result1, errorCode, errorPos, errorMsg); diff --git a/OptParser/OptTest/30/OptTest.java b/OptParser/OptTest/30/OptTest.java deleted file mode 100755 index b9feb45af2..0000000000 --- a/OptParser/OptTest/30/OptTest.java +++ /dev/null @@ -1,973 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import java.io.*; -import java.net.*; -import java.util.*; - -import jpl.JPL; -import jpl.Atom; -import jpl.Query; -import jpl.Term; -import jpl.Variable; -import jpl.fli.*; -import jpl.Compound; -import jpl.Util; -import java.nio.charset.Charset; -import java.util.SortedMap; - -public class OptTest { - - static { - System.loadLibrary("jpl"); - System.loadLibrary("regOptTest"); - } - - public static native int registerSecondo(); - - private String openedDatabase = ""; - private String OS_pl_encoding = null; - - static final int UNDEFINED = 0; - static final int SETUP = 1; - static final int TESTCASE = 2; - static final int TEARDOWN = 3; - - // multiline commands - static final int APPENDTOCOMMAND = 4; - - // special states for testcases - static final int AWAITINGYIELD = 1; - static final int AWAITINGCOMMAND = 2; - - static final int NEXTCOMMAND = 5; - - // flags for result comparison - static final int NOCOMPARE = 2; - static final int STRINGCOMPARE = 3; - static final int SQLRESULTCOMPARE = 4; - static final int OPTCOMPARE = 5; - - String resultfilename = "result.log"; - String auxiliarydest = "../../Optimizer/auxiliary"; - String calloptimizerdest = "../../Optimizer/calloptimizer"; - - // globale Variables to have mutliple returnvalues - String Solution = ""; - Hashtable[] solutions; - String summary = "\n\nThe result of the testfile : "; - - /* - ~parseTestfile~ takes a filename String which should be a testfile. It is opened - and processes it line - by line. - - */ - - private boolean parseTestfile(String testfilename) { - summary += testfilename; - summary += "\nThe following checks failed : \n"; - String testresults = ""; - String yield = ""; - String testfile = readTestfile(testfilename); - if (testfile.isEmpty()) { - System.out - .println("Error : Testfile " + testfilename + " is empty"); - return false; - } - - // split does remove emptylines - String linebuffer[] = testfile.split("[\\r\\n]+"); - int numberoflines = linebuffer.length; - - System.out.println("Parsing " + numberoflines + " lines"); - int state = UNDEFINED; - int testcasestate = UNDEFINED; - int setupstate = UNDEFINED; - String currentline = ""; - String optcommand = ""; - String testcasename = ""; - int yieldflag = 0; - - for (int lineno = 0; lineno < numberoflines; lineno++) { - currentline = linebuffer[lineno]; - // filter out comments - if (currentline.startsWith("# ") || currentline.equals("#") - || currentline.trim().isEmpty()) { - // System.out.println("ignoring Comment"); - } else { - switch (state) { - case UNDEFINED: - if (currentline.startsWith("#setup")) { - state = SETUP; - if (currentline.trim().length() > 6) { - String testfilecomment = currentline.substring(6); - if (testfilecomment.length() > 0) { - System.out.println("Testfile name : " - + testfilename); - System.out.println("Testfile description : " - + testfilecomment.trim().substring( - testfilecomment.indexOf(" "))); - } - } - } else { - System.out - .println("Error: Expected #setup directive here"); - return false; - } - break; - case SETUP: - if (currentline.startsWith("#testcase")) { - //System.out.println("INFO : changing state to TESTCASE"); - state = TESTCASE; - testcasestate = AWAITINGYIELD; - System.out.println("Testcasename : " - + currentline.trim().substring( - currentline.indexOf(" "))); - testcasename = currentline.substring(currentline - .indexOf(" ")); - } else { - if (currentline.startsWith("#setup")) { - System.out - .println("Error : Already in SETUP state in line : " - + (lineno + 1)); - return false; - } - if (currentline.startsWith("#teardown")) { - System.out - .println("Error : Testfile changing from SETUP state to TEARDOWN is useless in line :" - + (lineno + 1) + "."); - return false; - } - switch (setupstate) { - case UNDEFINED: - if (currentline.endsWith(";")) { - optcommand += currentline.substring(0, - currentline.length() - 1); - if (!execute(optcommand)) { - System.out - .println("Error: setup failed while executing :\n" - + optcommand); - return false; - } - // reset optcommand - optcommand = ""; - } else { - optcommand += currentline + " "; - //System.out.println("INFO : changing state to APPENDTOCOMMAND"); - setupstate = APPENDTOCOMMAND; - } - break; - case APPENDTOCOMMAND: - if (currentline.endsWith(";")) { - optcommand += currentline; - if (!execute(optcommand)) { - System.out - .println("Error: setup failed while executing :\n" - + optcommand); - return false; - } - optcommand = ""; - break; - } else { - optcommand += currentline + " "; - } - } - } - break; - case TESTCASE: - /* - * example testcase: - * #testcase - * #yields |@filename - * - */ - - // catch statechange errors first - if (currentline.startsWith("#setup")) { - System.out - .println("Error : Testfile changing from TESTCASE state to SETUP which is not allowed in line : " - + (lineno + 1) + "."); - return false; - } - // again statebased - switch (testcasestate) { - case UNDEFINED: - System.out - .println("Error : testcasestate cannot be undefined in line " - + (lineno + 1) + "."); - return false; - case AWAITINGYIELD: - if (currentline.startsWith("#yields")) { - if (currentline.trim().length() > 7) { - // gets yieldflag - yield = currentline.substring(7).trim(); - if (yield.indexOf(" ") != -1) { - yieldflag = Integer.parseInt(yield - .substring(0, yield.indexOf(" "))); - yield = yield.substring(yield.indexOf(" "), - yield.length()).trim(); - // if there is yield make checks else pass - if (yield.length() > 0) { - if (yield.startsWith("@")) { - String yieldfilename = yield - .substring(1); - System.out.println("Reading file " - + yieldfilename); - yield = readTestfile(yieldfilename); - } - } - } else { - yieldflag = STRINGCOMPARE; - } - - } else { - yieldflag = NOCOMPARE; - yield = ""; - } - //System.out.println("INFO : changing teststate to AWAITINGCOMMAND"); - testcasestate = AWAITINGCOMMAND; - } else { - System.out - .println("Error : Missing #yields directive in line : " - + (lineno + 1) + "."); - return false; - } - break; - case AWAITINGCOMMAND: - if (currentline.startsWith("#")) { - System.out - .println("Error : Directives not allowed, awaiting optimizer command: " - + yield - + " in line :" - + (lineno + 1) + "."); - } - if (currentline.endsWith(";")) { - optcommand += currentline.substring(0, - currentline.length() - 1); - if (!executeTest(optcommand, yield, yieldflag)) { - System.out - .println("Error: Testcasecommand failed while executing :\n" - + optcommand); - return false; - } - optcommand = ""; - //System.out.println("INFO : changing teststate to NEXTCOMMAND"); - testcasestate = NEXTCOMMAND; - } else { - optcommand = currentline + " "; - //System.out.println("INFO : changing teststate to APPENDTOCOMMAND"); - testcasestate = APPENDTOCOMMAND; - } - break; - case APPENDTOCOMMAND: - if (currentline.startsWith("#")) { - System.out - .println("Error : Directives or comments are not allowed, was awaiting something to append to " - + optcommand - + " in line :" - + (lineno + 1) + "."); - } - if (currentline.endsWith(";")) { - optcommand += currentline.substring(0, - currentline.length() - 1); - if (!executeTest(optcommand, yield, yieldflag)) { - System.out - .println("Error: Testcasecommand failed while executing :\n" - + optcommand); - return false; - } - optcommand = ""; - //System.out.println("INFO : changing teststate to NEXTCOMMAND"); - testcasestate = NEXTCOMMAND; - } else { - optcommand += currentline + " "; - //System.out.println("INFO : changing teststate to APPENDTOCOMMAND"); - testcasestate = APPENDTOCOMMAND; - } - - break; - case NEXTCOMMAND: - optcommand = ""; - if (currentline.startsWith("#testcase")) { - testcasename = currentline.substring(currentline - .indexOf(" ")); - //System.out.println("Info : Changing state to TESTCASE."); - testcasestate = AWAITINGYIELD; - System.out.println(); - System.out.println("Testcasename : " - + currentline.trim().substring( - currentline.indexOf(" "))); - } else { - if (currentline.startsWith("#setup")) { - System.out - .println("Error : Already in SETUP state in line : " - + (lineno + 1)); - return false; - } - if (currentline.startsWith("#teardown")) { - //System.out.println("INFO : changing state to TEARDOWN"); - state = TEARDOWN; - } - } - break; - } - break; - case TEARDOWN: - if (currentline.startsWith("#setup")) { - System.out - .println("Error : Testfile changing from TEARDOWN state to SETUP which is not allowed in line : " - + lineno + "."); - return false; - } - if (currentline.startsWith("#testcase")) { - System.out - .println("Error : Testfile changing from TEARDOWN state to TESTCASE which is not allowed in line : " - + lineno + "."); - return false; - } - if (currentline.endsWith(";")) { - optcommand += currentline.substring(0, - currentline.length() - 1); - if (!execute(optcommand)) { - System.out - .println("Error: setup failed while executing :\n" - + optcommand); - return false; - } - optcommand = ""; - } else { - optcommand += currentline + " "; - } - break; - } - } - } - System.out.println(summary); - if (state == TESTCASE || state == TEARDOWN) - return true; - else { - switch (state) { - case SETUP: - System.out - .println("testfile execution ended in illegal state SETUP"); - return false; - case UNDEFINED: - System.out - .println("testfile execution ended in illegal state UNDEFINED"); - return false; - } - } - return false; - } - - /* - * yield from testfile or @resultfile - * - */ - private boolean executeTest(String optcommand, String yield, int flag) { - String result = ""; - if (execute(optcommand)) { - if (solutions.length >= 0) { - for (int i = 0; i < solutions.length; i++) { - Hashtable sol = solutions[i]; - if (sol.size() <= 0) { - } else { - Enumeration vars = solutions[i].keys(); - int varnum = 0; - while (vars.hasMoreElements()) { - Object v = vars.nextElement(); - result += (v + " = " + solutions[i].get(v)); - } - result += "\n"; - } - } - // if solution is "" then compare to Solution - if (result.equals("")) { - //System.out.println("SOLUTION WRITE OUTPUT:" + Solution); - if (!compareResult(Solution, yield, flag)) { - summary += "Results from " + optcommand - + " did not match!!!\n"; - } - } else { - //System.out.println("SOLUTION UNIFIED VARS:" + result); - if (!compareResult(result, yield, flag)) { - summary += "Results from " + optcommand - + " did not match!!!\n"; - } - } - } else { - // compare to false - if (compareResult("false", yield, flag)) { - summary += "Results from " + optcommand - + " did not match!!!\n"; - } - return true; - } - return true; - } else { - return false; - } - } - - private String readTestfile(String filename) { - String line; - try { - // Open the file that is the first - // command line parameter - FileInputStream fstream = new FileInputStream(filename); - DataInputStream in = new DataInputStream(fstream); - BufferedReader br = new BufferedReader(new InputStreamReader(in)); - - // read file - String file = ""; - while ((line = br.readLine()) != null) { - // Print the content on the console - // System.out.println(line); - file += line + "\n"; - } - // close file - in.close(); - // parsing the input as a whole takes place in a separate method - return file; - } catch (Exception e) { - System.out.println("could not open or read testfile : " + filename); - e.printStackTrace(); - return ""; - } - } - - private boolean compareResult(String result, String yield, int flag) { - /* - System.out.println("CompareResult flag : " + flag); - System.out.println("___________________________________________"); - System.out.println("Comparing result:\n" + result); - System.out.println("___________________________________________"); - System.out.println("Comparing yield:\n" + yield); - System.out.println("++++++++++++++++++++++++++++++++++++++++++++"); - */ - - //force default heavior if none was set - if (flag == UNDEFINED) { - flag = STRINGCOMPARE; - } - switch (flag) { - case NOCOMPARE: - return true; - // compare incoming results char by char - case STRINGCOMPARE: - if (result.trim().contentEquals(yield.trim())) { - System.out.println("Info : results do match"); - return true; - } else { - summary += "\n-------------- result : ---------------------\n"; - summary += result; - summary += "\n-------------- given yield : ---------------------\n"; - summary += yield; - System.out.println("Error : results do NOT match"); - return false; - } - /* in SQLRESULTCOMPARE yield is compared starting from - "Command succeeded, result:"*/ - case SQLRESULTCOMPARE: - if (result.length() > 0 && yield.length() > 0) { - if (result.indexOf("Command succeeded, result:") != -1) { - result = result.trim().substring( - result.indexOf("Command succeeded, result:")); - } - if (yield.indexOf("Command succeeded, result:") != -1) { - yield = yield.trim().substring( - yield.indexOf("Command succeeded, result:")); - } - if (result.trim().contentEquals(yield.trim())) { - System.out.println("Info : results do match"); - return true; - } else { - System.out.println("Error : results do NOT match"); - summary += "\n-------------- result : ---------------------\n"; - summary += result; - summary += "\n-------------- given yield : ---------------------\n"; - summary += yield; - return false; - } - } else { - System.out.println("Error : results do NOT match"); - return false; - } - - // in OPTCOMPARE all the selectivities are being removed - case OPTCOMPARE: - String pattern = "\\{.*\\}"; - result = result.replaceAll(pattern, ""); - yield = result.replaceAll(pattern, ""); - if (result.trim().contentEquals(yield.trim())) { - System.out.println("Info : results do match"); - return true; - } else { - System.out.println("Error : results do NOT match"); - summary += "\n-------------- result : ---------------------\n"; - summary += result; - summary += "\n-------------- given yield : ---------------------\n"; - summary += yield; - summary += "\n-----------------------------------------------------------\n"; - return false; - } - } - System.out.print("Error check failed somehow"); - return false; - } - - private boolean createTestfile(String filename) { - String commandlist = readTestfile(filename); - if (commandlist.isEmpty()) { - System.out.println("Error : Testfile " + commandlist + " is empty"); - return false; - } - // split does remove emptylines - String linebuffer[] = commandlist.split("[\\r\\n]+"); - int numberoflines = linebuffer.length; - String currentline = ""; - int state = SETUP; - - System.out.println("analyzing " + numberoflines + " lines from " - + filename); - - String resultfile = ""; - String testname = ""; - if (filename.indexOf(".") != -1) { - testname = filename.substring(0, filename.indexOf(".")); - } else { - testname = filename; - } - String testfile = "# This is a by OptTest automatically generated testfile.\n" - + "# It was generated from file: " - + filename - + "\n" - + "#setup " + testname + "\n"; - - int testno = 0; - String optcommand = ""; - String description = ""; - for (int lineno = 0; lineno < numberoflines; lineno++) { - currentline = linebuffer[lineno]; - if (currentline.startsWith("# ") || currentline.equals("#") - || currentline.trim().isEmpty()) { - // System.out.println("ignoring Comment"); - } else { - switch (state) { - case SETUP: - if (currentline.trim().startsWith("#testcase")) { - state = TESTCASE; - //System.out.println("changing state to TESTCASE"); - } else { - if (currentline.endsWith(";")) { - optcommand += currentline.substring(0, - currentline.length() - 1); - if (execute(optcommand)) { - //DisplaySolutions(); - testfile += optcommand + ";\n"; - optcommand = ""; - } else { - System.out - .println("Error : setup section failed due to error "); - return false; - } - } else { - optcommand += currentline + " "; - } - } - break; - case TESTCASE: - if (currentline.startsWith("#teardown")) { - testfile += "#teardown\n"; - state = TEARDOWN; - } else { - if (currentline.endsWith(";")) { - optcommand += currentline.substring(0, - currentline.length() - 1) - + "\n"; - if (execute(optcommand)) { - resultfile = ""; - testno++; - testfile += "#testcase No" + testno + " " - + description + "\n"; - - String result = ""; - if (solutions.length > 0) { - for (int i = 0; i < solutions.length; i++) { - Hashtable sol = solutions[i]; - if (sol.size() <= 0) { - - } else { - Enumeration vars = solutions[i] - .keys(); - int varnum = 0; - while (vars.hasMoreElements()) { - Object v = vars.nextElement(); - result += (v + " = " + solutions[i] - .get(v)); - } - result += "\n"; - } - - } - if (result.equals("")) { - result = Solution; - } else { - System.out.println("solutions : " - + result); - } - - int comparemode = STRINGCOMPARE; - if (optcommand.trim().startsWith("sql select")) { - comparemode = SQLRESULTCOMPARE; - } - if (optcommand.trim() - .startsWith("optimize")) { - comparemode = OPTCOMPARE; - } - if (result.length() > 70) { - resultfile = result; - String rfilename = testname + "_No" - + testno + ".result"; - // testcase distinction - - testfile += "#yields " + comparemode - + " @" + rfilename + "\n"; - try { - FileWriter rstream = new FileWriter( - rfilename); - BufferedWriter rout = new BufferedWriter( - rstream); - rout.write(resultfile); - //Close the output stream - rout.close(); - } catch (IOException e) { - - } - - } else { - testfile += "#yields " + comparemode - + " " + result; - } - - } else { - testfile += "#yields false\n"; - } - testfile += optcommand.substring(0, - optcommand.length() - 1) - + ";\n\n"; - optcommand = ""; - description = ""; - - } else { - System.out - .println("Error : creating testfile failed while executing : " - + optcommand); - return false; - } - - } else { - if (currentline.startsWith("% ") - || currentline.startsWith("# ")) { - testfile += "# " - + currentline.substring(1).trim() - + "\n"; - } else { - optcommand += currentline + "\n"; - } - } - } - break; - case TEARDOWN: - if (currentline.endsWith(";")) { - optcommand += currentline.substring(0, - currentline.length() - 1); - if (execute(optcommand)) { - //DisplaySolutions(); - testfile += optcommand + ";\n"; - optcommand = ""; - } else { - System.out - .println("Error : setup section failed due to error "); - return false; - } - } else { - optcommand += currentline + " "; - } - break; - } - } - } - try { - String tfilename = filename.substring(0, filename.indexOf(".")) - + ".test"; - FileWriter tstream = new FileWriter(tfilename); - - BufferedWriter tout = new BufferedWriter(tstream); - tout.write(testfile); - //Close the output stream - tout.close(); - return true; - } catch (IOException e) { - System.out.println(e.getMessage()); - return false; - } - - } - - /** - * init prolog register the secondo predicate loads the optimizer prolog - * code - */ - private boolean initialize() { - // later here is to invoke the init function which - // registers the Secondo(command,Result) predicate to prolog - if (registerSecondo() != 0) { - System.err.println("error in registering the secondo predicate "); - return false; - } - // cout.println("registerSecondo successful"); - try { - - String[] plargs = { "-L256M", "-G256M" }; - boolean ok = JPL.init(plargs); - - // VTA - 18.09.2006 - // I added this piece of code in order to run with newer versions - // of prolog. Without this code, the libraries (e.g. lists.pl) are - // not automatically loaded. It seems that something in our code - // (auxiliary.pl and calloptimizer.pl) prevents them to be - // automatically loaded. In order to solve this problem I added - // a call to 'member(x, [x]).' so that the libraries are loaded - // before running our scripts. - Term[] args = new Term[2]; - args[0] = new Atom("x"); - args[1] = jpl.Util.termArrayToList(new Term[] { new Atom("x") }); - Query q = new Query("member", args); - if (!q.hasSolution()) { - System.out.println("error in the member call'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom(auxiliarydest); - q = new Query("consult", args); - if (!q.hasSolution()) { - System.out.println("error in loading 'auxiliary.pl'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom(calloptimizerdest); - q = new Query("consult", args); - if (!q.hasSolution()) { - System.out.println("error in loading 'calloptimizer.pl'"); - return false; - } - - q = new Query("set_prolog_flag(debug_on_error, false)"); - if (!q.hasSolution()) { - System.out.println("error setting debug_on_error to false"); - return false; - } - return true; - } catch (Exception e) { - System.out.println("Exception in initialization " + e); - return false; - } - } - - /** - * analyzed the given string and extract the command and the argumentlist
    - * then the given command is executed all Solutions are stored into the - * Vector Solution - */ - private boolean execute(String command) { - if (Solution != "") { - Solution = ""; - } - if (solutions != null) { - solutions = null; - } - command = command.trim(); - System.out.println("Optimizer command: " + command); - command = "tell('" + resultfilename + "')," + command + ",told"; - command = encode(command); - //System.out.println("Command to execute : " + command); - try { - Query pl_query = new Query(command); - if (pl_query == null) { - System.out.println("Error : error in parsing command: "); - return false; - } - solutions = pl_query.allSolutions(); - /* debug */ - //System.out.println("Number of solutions : " + solutions.length); - //System.out.println(""); - /* end debug */ - if (solutions.length > 0) { - Solution = readTestfile(resultfilename); - //System.out.println("File Solution : " + Solution); - return true; - } else { - Solution = "false"; - return true; - } - } catch (Exception e) { - return false; - } - } - - private void DisplaySolutions() { - System.out.println("Display Solutions"); - System.out.println("Solution : " + Solution); - String result = ""; - for (int i = 0; i > solutions.length; i++) { - Hashtable solution = solutions[i]; - Enumeration vars = solution.keys(); - int varnum = 0; - while (vars.hasMoreElements()) { - Object v = vars.nextElement(); - result += (v + " = " + solution.get(v)); - } - } - System.out.println("+++++++++++++++++"); - System.out.println("result :" + result); - System.out.println("?????????????????"); - } - - /* - private String readFile(String file) { - try { - BufferedReader reader = new BufferedReader(new FileReader(file)); - String line = null; - StringBuilder stringBuilder = new StringBuilder(); - String ls = System.getProperty("line.separator"); - - while ((line = reader.readLine()) != null) { - stringBuilder.append(line); - stringBuilder.append(ls); - } - return stringBuilder.toString(); - - } catch (IOException e) { - System.out.println(e.getStackTrace()); - System.out.println("Could not open or read " + file); - return ""; - } - } - */ - /** Converts a string into OS_pl_encoding **/ - private String encode(String src) { - if (OS_pl_encoding == null) { - return src; - } - try { - byte[] encodedBytes = src.getBytes(OS_pl_encoding); - return new String(encodedBytes, "UTF-8"); - } catch (Exception e) { - System.err.println("Used encoding not supported\n" + e); - return src; - } - } - - /** Converts a string from OS_pl_encoding **/ - private String decode(String src) { - if (OS_pl_encoding == null) { - return src; - } - try { - byte[] encodedBytes = src.getBytes("UTF-8"); - return new String(encodedBytes, OS_pl_encoding); - } catch (Exception e) { - System.err.println("Used encoding not supported\n" + e); - return src; - } - } - - public static void main(String[] args) { - OptTest opttest = new OptTest(); - if (args.length == 1) { - try { - Class.forName("jpl.fli.Prolog"); // ensure to load the jpl library - } catch (Exception e) { - System.err.println("loading prolog class failed"); - System.exit(1); - } - - if (!opttest.initialize()) { - System.out.println("initialization failed"); - System.exit(1); - } - System.out.println("Testfile : " + args[0]); - System.out.println(opttest.parseTestfile(args[0])); - - /* - opttest.execute("current_prolog_flag(debug_on_error, X)"); - opttest.execute("set_prolog_flag(debug_on_error, false)"); - opttest.execute("current_prolog_flag(debug_on_error, X)"); - - opttest.execute("open database opt"); - //opttest.execute("tell('" + opttest.resultfilename + "')"); - String command = "sqdsdxl select count(*) from orte"; - opttest.execute("tell('" + opttest.resultfilename + "')," + command - + ",told"); - - command = "sql select * from orte"; - opttest.execute("tell('" + opttest.resultfilename + "')," + command + ",told"); - command = "sql select bevt from orte"; - opttest.execute("tell('" + opttest.resultfilename + "')," + command + ",told"); - command = "optimize(select bevt from orte where [bevt < 100 ,bevt > 50])"; - opttest.execute("tell('" + opttest.resultfilename + "')," + command + ",told"); - */ - //opttest.execute("sql select * from plz"); - //opttest.execute("told"); - } else { - if (args.length == 2) { - System.out.println("args.length == 2, arg[1] =" + args[1]); - if (args[0].equals("-c")) { - try { - Class.forName("jpl.fli.Prolog"); // ensure to load the jpl library - } catch (Exception e) { - System.err.println("loading prolog class failed"); - System.exit(1); - } - - if (!opttest.initialize()) { - System.out.println("initialization failed"); - System.exit(1); - } - System.out.println("Creating testfile from " + args[1]); - if (opttest.createTestfile(args[1])) { - System.out.println("creating testfile successful"); - } else { - System.out.println("creating testfile failed"); - } - - } - } else { - System.out - .println("OptTest \n Usage : \n " - + "execute testfile : \n OptTest \n" - + "create testfile from commands: \n OptTest -c \n"); - } - } - } -} diff --git a/OptParser/OptTest/30/berlintest.tspec b/OptParser/OptTest/30/berlintest.tspec deleted file mode 100644 index 27176396af..0000000000 --- a/OptParser/OptTest/30/berlintest.tspec +++ /dev/null @@ -1,62 +0,0 @@ -open database berlintest; -#testcase -% Example: spatial predicate intersects (database berlintest) -sql select [s:name as sname, w:name as wname] -from [strassen as s, wstrassen as w] -where [s:geodata intersects w:geodata]; - -% Example: spatio temporal predicate (database berlintest) -sql select [s:name as sname] -from [strassen as s] -where [train1 passes s:geodata]; - -% Example: temporal predicate (database berlintest) -sql select [t:id as id] -from [trains as t] -where [t:trip present six30]; - -% Example: spatio temporal predicate (database berlintest) -sql select [s:name as sname] -from [strassen as s] -where [(train1 atperiods deftime(train5)) passes s:geodata]; - -% Example: spatio temporal predicate (database berlintest) -sql select [s:name as sname] -from [trains as t, strassen as s] -where [(t:trip atperiods deftime(train5)) passes s:geodata]; - -% Example: distance query, no predicate (database berlintest) -sql select * -from kinos -orderby distance(geodata, mehringdamm) first 5; - -% Example: distance query, selection predicate (database berlintest) -sql select * -from ubahnhof -where typ = "Zone A" -orderby distance(geodata, alexanderplatz) first 5; - -% Example: distance query, rtree, no predicate (database berlintest) -sql select * -from strassen -orderby distance(geodata, mehringdamm) first 5; - -% Example: distance query, rtree, selection predicate (database berlintest) -sql select * -from strassen -where typ starts "Hauptstra" -orderby distance(geodata, alexanderplatz) first 5; - -% Example: distance query, rtree, join predicate (database berlintest) -sql select * -from [strassen as s, sbahnhof as b] -where s:name = b:name -orderby distance(s:geodata, mehringdamm) first 5; - -% Example: spatio temporal pattern query (database berlintest) -sql select count(*) -from trains -where pattern([trip inside msnow as preda, - distance(trip, mehringdamm)<10.0 as predb], - [stconstraint("preda","predb",vec("aabb"))]); - diff --git a/OptParser/OptTest/30/dbopt.tspec b/OptParser/OptTest/30/dbopt.tspec deleted file mode 100644 index d46a353d63..0000000000 --- a/OptParser/OptTest/30/dbopt.tspec +++ /dev/null @@ -1,22 +0,0 @@ -open database opt; -#testcase -sql select count(*) - from [staedte as s, plz as p] - where [p:ort = s:sname, p:plz > 40000, (p:plz mod 5) = 0]; - -optimize(select count(*) from staedte,Plan, Cost); - -sql select count(*) - from staedte - where bev > 500000; - -optimize(select count(*) - from [staedte as s, plz as p] - where [p:ort = s:sname, p:plz > 40000, (p:plz mod 5) = 0],Plan, Cost); - -# sql select * -# from [staedte as s, plz as p] -# where [p:ort = s:sname, p:plz > 40000, (p:plz mod 5) = 0]; - -#teardown -secondo('close database',R). diff --git a/OptParser/OptTest/30/dmltest.tspec b/OptParser/OptTest/30/dmltest.tspec deleted file mode 100644 index cd0aedf64a..0000000000 --- a/OptParser/OptTest/30/dmltest.tspec +++ /dev/null @@ -1,138 +0,0 @@ -secondo('drop database dmltest'); -secondo('create database dmltest'); -secondo('close database'); -open database dmltest; -#testcase -% create table with standard datatypes -sql create table standardtypes columns [zeichenkette:string, ganzzahl:int, fliesszahl:real, wahrheitswert:bool]; -% check if table standard types exists -sql select * from standardtypes; - -% insert into table standardtypes values -sql insert into standardtypes values ["Hallo", 1 , 2.3, false]; -% check dml result -sql select * from standardtypes; - -% update single column string -sql update standardtypes set zeichenkette = "Welt"; -% check dml result -sql select * from standardtypes; - -% update single column int -sql update standardtypes set ganzzahl = 2; -% check dml result -sql select * from standardtypes; - -% update single column real -sql update standardtypes set fliesszahl = 0.6; -% check dml result -sql select * from standardtypes; - -% update single column boolean -sql update standardtypes set wahrheitswert = true; -% check dml result -sql select * from standardtypes; - -% update all columns not in order -sql update standardtypes set [ganzzahl = 9, fliesszahl=0.3, zeichenkette="SECONDO", wahrheitswert=false]; -% check dml result -sql select * from standardtypes; - -% insert into table standardtypes values -sql insert into standardtypes values ["Hagen", 2 , 7.3, true]; -% check dml result -sql select * from standardtypes; - -% update all values with predicate -sql update standardtypes set [zeichenkette = "Dortmund", ganzzahl = 4, fliesszahl=6.6] where zeichenkette = "Hagen"; -% check dml result -sql select * from standardtypes; - -% update single column string with predicate -sql update standardtypes set zeichenkette = "Welt" where zeichenkette = "SECONDO"; -% check dml result -sql select * from standardtypes; - -% update single column int with predicate -sql update standardtypes set ganzzahl = 2 where ganzzahl = 9; -% check dml result -sql select * from standardtypes; - -% update single column real with predicate -sql update standardtypes set fliesszahl=0.6 where fliesszahl = 0.3; -% check dml result -sql select * from standardtypes; - -% update single column boolean -sql update standardtypes set wahrheitswert = false where wahrheitswert not 'false'; -% check dml result -sql select * from standardtypes; - -% delete row with predicate -sql delete from standardtypes where fliesszahl = 0.3; -% check dml result -sql select * from standardtypes; - -% delete all rows -sql delete from standardtypes; -% check dml result -sql select * from standardtypes; - -% drop the table standardtypes -sql drop table standardtypes; - -% drop the table standardtypes -showDatabaseSchema; - -% prepare table for let and index tests -sql create table testindex columns [zeichenkette:string, ganzzahl:int]; - -sql insert into testindex values ["The", 1]; -sql insert into testindex values ["goal", 2]; -sql insert into testindex values ["of", 3]; -sql insert into testindex values ["SECONDO", 4]; -sql insert into testindex values ["is", 5]; -sql insert into testindex values ["to", 6]; -sql insert into testindex values ["provide", 7]; -sql insert into testindex values ["a", 8]; -sql insert into testindex values ["generic", 9]; -sql insert into testindex values ["database", 10]; -sql insert into testindex values ["system", 11]; -sql insert into testindex values ["frame", 12]; -sql insert into testindex values ["that", 13]; -sql insert into testindex values ["can", 14]; -sql insert into testindex values ["be", 15]; -sql insert into testindex values ["filled", 16]; -sql insert into testindex values ["with", 17]; -sql insert into testindex values ["implementations", 18]; -sql insert into testindex values ["of", 19]; -sql insert into testindex values ["various", 20]; -sql insert into testindex values ["DBMS", 21]; -sql insert into testindex values ["data", 22]; -sql insert into testindex values ["models", 23]; - -% create standard index on -sql create index on testindex columns zeichenkette; - -% drop standard index on -sql drop index testindex_zeichenkette_btree; - -% create btree index on -sql create index on testindex columns zeichenkette indextype btree; -% drop btree index on -sql drop index testindex_zeichenkette_btree; - -% create standard index on -sql create index on testindex columns zeichenkette indextype hash; -% drop hash index on -sql drop index testindex_zeichenkette_hash; - -% create an object with let -let(testindex2,select * from testindex orderby ganzzahl desc); - -% create an object with hybrid let -let(testindex3,select * from testindex,'sortby[Ganzzahl desc] consume'); - -#teardown -# secondo('delete database dmltest'); - diff --git a/OptParser/OptTest/30/makefile b/OptParser/OptTest/30/makefile deleted file mode 100755 index 1443fe4339..0000000000 --- a/OptParser/OptTest/30/makefile +++ /dev/null @@ -1,44 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -######################################################################## -# -# SECONDO Makefile -# -######################################################################### - -include ../../../makefile.env - -ifdef JPL_JAR -CLASSPATH=$(JPL_JAR) -else -CLASSPATH=$(JPL_CLASSPATH) -endif - -OPT_TEST_DIR=$(SECONDO_BUILD_DIR)/OptParser/OptTest - -.PHONY:all -all: $(OPTDIR)/OptTest.class - -$(OPTDIR)/OptTest.class: OptTest.java - $(JAVAC) -classpath $(CLASSPATH) -d $(OPT_TEST_DIR) OptTest.java - -.PHONY:clean -clean: - rm -f $(OPT_TEST_DIR)/*.class diff --git a/OptParser/OptTest/30/optimize.tspec b/OptParser/OptTest/30/optimize.tspec deleted file mode 100644 index 304d95f4f4..0000000000 --- a/OptParser/OptTest/30/optimize.tspec +++ /dev/null @@ -1,148 +0,0 @@ -open database opt; -#testcase - -% %%%%%%%%% select %%%%%%%%%%% -% first simple star query -optimize(select * from ten,Plan, _); - -% simple one attribute element query -optimize(select bevt from orte,Plan, _); - -% multiple attributes element query -optimize(select [bevt,ort,kennzeichen,vorwahl] from orte,Plan, _); - -% aliased attributes element query -optimize(select bevt as bevoelkerung from orte,Plan, _); - -% alias, multiple attributes -optimize(select [bevt as bevoelkerung, ort as stadt] from orte first 5,Plan, _); - -% alias on relation -optimize(select [o:bevt, o:ort] from orte as o first 5,Plan, _); - -% alias on everything -optimize(select [o:bevt as bevoelkerung, o:ort as stadt] from orte as o,Plan, _); - -% distinct clause -optimize(select distinct kennzeichen from orte,Plan, _); - -% distinct all clause -optimize(select all kennzeichen from orte,Plan, _); -% %%%%%%%%% operators %%%%%%%%%%% -% count(*) -optimize(select count(*) from ten,Plan, _); - -% sum operator -optimize(select sum(no) from ten,Plan, _); - -% min operator -optimize(select min(no) from ten,Plan, _); - -% max operator -optimize(select max(no) from ten,Plan, _); - -% avg operator -optimize(select avg(no) from ten,Plan, _); - -% unary now operator -optimize(select [now as time] from ten,Plan, _); - -% nested operators -optimize(select [randint(5+3) as zufallszahl] from ten,Plan, _); - -% addition expression -optimize(select [1+1 as sum] from ten,Plan, _); - -% addition expression -optimize(select [no + 1 as sum] from ten,Plan, _); - -% addition expression -optimize(select [no + 1 as sum] from ten,Plan, _); - -% subtraction expression -optimize(select [1-1 as sum] from ten,Plan, _); - -% subtraction addition expression -optimize(select [-3 + no as sum] from ten,Plan, _); - -% multiplication expression -optimize(select [3 * -5 as sum] from ten,Plan, _); - -% multi expression query -optimize(select [3 + 6 as sum, 4 * 7 as product, no] from ten,Plan, _); - -% mixture of aliased and non aliased attributes -optimize(select [bevt, 1+1 as t] from orte,Plan, _); - -% mixture of alias, unaliased and expressions -optimize(select distinct [kennzeichen, ort, 12+bevt as d,bevt] from orte,Plan, _); - -% mixture of distinct and expressions and alias and unaliased elements -optimize(select distinct [12+ (-13) as t,bevt] from orte,Plan, _); - -% %%%%%%%%% fromclause %%%%%%%%%%% -% simple multirelation cross join -optimize(select * from [ten as a, ten as b],Plan, _); - -% simple multirelation cross self join one aliased one not -optimize(select * from [ten, ten as b],Plan, _); - -% %%%%%%%%% fromclause %%%%%%%%%%% -% simple where clause with one simple predicate -optimize(select * from ten where no < 4,Plan, _); - -% where clause with expression in predicate -optimize(select * from ten where no+1 < 4,Plan, _); - -% where clause with expression in predicate -optimize(select * from ten where no+1 < 4-2,Plan, _); - -% where clause with twi expressions in predicate -optimize(select * from ten where no+1 < 4-2,Plan, _); - -% where clause with multiple predicates -optimize(select * from ten where [no < 6, no > 2],Plan, _); - -% where clause with multiple predicates -optimize(select * from ten where [no < 6, no > 2, no >1],Plan, _); - -% where clause with or operator and bracketed first order expression -optimize(select * from ten where [(no >5 and no > 6) or no < 2],Plan, _); - -% where clause with nested first order expression -optimize(select * from ten where [(no >5 and no > 6) or (no < 2 and no <3)],Plan, _); - -% where clause with nested first order expression -optimize(select * from ten where [(no >5 and no > 6) or no=4],Plan, _); - -% %%%%%%%%% groupby clause %%%%%%%%%%% -% simple groupby no where -optimize(select [kennzeichen, sum(bevt) as bevoelkerung ]from orte groupby kennzeichen,Plan, _); - -% empty groupby clause -optimize(select [min(plz) as minplz, - max(plz) as maxplz, - avg(plz) as avgplz, - count(distinct ort) as ortcnt] - from plz - groupby [],Plan, _); - -% %%%%%%%%% orderby clause %%%%%%%%%%% -% simple orderby query -optimize(select * from ten orderby no,Plan, _); - -% simple orderby query ascending order -optimize(select * from ten orderby no asc,Plan, _); - -% simple orderby query descending order -optimize(select * from ten orderby no desc,Plan, _); - -% %%%%%%%%% first clause %%%%%%%%%%% -% simple first query -optimize(select * from ten first 5,Plan, _); - -% simple last query -optimize(select * from ten last 5,Plan, _); - -#teardown -close database opt. diff --git a/OptParser/OptTest/30/optparse.tspec b/OptParser/OptTest/30/optparse.tspec deleted file mode 100644 index ccdd48aabb..0000000000 --- a/OptParser/OptTest/30/optparse.tspec +++ /dev/null @@ -1,126 +0,0 @@ -open database opt; -#testcase -% %%%%%% select queries working %%%%%%%% -% simple select -check_syntax('sql select * from orte',R); - -% simple one attribute element query -check_syntax('sql select bevt from orte',R); - -% multiple attributes element query -check_syntax('sql select [bevt,ort,kennzeichen,vorwahl] from orte',R); - -% aliased attributes element query -check_syntax('sql select bevt as bevoelkerung from orte',R); - -% alias, multiple attributes -check_syntax('sql select [bevt as bevoelkerung, ort as stadt] from orte first 5',R); - -% alias on relation -check_syntax('sql select [o:bevt, o:ort] from orte as o first 5',R); - -% alias on everything -check_syntax('sql select [o:bevt as bevoelkerung, o:ort as stadt] from orte as o',R); - -% distinct clause -check_syntax('sql select distinct kennzeichen from orte',R); - -% distinct all clause -check_syntax('sql select all kennzeichen from orte',R); - -% aliased attributes element query -check_syntax('sql select bevt as bevoelkerung from orte',R); - -% alias, multiple attributes -check_syntax('sql select [bevt as bevoelkerung, ort as stadt] from orte first 5',R); - -% alias on relation -check_syntax('sql select [o:bevt, o:ort] from orte as o first 5',R); - -% alias on everything -check_syntax('sql select [o:bevt as bevoelkerung, o:ort as stadt] from orte as o',R); - -% distinct clause -check_syntax('sql select distinct kennzeichen from orte',R); - -% distinct all clause -check_syntax('sql select all kennzeichen from orte',R); - -% %%%%%%%%% operators %%%%%%%%%%% -% count(*) -check_syntax('sql select count(*) from ten',R); - -% sum operator -check_syntax('sql select sum(no) from ten',R); - -% min operator -check_syntax('sql select min(no) from ten',R); - -% max operator -check_syntax('sql select max(no) from ten',R); - -% avg operator -check_syntax('sql select avg(no) from ten',R); - -% unary now operator -check_syntax('sql select [now as time] from ten',R); - -% nested operators -check_syntax('sql select [randint(5+3) as zufallszahl] from ten',R); - -% addition expression -check_syntax('sql select [1+1 as sum] from ten',R); - -% addition expression -check_syntax('sql select [no + 1 as sum] from ten',R); - -% addition expression -check_syntax('sql select [no + 1 as sum] from ten',R); - -% subtraction expression -check_syntax('sql select [1-1 as sum] from ten',R); - -% subtraction addition expression -check_syntax('sql select [-3 + no as sum] from ten',R); - -% multiplication expression -check_syntax('sql select [3 * -5 as sum] from ten',R); - -% multi expression query -check_syntax('sql select [3 + 6 as sum, 4 * 7 as product, no] from ten',R); - -% mixture of aliased and non aliased attributes -check_syntax('sql select [bevt, 1+1 as t] from orte',R); - -% mixture of alias, unaliased and expressions -check_syntax('sql select distinct [kennzeichen, ort, 12+bevt as d,bevt] from orte',R); - -% mixture of distinct and expressions and alias and unaliased elements -check_syntax('sql select distinct [12+ (-13) as t,bevt] from orte',R); - -% %%%%%% select queries with errors in them %%%%%%%% -% not existent attribute in list brackets -check_syntax('sql select [bev] from orte',R); - -% not existent attribute in list brackets -check_syntax('sql select bev from orte',R); - -% two not existent attribute -check_syntax('sql select [bev, ard] from orte',R); - -% mixture of existing and not existent attributes -check_syntax('sql select [bev, ard,bevt] from orte',R); - -% mixture of existing and not existent attributes and an expression -check_syntax('sql select [bev, ard,bevt, 1+4 as t] from orte',R); - -% missing prolog list brackets -check_syntax('sql select bevt, kennzeichen from orte',R); - -% missing close brackets -check_syntax('sql select [bevt, kennzeichen from orte',R); - -% missing close brackets -check_syntax('sql select bevt from orte where [bevt < 10',R); - - diff --git a/OptParser/OptTest/30/sqltest.tspec b/OptParser/OptTest/30/sqltest.tspec deleted file mode 100644 index f46f59d3fc..0000000000 --- a/OptParser/OptTest/30/sqltest.tspec +++ /dev/null @@ -1,155 +0,0 @@ -open database opt; -#testcase - -% %%%%%%%%% select %%%%%%%%%%% -% first simple star query -sql select * from ten; - -% simple one attribute element query -sql select bevt from orte; - -% multiple attributes element query -sql select [bevt,ort,kennzeichen,vorwahl] from orte; - -% aliased attributes element query -sql select bevt as bevoelkerung from orte; - -% alias, multiple attributes -sql select [bevt as bevoelkerung, ort as stadt] from orte first 5; - -% alias on relation -sql select [o:bevt, o:ort] from orte as o first 5; - -% alias on everything -sql select [o:bevt as bevoelkerung, o:ort as stadt] from orte as o; - -% distinct clause -sql select distinct kennzeichen from orte; - -% distinct all clause -sql select all kennzeichen from orte; -% %%%%%%%%% operators %%%%%%%%%%% -% count(*) -sql select count(*) from ten; - -% sum operator -sql select sum(no) from ten; - -% min operator -sql select min(no) from ten; - -% max operator -sql select max(no) from ten; - -% avg operator -sql select avg(no) from ten; - -% unary now operator -sql select [now as time] from ten; - -% nested operators -sql select [randint(5+3) as zufallszahl] from ten; - -% addition expression -sql select [1+1 as sum] from ten; - -% addition expression -sql select [no + 1 as sum] from ten; - -% addition expression -sql select [no + 1 as sum] from ten; - -% subtraction expression -sql select [1-1 as sum] from ten; - -% subtraction addition expression -sql select [-3 + no as sum] from ten; - -% multiplication expression -sql select [3 * -5 as sum] from ten; - -% multi expression query -sql select [3 + 6 as sum, 4 * 7 as product, no] from ten; - -% mixture of aliased and non aliased attributes -sql select [bevt, 1+1 as t] from orte; - -% mixture of alias, unaliased and expressions -sql select distinct [kennzeichen, ort, 12+bevt as d,bevt] from orte; - -% mixture of distinct and expressions and alias and unaliased elements -sql select distinct [12+ (-13) as t,bevt] from orte; - -% %%%%%%%%% fromclause %%%%%%%%%%% -% simple multirelation cross join -sql select * from [ten as a, ten as b]; - -% simple multirelation cross self join one aliased one not -sql select * from [ten, ten as b]; - -% %%%%%%%%% fromclause %%%%%%%%%%% -% simple where clause with one simple predicate -sql select * from ten where no < 4; - -% where clause with expression in predicate -sql select * from ten where no+1 < 4; - -% where clause with expression in predicate -sql select * from ten where no+1 < 4-2; - -% where clause with twi expressions in predicate -sql select * from ten where no+1 < 4-2; - -% where clause with multiple predicates -sql select * from ten where [no < 6, no > 2]; - -% where clause with multiple predicates -sql select * from ten where [no < 6, no > 2, no >1]; - -% where clause with or operator and bracketed first order expression -sql select * from ten where [(no >5 and no > 6) or no < 2]; - -% where clause with nested first order expression -sql select * from ten where [(no >5 and no > 6) or (no < 2 and no <3)]; - -% where clause with nested first order expression -sql select * from ten where [(no >5 and no > 6) or no=4]; - -% %%%%%%%%% groupby clause %%%%%%%%%%% -% simple groupby no where -sql select [kennzeichen, sum(bevt) as bevoelkerung ]from orte groupby kennzeichen; - -% empty groupby clause -sql select [min(plz) as minplz, - max(plz) as maxplz, - avg(plz) as avgplz, - count(distinct ort) as ortcnt] - from plz - groupby []; - -% %%%%%%%%% orderby clause %%%%%%%%%%% -% simple orderby query -sql select * from ten orderby no; - -% simple orderby query ascending order -sql select * from ten orderby no asc; - -% simple orderby query descending order -sql select * from ten orderby no desc; - -% %%%%%%%%% first clause %%%%%%%%%%% -% simple first query -sql select * from ten first 5; - -% simple last query -sql select * from ten last 5; - -% %%%%%%%%% not working = false != exeception %%%%%%%%%%% -% notworking select String -sql select "text" as t from ten; - -# % where clause with nested unbracketed first order expression -# % sql select * from ten where [no >5 and no > 6 or no=4]; - -#teardown -close database opt. diff --git a/OptParser/OptTest/createBerlintest b/OptParser/OptTest/createBerlintest deleted file mode 100755 index 67ef6ade70..0000000000 --- a/OptParser/OptTest/createBerlintest +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -cp 30/berlintest.tspec $HOME/secondo/OptParser/OptTest -cd $HOME/secondo/OptParser/OptTest -make -StartTest -c berlintest.tspec diff --git a/OptParser/OptTest/createDMLTest b/OptParser/OptTest/createDMLTest deleted file mode 100755 index 1be864a0a6..0000000000 --- a/OptParser/OptTest/createDMLTest +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -cp 30/dmltest.tspec $HOME/secondo/OptParser/OptTest -cd $HOME/secondo/OptParser/OptTest -make -StartTest -c dmltest.tspec diff --git a/OptParser/OptTest/createOptParseTest b/OptParser/OptTest/createOptParseTest deleted file mode 100755 index 378e440d6b..0000000000 --- a/OptParser/OptTest/createOptParseTest +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -cp 30/optparse.tspec /home/secondo/secondo/OptParser/OptTest -cd /home/secondo/secondo/OptParser/OptTest -make -StartTest -c optparse.tspec diff --git a/OptParser/OptTest/createOptimizerTest b/OptParser/OptTest/createOptimizerTest deleted file mode 100755 index 99fb0ffebe..0000000000 --- a/OptParser/OptTest/createOptimizerTest +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -cp 30/optimize.tspec /home/secondo/secondo/OptParser/OptTest -cd /home/secondo/secondo/OptParser/OptTest -make -StartTest -c optimize.tspec diff --git a/OptParser/OptTest/createSQLTest b/OptParser/OptTest/createSQLTest deleted file mode 100755 index 7c7e6859cd..0000000000 --- a/OptParser/OptTest/createSQLTest +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -cp makefile /home/secondo/secondo/OptParser/OptTest -cp regSecondo.c /home/secondo/secondo/OptParser/OptTest -cp StartTest /home/secondo/secondo/OptParser/OptTest -cp 30/OptTest.java /home/secondo/secondo/OptParser/OptTest/30 -cp 30/makefile /home/secondo/secondo/OptParser/OptTest/30 -cp 30/ParserFile.java /home/secondo/secondo/OptParser/OptTest/30 -cp 30/sqltest.tspec /home/secondo/secondo/OptParser/OptTest -cd /home/secondo/secondo/OptParser/OptTest -make -StartTest -c sqltest.tspec diff --git a/OptParser/OptTest/makefile b/OptParser/OptTest/makefile deleted file mode 100644 index 7df7449ff6..0000000000 --- a/OptParser/OptTest/makefile +++ /dev/null @@ -1,87 +0,0 @@ -#This file is part of SECONDO. -# -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. -# -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. -# -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -######################################################################## -# -# SECONDO Makefile -# -######################################################################### - -include ../../makefile.env -include ../../makefile.optimizer -include ../../makefile.jni - -OPTTESTDIR=$(SECONDO_BUILD_DIR)/OptParser/OptTest - -INCLUDEFLAGS := -I. $(JNIINCLUDE) $(PLINCLUDEFLAGS) -I$(INCLUDEDIR) - -REG_SEC_DLL=$(OPTTESTDIR)/$(DLLPREF)regOptTest.$(JNI_DLLEXT) - -ifndef JPL_DLL - #JPL_DLL=$(OPTDIR)/$(DLLPREF)jpl.$(JNI_DLLEXT) - JPL_DLL=../../Optimizer/$(DLLPREF)jpl.$(JNI_DLLEXT) -endif - -LINKFILES := $(SECONDO_BUILD_DIR)/UserInterfaces/cmsg.o $(SECONDOPL_DIR)/SecondoPL.o $(LIBDIR)/SecondoInterfaceCS.o $(LIBDIR)/SecondoInterfaceGeneral.o - -# Some optional switches used for providing a prolog -# predicate which maximizes the entropy. For details -# refer to "SecondoPL.cpp" and the subdirectory "Optimizer/Entropy" - -ifdef ENTROPY - LINKFILES += $(OPTDIR)/Entropy/Iterative_scaling.o -endif - -LINK_FLAGS := $(ENT_LINK_LIBS) $(LD_LINK_LIBS) \ - $(JNI_CCFLAGS) $(PLLDFLAGS) - -LINKFILES += $(JPL_DLL) - -.PHONY:all -all: jsrc $(REG_SEC_DLL) - -jsrc: - $(MAKE) -C $(JPLVER) all - -regSecondo.o: regSecondo.c - $(CC) -c -fPIC -g -o $@ $(INCLUDEFLAGS) $< - -LINKFILES += $(PL_DLL) - -ifeq ($(platform),win32) - -$(REG_SEC_DLL): regSecondo.o $(LINKFILES) regSeg.def - $(CC) $(DLLFLAGS) -Wl,-soname,jpl.$(JNI_DLLEXT) -o $@ \ - $^ -lsdbnl $(LINK_FLAGS) regSeg.def - -regSeg.def: regSecondo.o - dlltool -z $@.tmp $^ - sed -e "s#\(.*\)@\(.*\)@.*#\1 = \1@\2#g" $@.tmp > $@ - rm $@.tmp - -else -$(REG_SEC_DLL): regSecondo.o $(LINKFILES) - $(LD) $(DLLFLAGS) $(EXEFLAGS) $(LDFLAGS) -o $@ $^ -lsdbnl $(LINK_FLAGS) -endif - -.PHONY:clean -clean: - rm -f regSecondo.o - rm -f $(REG_SEC_DLL) - diff --git a/OptParser/OptTest/regSecondo.c b/OptParser/OptTest/regSecondo.c deleted file mode 100644 index 43bc0465a4..0000000000 --- a/OptParser/OptTest/regSecondo.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - ---- - This file is part of SECONDO. - - Copyright (C) 2011, University in Hagen, Department of Computer Science, - Database Systems for New Applications. - - SECONDO is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - SECONDO is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SECONDO; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - ---- - -This file is a Java Native Interface file for interfacing Secondo and OptTest. - -*/ - -#include -#include - -JNIEXPORT jint JNICALL Java_OptTest_registerSecondo( - JNIEnv * env , - jclass cl){ - int res = registerSecondo(); - return res; - -} - diff --git a/OptParser/OptTest/startOptTest b/OptParser/OptTest/startOptTest deleted file mode 100755 index c663089181..0000000000 --- a/OptParser/OptTest/startOptTest +++ /dev/null @@ -1,15 +0,0 @@ - - -CLASSPATH=. -if [ "$JPL_JAR" != "" ]; then - CLASSPATH=$CLASSPATH:$JPL_JAR; -else - CLASSPATH=../../Jpl/lib/classes:$CLASSPATH -fi - - -java -Djava.library.path=.:$PL_DLL_DIR -cp $CLASSPATH OptTest $* - - - - diff --git a/OptParser/OptTest/testDML b/OptParser/OptTest/testDML deleted file mode 100755 index ec2372eb76..0000000000 --- a/OptParser/OptTest/testDML +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -cd $HOME/secondo/OptParser/OptTest -make -StartTest dmltest.test diff --git a/OptParser/OptTest/testOptParse b/OptParser/OptTest/testOptParse deleted file mode 100755 index 8ab1763d1b..0000000000 --- a/OptParser/OptTest/testOptParse +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -cd /home/secondo/secondo/OptParser/OptTest -make -StartTest optparse.test diff --git a/OptParser/OptTest/testOptimize b/OptParser/OptTest/testOptimize deleted file mode 100755 index 77330f4071..0000000000 --- a/OptParser/OptTest/testOptimize +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -cd /home/secondo/secondo/OptParser/OptTest -make -StartTest optimize.test diff --git a/OptParser/OptTest/testSQL b/OptParser/OptTest/testSQL deleted file mode 100755 index 659b5e9491..0000000000 --- a/OptParser/OptTest/testSQL +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -cd $HOME/secondo/OptParser/OptTest -make -# StartTest sqltest.test -startOptTest sqltest.test diff --git a/OptParser/makefile b/OptParser/makefile index 6c2019a75c..d9c3ea7746 100755 --- a/OptParser/makefile +++ b/OptParser/makefile @@ -28,8 +28,6 @@ parser.h: parser.c parser.c: OptParser.y OptSecUtils.h Types.h $(YACC) -d -o parser.c OptParser.y -LINKFILES := $(SECONDO_BUILD_DIR)/UserInterfaces/cmsg.o $(SECONDOPL_DIR)/SecondoPL.o $(LIBDIR)/SecondoInterface.o $(LIBDIR)/SecondoInterfaceGeneral.o $(LIBDIR)/libappCommon.a - .PHONY: clean clean: rm -f parser.c parser.h scanner.c scanner.o parser.o $(LIBDIR)/liboptparser.a OptChecker.o OptSecUtils.o Types.o parser.output diff --git a/OptServer/10/NamedVariable.java b/OptServer/10/NamedVariable.java deleted file mode 100644 index d62be57e03..0000000000 --- a/OptServer/10/NamedVariable.java +++ /dev/null @@ -1,80 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import java.io.*; -import java.net.*; -import java.util.*; - -import jpl.JPL; -import jpl.Atom; -import jpl.Query; -import jpl.Term; -import jpl.Variable; -import jpl.fli.*; -import jpl.Compound; - - - - - class NamedVariable{ - /* creates a new Named Variable */ - public NamedVariable(String Name){ - varValue = new Variable(); - name = Name; - } - - /** returns the variable value - * if it's a atom null is returned - */ - public Variable getVariable(){ - return varValue; - } - - - /** returns the name of this variable*/ - public String getName(){ - return name; - } - - /** returns true if the Name is equal - */ - public boolean equals(Object o){ - if(o==null | !(o instanceof NamedVariable)) - return false; - return name.equals( ((NamedVariable) o).name); - } - - /** returns the variable-value if it's a variable, - * otherwise the atom-value is returned - */ - public Term getTerm(){ - return varValue; - } - - public String toString(){ - return name; - } - - private String name; - private Variable varValue; - - } - - - diff --git a/OptServer/10/OptimizerServer.java b/OptServer/10/OptimizerServer.java deleted file mode 100755 index 0458327e4c..0000000000 --- a/OptServer/10/OptimizerServer.java +++ /dev/null @@ -1,696 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import java.io.*; -import java.net.*; -import java.util.*; - -import jpl.JPL; -import jpl.Atom; -import jpl.Query; -import jpl.Term; -import jpl.Variable; -import jpl.fli.*; -import jpl.Compound; -import jpl.Util; - - -public class OptimizerServer extends Thread{ - -static { - System.loadLibrary( "jpl" ); - System.loadLibrary("regSecondo"); - } - - - public static native int registerSecondo(); - - - - /** shows a prompt at the console - */ - private static void showPrompt(){ - System.out.print("\n opt-server > "); - } - - - /** init prolog - * register the secondo predicate - * loads the optimizer prolog code - */ - private boolean initialize(){ - // later here is to invoke the init function which - // registers the Secondo(command,Result) predicate to prolog - if(registerSecondo()!=0){ - System.err.println("error in registering the secondo predicate "); - return false; - } - try{ - System.out.println("call JPL.init()"); - JPL.init(); - System.out.println("initialisation successful"); - - // VTA - 18.09.2006 - // I added this piece of code in order to run with newer versions - // of prolog. Without this code, the libraries (e.g. lists.pl) are - // not automatically loaded. It seems that something in our code - // (auxiliary.pl and calloptimizer.pl) prevents them to be - // automatically loaded. In order to solve this problem I added - // a call to 'member(x, [x]).' so that the libraries are loaded - // before running our scripts. - Term[] args = new Term[2]; - args[0] = new Atom("x"); - args[1] = jpl.Util.termArrayToList( new Term[] { new Atom("x") } ); - Query q = new Query("member",args); - if(!q.query()){ - System.out.println("error in the member call'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom("auxiliary"); - q = new Query("consult",args); - if(!q.query()){ - System.out.println("error in loading 'auxiliary.pl'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom("calloptimizer"); - q = new Query("consult",args); - if(!q.query()){ - System.out.println("error in loading 'calloptimizer.pl'"); - return false; - } - return true; - } catch(Exception e){ - System.out.println("Exception in initialization "+e); - return false; - } - } - - - /** invokes a prolog predicate - * all terms in variables must be contained in arguments - * variables and results can be null if no result is desired - */ - synchronized private static boolean command(Query pl_query, NamedVariable[] variables,Vector results){ - if(pl_query==null) - return false; - try{ - if(trace){ - System.out.println("execute query: "+pl_query); - } - String ret =""; - int number =0; // the number of solutions - if(results!=null) - results.clear(); - while(pl_query.hasMoreSolutions(Prolog.Q_NODEBUG)){ - number++; - Hashtable solution = pl_query.nextSolution(); - if(results!=null){ - ret = ""; - if(variables==null || variables.length==0) - results.add("yes"); - else{ - for(int i=0;i0) ret += " $$$ "; - ret += ( P.getName() + " = " + solution.get(P.getVariable())); - } - results.add(ret); - } - } - } - if(number == 0){ - if(trace) - System.out.println("no solution found for' "+pl_query.atom() +"/"+pl_query.args().length); - return false; - } else{ - // check if a new database is opened - Variable X = new Variable(); - - Query dbQuery = new Query("databaseName",X); - Hashtable sol = dbQuery.oneSolution(); - if(sol==null){ - System.out.println("Error in getting database name "); - return false; - } - String name = sol.get(X).toString(); - if(!name.equals(openedDatabase)){ - if(trace){ - System.out.println("use database "+name); - } - openedDatabase = name; - } - return true; - } - } catch(Exception e){ - if(trace) - System.out.println("exception in calling the "+pl_query.atom()+"-predicate"+e); - return false; - } - } - - - /** analyzed the given string and extract the command and the argumentlist - *
    then the given command is executed - * all Solutions are stored into the Vector Solution - */ - private synchronized static boolean execute(String command,Vector Solution){ - if(Solution!=null) - Solution.clear(); - - // clients should not have the possibility - // to shut down the Optimizer-Server - command = command.trim(); - if(command.startsWith("halt ") || command.equals("halt")) - return false; - - Vector TMPVars = new Vector(); - if(trace){ - System.out.println("analyse command: "+command); - } - Query pl_query = Parser.parse(command,TMPVars); - if(pl_query==null){ - if(trace) - System.out.println("error in parsing command: "+command); - return false; - } - - NamedVariable[] variables = new NamedVariable[TMPVars.size()]; - for(int i=0;i")){ - out.write("\n",0,12); - out.flush(); - running = true; - }else{ - if(trace) - System.out.println("protocol-error , close connection (expect: , received :"+First); - showPrompt(); - running = false; - } - }catch(Exception e){ - if(trace){ - System.out.println("Exception occured "+e); - e.printStackTrace(); - } - showPrompt(); - running = false; - } - } - - /** disconnect this server from a client */ - private void disconnect(){ - // close Connection if possible - try{ - if(S!=null) - S.close(); - }catch(Exception e){ - if(trace){ - System.out.println("Exception in closing connection "+e); - e.printStackTrace(); - } - } - OptimizerServer.Clients--; - if(trace){ - System.out.println("\nbye client"); - System.out.println("number of clients is :"+ OptimizerServer.Clients); - } - showPrompt(); - } - - - - - /** processes requests from clients until the client - * finish the connection or an error occurs - */ - public void run(){ - if(!running){ - disconnect(); - return; - } - - boolean execFlag=false; // flags for control execute or optimize request - try{ - String input = in.readLine(); - if(input==null){ - if(trace) - System.out.println("connection is broken"); - disconnect(); - return; - } - while(!input.equals("")){ - - if(!input.equals("") && !input.equals("") ){ // protocol_error - if(trace) - System.out.println("protocol error( expect: or , found:"+input); - disconnect(); - return; - } - execFlag = input.equals(""); - // read the database name - input = in.readLine(); - if(input==null){ - if(trace) - System.out.println("connection is broken"); - disconnect(); - return; - } - if(!input.equals("")){ // protocol_error - if(trace) - System.out.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - String Database = in.readLine(); - if(Database==null){ - System.out.println("connection is broken"); - disconnect(); - return; - }else { - Database = Database.trim(); - } - input = in.readLine(); - if(input==null){ - if(trace) - System.out.println("connection is broken"); - disconnect(); - return; - }else{ - input = input.trim(); - } - if(!input.equals("")){ // protocol error - if(trace) - System.out.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - input = in.readLine(); - if(input==null){ - if(trace) - System.out.println("connection is broken"); - disconnect(); - return; - }else{ - input = input.trim(); - } - if(!input.equals("")){ // protocol error - if(trace) - System.out.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - - StringBuffer res = new StringBuffer(); - // build the query from the next lines - input = in.readLine(); - //System.out.println("receive"+input); - if(input==null){ - if(trace) - System.out.println("connection is broken"); - disconnect(); - return; - } - while(!input.equals("")){ - res.append(input + "\n"); - input = in.readLine(); - //System.out.println("receive"+input); - if(input==null){ - if(trace) - System.out.println("connection is broken"); - disconnect(); - return; - } - } - - input = in.readLine(); - if(input==null){ - System.out.println("connection is broken"); - disconnect(); - return; - } - - if(! (input.equals("") & !execFlag) & !(input.equals("") & execFlag)){ //protocol-error - if(trace) - System.out.println("protocol error( expect: or , found:"+input); - disconnect(); - return; - } - - String Request = res.toString().trim(); - Vector V = new Vector(); - synchronized(SyncObj){ - useDatabase(Database); - if(!execFlag){ - String opt = OptimizerServer.this.optimize(Request); - if(!opt.equals(Request)) - V.add(opt); - }else{ - execute(Request,V); - } - } - - showPrompt(); - - out.write("\n",0,9); - String answer; - for(int i=0;i\n",0,10); - out.flush(); - input = in.readLine().trim(); - if (input==null){ - System.out.println("connection broken"); - showPrompt(); - disconnect(); - return; - } - } // while - System.out.println("connection ended normally"); - showPrompt(); - }catch(IOException e){ - System.out.println("error in socket-communication"); - disconnect(); - showPrompt(); - return; - } - disconnect(); - } - - private BufferedReader in; - private BufferedWriter out; - private boolean running; - private Socket S; - } - - - - /** creates the server process */ - private boolean createServer(){ - SS=null; - try{ - SS = new ServerSocket(PortNr); - } catch(Exception e){ - System.out.println("unable to create a ServerSocket"); - e.printStackTrace(); - return false; - } - return true; - } - - /** waits for request from clients - * for each new client a new socket communicationis created - */ - public void run(){ - System.out.println("\nwaiting for requests"); - showPrompt(); - while(running){ - try{ - Socket S = SS.accept(); - Clients++; - if(trace){ - System.out.println("\na new client is connected"); - System.out.println("number of clients :"+Clients); - showPrompt(); - } - (new Server(S)).start(); - } catch(Exception e){ - System.out.println("error in communication"); - showPrompt(); - } - } - - } - - - - /** creates a new server object - * process inputs from the user - * available commands are - * client : prints out the number of connected clients - * quit : shuts down the server - */ - public static void main(String[] args){ - if(args.length<1){ - System.err.println("usage: java OptimizerServer -classpath .: OptimizerServer PortNumber"); - System.exit(1); - } - // process options - Runtime rt = Runtime.getRuntime(); - int pos = 1; - while(pos"); - String command = ""; - Vector ResVector = new Vector(); - while(!command.equals("quit")){ - command = in.readLine().trim(); - if(command.equals("clients")){ - System.out.println("Number of Clients: "+ Clients); - }else if(command.equals("quit")){ - if( Clients > 0){ - System.out.print("clients exists ! shutdown anyway (y/n) >"); - String answer = in.readLine().trim().toLowerCase(); - if(!answer.startsWith("y")) - command=""; - } - } else if(command.equals("trace-on")){ - trace=true; - System.out.println("tracing is activated"); - } else if(command.equals("trace-off")){ - trace=false; - System.out.println("tracing is deactivated"); - } else if(command.equals("help") | command.equals("?") ){ - System.out.println("quit : quits the server "); - System.out.println("clients : prints out the number of connected clients"); - System.out.println("trace-on : prints out messages about command, optimized command, open database"); - System.out.println("trace-off : disable messages"); - } else if(command.startsWith("exec")){ - String cmdline = command.substring(4,command.length()).trim(); - execute(cmdline,ResVector); - }else{ - System.out.println("unknow command, try help show a list of valid commands"); - } - if(!command.equals("quit")) - showPrompt(); - - } - OS.running = false; - }catch(Exception e){ - OS.running = false; - System.out.println("error in reading commands"); - if(trace) - e.printStackTrace(); - } - try{ - JPL.halt(); - } catch(Exception e){ - System.err.println(" error in shutting down the prolog engine"); - } - - } - - - /** Prints out the licence information of this software **/ - public static void printLicence(PrintStream out){ - out.println(" Copyright (C) 2004, University in Hagen, "); - out.println(" Department of Computer Science, "); - out.println(" Database Systems for New Applications. \n"); - - out.println(" This is free software; see the source for copying conditions."); - out.println(" There is NO warranty; not even for MERCHANTABILITY or FITNESS "); - out.println(" FOR A PARTICULAR PURPOSE."); - } - - - private static PrologParser Parser = new PrologParser(); - private boolean optimizer_loaded = false; - private int PortNr = 1235; - private static int Clients = 0; - private ServerSocket SS; - private boolean running; - private static String openedDatabase =""; - private static boolean trace = true; - private static Object SyncObj = new Object(); - -} - - - - diff --git a/OptServer/10/PrologParser.java b/OptServer/10/PrologParser.java deleted file mode 100644 index 0bfc66956a..0000000000 --- a/OptServer/10/PrologParser.java +++ /dev/null @@ -1,361 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import java.io.*; -import java.net.*; -import java.util.*; - -import jpl.JPL; -import jpl.Atom; -import jpl.Query; -import jpl.Term; -import jpl.Variable; -import jpl.fli.*; -import jpl.Compound; -import jpl.List; - - - -class PrologParser{ - - private class Scanner{ - public Scanner(String i){ - input = i; - nextStart=0; - length=input.length(); - } - - int getNext(){ - int state = 0; - int startPos = nextStart; - int pos = nextStart; - char c=' '; - while(pos='A' && c <='Z'; - } - - /** returns true if c is a separator without meaning*/ - private boolean isWhiteSpace(char c){ - return c==' ' | c=='\n' | c=='\t' | c==',' | c==';' | c==':' | c=='|'; - } - - /** returns true if c is a character which indicates the end of a atom or a variable */ - private boolean isSeparator(char c){ - return isWhiteSpace(c) | c=='(' | c==')' | c=='[' | c==']' | c=='\"' | c=='\''; - } - - /** return the value of the last getNext or preview command */ - public String getValue(){ - return value; - } - - private String value; - private int nextStart; - private String input; - private int length; - - private int EOI = 0; // end of input - private int ATOM = 1; - private int VARIABLE = 2; - private int OPENBRACKET1 = 3; // ( - private int OPENBRACKET2 = 4; // [ - private int CLOSEBRACKET1 = 5; // ) - private int CLOSEBRACKET2 = 6; // ] - private int ERROR = -1; - - } // class scanner - - - - /** the method constructs a prolog query from given input - * if the string is not a valid query, null is returned - * all - */ - public Query parse(String Input,Vector Variables){ - if(Variables==null) - Variables = new Vector(); - Variables.clear(); - pos = 0; - ErrorMessage=""; - if(Input==null){ - ErrorMessage="null is not allowed as input "; - return null; - } - Scan = new Scanner(Input); - Token = Scan.getNext(); - if(Token != Scan.ATOM){ - ErrorMessage="prolog command must begin with an atom"; - return null; - } - Atom Command = new Atom(Scan.getValue()); - int P = Scan.preview(); - Vector V; - if (P==Scan.OPENBRACKET1){ - P = Scan.getNext(); // read over the bracket - V = getArgumentList(Variables,Scan.CLOSEBRACKET1); - } - /*else if(P==Scan.OPENBRACKET2){ - P = Scan.getNext(); - V = getArgumentList(Variables,Scan.CLOSEBRACKET2); - }*/ - else - V = getArgumentList(Variables,Scan.EOI); - - - P=Scan.preview(); - if(P!=Scan.EOI){ - ErrorMessage="input after end of command found"; - return null; - } - if(V==null) // an error is occured - return null; - - Term[] args= new Term[V.size()]; - for(int i=0;i=0;i--){ - L = new List( (Term) sublist.get(i),L); - } - result.add(L); - } - } else { - if(T==Scan.ERROR) - ErrorMessage=Scan.getValue(); - else - ErrorMessage="error in building argument list"+T; - return null; - } - T = Scan.getNext(); - - } - return result; - } - - - // for tests only - public static void main(String[] args){ - System.out.println("only a test for the prolog parser"); - System.out.println("type in your prolog command and the resulting query is printed out"); - - try{ - BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); - PrologParser P = new PrologParser(); - String line; - Query Q; - while(!(line=in.readLine()).equals("exit")){ - Q = P.parse(line,null); - if(Q==null){ - System.out.println("error in parsing command: "+P.ErrorMessage); - }else - System.out.println("=> "+Q); - } - - } - catch(Exception e){ - e.printStackTrace(); - } - - } - - - private int Token; - private int pos; // position in input-stream - private Vector arguments; - private Scanner Scan; - public String ErrorMessage=""; - - - -} - - diff --git a/OptServer/10/makefile b/OptServer/10/makefile deleted file mode 100755 index 3932bd5d77..0000000000 --- a/OptServer/10/makefile +++ /dev/null @@ -1,58 +0,0 @@ -#This file is part of SECONDO. - -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. - -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. - -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../makefile.env - -ifdef JPL_JAR -CLASSPATH=.:$(JPL_JAR) -else -CLASSPATH=$(JPL_CLASSPATH) -endif - -BASIC_OPT_DIR=$(OPTDIR)/../OptimizerBasic - - -.PHONY:all -all: std basic - -std: $(OPTDIR)/OptimizerServer.class $(OPTDIR)/NamedVariable.class $(OPTDIR)/PrologParser.class -basic: $(BASIC_OPT_DIR)/OptimizerServer.class $(BASIC_OPT_DIR)/NamedVariable.class $(BASIC_OPT_DIR)/PrologParser.class - -$(OPTDIR)/OptimizerServer.class: OptimizerServer.java - $(JAVAC) -classpath $(JPL_CLASSPATH) -d $(OPTDIR) OptimizerServer.java - -$(OPTDIR)/PrologParser.class: PrologParser.java - $(JAVAC) -classpath $(JPL_CLASSPATH) -d $(OPTDIR) PrologParser.java - -$(OPTDIR)/NamedVariable.class: NamedVariable.java - $(JAVAC) -classpath $(JPL_CLASSPATH) -d $(OPTDIR) NamedVariable.java - -$(BASIC_OPT_DIR)/OptimizerServer.class: OptimizerServer.java - $(JAVAC) -classpath $(JPL_CLASSPATH) -d $(BASIC_OPT_DIR) OptimizerServer.java - -$(BASIC_OPT_DIR)/PrologParser.class: PrologParser.java - $(JAVAC) -classpath $(JPL_CLASSPATH) -d $(BASIC_OPT_DIR) PrologParser.java - -$(BASIC_OPT_DIR)/NamedVariable.class: NamedVariable.java - $(JAVAC) -classpath $(JPL_CLASSPATH) -d $(BASIC_OPT_DIR) NamedVariable.java - -.PHONY:clean -clean: - rm -f $(OPTDIR)/*.class - rm -f $(BASIC_OPT_DIR)/*.class diff --git a/OptServer/30/OptimizerServer.java b/OptServer/30/OptimizerServer.java deleted file mode 100755 index 93aeae526e..0000000000 --- a/OptServer/30/OptimizerServer.java +++ /dev/null @@ -1,937 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import java.io.*; -import java.net.*; -import java.util.*; - -import jpl.JPL; -import jpl.Atom; -import jpl.Query; -import jpl.Term; -import jpl.Variable; -import jpl.fli.*; -import jpl.Compound; -import jpl.Util; -import java.nio.charset.Charset; -import java.util.SortedMap; - - - -public class OptimizerServer extends Thread{ - -static { - System.loadLibrary( "jpl" ); - System.loadLibrary( "regSecondo" ); - } - - - public static native int registerSecondo(); - - - - - /** shows a prompt at the console - */ - private static void showPrompt(){ - cout.print("\n opt-server > "); - } - - - /** init prolog - * register the secondo predicate - * loads the optimizer prolog code - */ - private boolean initialize(){ - // later here is to invoke the init function which - // registers the Secondo(command,Result) predicate to prolog - if(registerSecondo()!=0){ - System.err.println("error in registering the secondo predicate "); - return false; - } - //cout.println("registerSecondo successful"); - try{ - - String[] plargs = {"-L256M","-G256M"}; - boolean ok = JPL.init(plargs); - - // VTA - 18.09.2006 - // I added this piece of code in order to run with newer versions - // of prolog. Without this code, the libraries (e.g. lists.pl) are - // not automatically loaded. It seems that something in our code - // (auxiliary.pl and calloptimizer.pl) prevents them to be - // automatically loaded. In order to solve this problem I added - // a call to 'member(x, [x]).' so that the libraries are loaded - // before running our scripts. - Term[] args = new Term[2]; - args[0] = new Atom("x"); - args[1] = jpl.Util.termArrayToList( new Term[] { new Atom("x") } ); - Query q = new Query("member",args); - if(!q.hasSolution()){ - cout.println("error in the member call'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom("auxiliary"); - q = new Query("consult",args); - if(!q.hasSolution()){ - cout.println("error in loading 'auxiliary.pl'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom("calloptimizer"); - q = new Query("consult",args); - if(!q.hasSolution()){ - cout.println("error in loading 'calloptimizer.pl'"); - return false; - } - return true; - } catch(Exception e){ - cout.println("Exception in initialization "+e); - e.printStackTrace(); - return false; - } - } - - - - public static boolean halt(){ - try{ - Query q = new Query("halt"); - boolean res = command(q,null); - return res; - } catch(Exception e){ - System.err.println(" error in shutting down the prolog engine"); - e.printStackTrace(); - return false; - } - } - - /** invokes a prolog predicate - * all terms in variables must be contained in arguments - * variables and results can be null if no result is desired - */ - synchronized private static boolean command(Query pl_query, Vector results){ - if(pl_query==null) - return false; - try{ - if(trace){ - cout.println("execute query: "+pl_query); - } - String ret =""; - int number =0; // the number of solutions - if(results!=null) - results.clear(); - while(pl_query.hasMoreSolutions()){ - number++; - Hashtable solution = pl_query.nextSolution(); - if(results!=null){ - ret = ""; - if(solution.size()<=0){ - results.add("yes"); - } else{ - Enumeration vars = solution.keys(); - int varnum =0; - while(vars.hasMoreElements()){ - Object v = vars.nextElement(); - if (varnum>0) ret += " $$$ "; - ret += ( v + " = " + solution.get(v)); - } - results.add(ret); - } - } - } - if(number == 0){ - if(trace) - cout.println("no solution found for' "+pl_query.goal() +"/"+pl_query.goal().arity()); - return false; - } else{ - // check if the used database is changed - Query dbQuery = new Query("databaseName(X)"); - if(dbQuery.hasMoreSolutions()){ - Hashtable sol = dbQuery.nextSolution(); - Object v = sol.keys().nextElement(); - String name = ""+sol.get(v); - if(!name.equals(openedDatabase)){ - if(trace){ - cout.println("use database "+ name); - } - openedDatabase=name; - } - - } else{ // no database open - openedDatabase = ""; - } - - return true; - } - } catch(Exception e){ - if(trace){ - cout.println("exception in calling the "+pl_query.goal()+"-predicate"+e); - e.printStackTrace(); - } - return false; - } - } - - - /** analyzed the given string and extract the command and the argumentlist - *
    then the given command is executed - * all Solutions are stored into the Vector Solution - */ - private synchronized static boolean execute(String command,Vector Solution){ - if(Solution!=null) - Solution.clear(); - - // clients should not have the possibility - // to shut down the Optimizer-Server - command = command.trim(); - if(command.startsWith("halt ") || command.equals("halt")) - return false; - - Vector TMPVars = new Vector(); - if(trace){ - cout.println("analyse command: "+command); - } - command = encode(command); - try{ - Query pl_query = new Query(command); - if(pl_query==null){ - if(trace) - cout.println("error in parsing command: "+command); - return false; - } - boolean res = command(pl_query,Solution); - - if(res & trace & Solution!=null){ // successful - if(Solution.size()==0) - cout.println("Yes"); - else - for(int i=0;i 1){ - allret += "\n"; - } - Hashtable solution = pl_query.nextSolution(); - if(solution.size()!=1){ - if(trace){ - cout.println("Error: optimization returns more than a single binding"); - } - return query; - } - Enumeration e = solution.keys(); - while(e.hasMoreElements()){ - allret += "" + solution.get(e.nextElement()); - } - if(number==1){ - ret1 = allret; - } - } - if(number>1){ - if(trace){ - cout.println("Error: optimization returns more than one solution"); - cout.println("Solutions are \n" + allret); - } - ret1 = ret1.trim(); - if(ret1.startsWith("'") && ret1.endsWith("'")){ - if(ret1.length()==2){ - ret1 = ""; - } else{ - ret1 = ret1.substring(1,ret1.length()-1); - } - } - - return decode(ret1); - } - - if(number==0){ - if(trace) - cout.println("optimization failed - no solution found"); - return query; - } - else{ - if(trace) - cout.println("\n optimization-result : "+allret+"\n"); - - // free ret from enclosing '' - allret = allret.trim(); - if(allret.startsWith("'") && allret.endsWith("'")){ - if(allret.length()==2){ - allret = ""; - } else{ - allret = allret.substring(1,allret.length()-1); - } - } - - return decode(allret); - } - } catch(Exception e){ - if(trace) { - cout.println("\n Exception :"+e); - e.printStackTrace(); - } - showPrompt(); - return query; - } - - } - - /** if Name is not the database currenty used, - * the opened database is closed and the database - * Name is opened - */ - private synchronized boolean useDatabase(String Name){ - if(openedDatabase.equals(Name)){ - return true; - } - Term[] arg = new Term[1]; - if(!openedDatabase.equals("")){ - if(trace) - cout.println("close the opened database"); - Query Q = new Query("secondo('close database')"); - command(Q,null); - } - - Query Q_open = new Query("secondo('open database "+Name+"')"); - showPrompt(); - boolean res = command(Q_open,null); - openedDatabase = res?Name:""; - return res; - } - - - - /** a class for communicate with a client */ - private class Server extends Thread{ - - /** creates a new Server from given socket */ - public Server(Socket S){ - this.S = S; - //cout.println("requesting from client"); - try{ - // communication with client, always use UTF-8 encoding - try{ - in = new BufferedReader(new InputStreamReader(S.getInputStream(),"UTF-8")); - } catch(UnsupportedEncodingException e){ - System.err.println("Encoding UTF-8 not supported"); - in = new BufferedReader(new InputStreamReader(S.getInputStream())); - } - try{ - out = new BufferedWriter(new OutputStreamWriter(S.getOutputStream(),"UTF-8")); - } catch(UnsupportedEncodingException e){ - System.err.println("Encoding UTF-8 not supported"); - out = new BufferedWriter(new OutputStreamWriter(S.getOutputStream())); - } - String First = in.readLine(); - //cout.println("receive :"+First); - if(First==null){ - if(trace) - cout.println("connection broken"); - showPrompt(); - running=false; - return; - } - if(First.equals("")){ - out.write("\n",0,12); - out.flush(); - running = true; - }else{ - if(trace) - cout.println("protocol-error , close connection (expect: , received :"+First); - showPrompt(); - running = false; - } - }catch(Exception e){ - if(trace){ - cout.println("Exception occured "+e); - e.printStackTrace(); - } - showPrompt(); - running = false; - } - } - - /** disconnect this server from a client */ - private void disconnect(){ - // close Connection if possible - try{ - if(S!=null) - S.close(); - }catch(Exception e){ - if(trace){ - cout.println("Exception in closing connection "+e); - e.printStackTrace(); - } - } - OptimizerServer.Clients--; - if(trace){ - cout.println("\nbye client"); - cout.println("number of clients is :"+ OptimizerServer.Clients); - } - if((OptimizerServer.Clients==0) && OptimizerServer.quitAfterDisconnect){ - // OptimizerServer.halt(); // not allowed from this tread - System.exit(0); - } - showPrompt(); - } - - - - - /** processes requests from clients until the client - * finish the connection or an error occurs - */ - public void run(){ - if(!running){ - disconnect(); - return; - } - - boolean execFlag=false; // flags for control execute or optimize request - try{ - String input = in.readLine(); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - while(!input.equals("")){ - - if(!input.equals("") && !input.equals("") ){ // protocol_error - if(trace) - cout.println("protocol error( expect: or , found:"+input); - disconnect(); - return; - } - //cout.println("receive "+input+" from client"); - - execFlag = input.equals(""); - // read the database name - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - if(!input.equals("")){ // protocol_error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - String Database = in.readLine(); - - //cout.println("receive "+Database+" from client"); - - if(Database==null){ - cout.println("connection is broken"); - disconnect(); - return; - }else { - Database = Database.trim(); - } - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - }else{ - input = input.trim(); - } - if(!input.equals("")){ // protocol error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - }else{ - input = input.trim(); - } - if(!input.equals("")){ // protocol error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - - StringBuffer res = new StringBuffer(); - // build the query from the next lines - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - //cout.println("receive"+input); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - while(!input.equals("")){ - res.append(input + "\n"); - input = in.readLine(); - //cout.println("receive"+input); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - } - - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - cout.println("connection is broken"); - disconnect(); - return; - } - - if(! (input.equals("") & !execFlag) & !(input.equals("") & execFlag)){ //protocol-error - if(trace) - cout.println("protocol error( expect: or , found:"+input); - disconnect(); - return; - } - - String Request = res.toString().trim(); - - //cout.println("Request is " + Request ); - - Vector V = new Vector(); - synchronized(SyncObj){ - useDatabase(Database); - if(!execFlag){ - String opt = OptimizerServer.this.optimize(Request); - if(!opt.equals(Request)) - V.add(opt); - }else{ - execute(Request,V); - } - } - - showPrompt(); - - out.write("\n",0,9); - String answer; - for(int i=0;i\n",0,10); - out.flush(); - input = in.readLine().trim(); - - //cout.println("receive "+input+" from client"); - - if (input==null){ - cout.println("connection broken"); - showPrompt(); - disconnect(); - return; - } - } // while - cout.println("connection ended normally"); - showPrompt(); - }catch(IOException e){ - cout.println("error in socket-communication" + e); - - disconnect(); - showPrompt(); - return; - } - disconnect(); - } - - - private BufferedReader in; - private BufferedWriter out; - private boolean running; - private Socket S; - - - - - } - - - - /** creates the server process */ - private boolean createServer(){ - SS=null; - try{ - SS = new ServerSocket(PortNr); - } catch(java.net.BindException be){ - cout.println("BindException occured"); - cout.println("check if the port "+PortNr+" is already in use"); - return false; - } catch(Exception e){ - cout.println("unable to create a ServerSocket" + e); - e.printStackTrace(); - return false; - } - return true; - } - - /** waits for request from clients - * for each new client a new socket communicationis created - */ - public void run(){ - cout.println("\nwaiting for requests"); - showPrompt(); - while(running){ - try{ - Socket S = SS.accept(); - Clients++; - if(trace){ - cout.println("\na new client is connected"); - cout.println("number of clients :"+Clients); - showPrompt(); - } - (new Server(S)).start(); - } catch(Exception e){ - cout.println("error in communication" + e); - showPrompt(); - } - } - - } - - - private static void showUsage(){ - cout.println("java -classpath .: OptimizerServer PORT [options] "); - cout.println(" : jar file containing the JPL (prolog) API"); - cout.println("PORT : port for the server"); - cout.println("[Options can be :"); - cout.println(" -autoquit : exits the server if the last client disconnects"); - cout.println(" -trace_methods : enables tracing of method calls (for debugging)"); - cout.println(" -trace_instructions : enables tracing of instructions (for debugging)"); - cout.println(" -trace_commands : enables tracing of input/output"); - cout.println(" -encoding enc : switch the output encoding"); - } - - - /** creates a new server object - * process inputs from the user - * available commands are - * client : prints out the number of connected clients - * quit : shuts down the server - */ - public static void main(String[] args){ - cout = System.out; - if(args.length<1){ - showUsage(); - System.exit(1); - } - // process options - Runtime rt = Runtime.getRuntime(); - int pos = 1; - String console_enc = "utf-8"; // standard - while(pos=args.length){ - showUsage(); - System.exit(1); - } - console_enc = args[pos+1]; - pos++; - pos++; - } else if(args[pos].equals("-trace_commands")){ - trace=true; - pos++; - } else { - cout.println("unknown option " + args[pos]); - showUsage(); - System.exit(1); - } - } - - if(!console_enc.equals("utf-8")){ - SortedMap available = Charset.availableCharsets(); - if(!available.containsKey(console_enc)){ - cout.println("encoding " + console_enc + " unknown"); - cout.println(" Available encodinga are : "); - cout.println(available.keySet()); - System.exit(1); - } - try { - cout = new PrintStream(System.out, true, console_enc); - } catch(Exception e){ - cout = System.out; - cout.println("Problem in changing output encoding, use utf-8"); - e.printStackTrace(); - } - } - - - cout.println("\n\n"); - printLicence(cout); - cout.println("\n"); - String arg = args[0]; - OptimizerServer OS = new OptimizerServer(); - try{ - int P = Integer.parseInt(arg); - if(P<=0){ - System.err.println("the Portnumber must be greater then zero"); - System.exit(1); - } - OS.PortNr=P; - }catch(Exception e){ - System.err.println("the Portnumber must be an integer"); - System.exit(1); - } - - try{ - Class.forName("jpl.fli.Prolog"); // ensure to load the jpl library - } catch(Exception e){ - System.err.println("loading prolog class failed"); - System.exit(1); - } - - if(! OS.initialize()){ - cout.println("initialization failed"); - System.exit(1); - } - if(!OS.createServer()){ - cout.println("creating Server failed"); - System.exit(1); - } - OS.running = true; - OS.start(); - try{ - BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); - cout.print("optserver >"); - String command = ""; - Vector ResVector = new Vector(); - while(!command.equals("quit")){ - command = in.readLine(); - if(command==null){ - command = ""; - continue; - } - command = command.trim(); - if(command.equals("clients")){ - cout.println("Number of Clients: "+ Clients); - }else if(command.equals("quit")){ - if( Clients > 0){ - cout.print("clients exists ! shutdown anyway (y/n) >"); - String answer = in.readLine().trim().toLowerCase(); - if(!answer.startsWith("y")) - command=""; - } - } else if(command.equals("trace-on")){ - trace=true; - cout.println("tracing is activated"); - } else if(command.equals("trace-off")){ - trace=false; - cout.println("tracing is deactivated"); - } else if(command.equals("help") | command.equals("?") ){ - cout.println("quit : quits the server "); - cout.println("clients : prints out the number of connected clients"); - cout.println("trace-on : prints out messages about command, optimized command, open database"); - cout.println("trace-off : disable messages"); - } else if(command.startsWith("exec")){ - String cmdline = command.substring(4,command.length()).trim(); - execute(cmdline,ResVector); - }else if(!command.equals("")){ - cout.println("unknow command, try help show a list of valid commands"); - } - if(!command.equals("quit")) - showPrompt(); - - } - OS.running = false; - }catch(Exception e){ - OS.running = false; - cout.println("error in reading commands"); - if(trace) - e.printStackTrace(); - } - try{ - Query q = new Query("halt"); - command(q,null); - } catch(Exception e){ - System.err.println(" error in shutting down the prolog engine"); - } - - } - - - /** Prints out the licence information of this software **/ - public static void printLicence(PrintStream out){ - cout.println(" Copyright (C) 2006, University in Hagen, "); - cout.println(" Faculty of Mathematics and Computer Science, "); - cout.println(" Database Systems for New Applications. \n"); - - cout.println(" This is free software; see the source for copying conditions."); - cout.println(" There is NO warranty; not even for MERCHANTABILITY or FITNESS "); - cout.println(" FOR A PARTICULAR PURPOSE."); - } - - /** Converts a string into OS_pl_encoding **/ - private static String encode(String src){ - if(OS_pl_encoding==null){ - return src; - } - try{ - byte[] encodedBytes = src.getBytes(OS_pl_encoding); - return new String(encodedBytes, "UTF-8"); - } catch(Exception e){ - System.err.println("Used encoding not supported\n" + e); - return src; - } - } - - /** Converts a string from OS_pl_encoding **/ - private static String decode(String src){ - if(OS_pl_encoding==null){ - return src; - } - try{ - byte[] encodedBytes = src.getBytes("UTF-8"); - return new String(encodedBytes, OS_pl_encoding); - } catch(Exception e){ - System.err.println("Used encoding not supported\n" + e); - return src; - } - } - - - - - private static String OS_pl_encoding = null; - - - private boolean optimizer_loaded = false; - private int PortNr = 1235; - private static int Clients = 0; - private static boolean quitAfterDisconnect = false; - private ServerSocket SS; - private boolean running; - private static String openedDatabase =""; - private static boolean trace = true; - private static Object SyncObj = new Object(); - private static PrintStream cout; - -} - - - - diff --git a/OptServer/30/makefile b/OptServer/30/makefile deleted file mode 100755 index 2de2dc82b8..0000000000 --- a/OptServer/30/makefile +++ /dev/null @@ -1,44 +0,0 @@ -#This file is part of SECONDO. - -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. - -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. - -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../makefile.env - -ifdef JPL_JAR -CLASSPATH=$(JPL_JAR) -else -CLASSPATH=$(JPL_CLASSPATH) -endif - -BASIC_OPT_DIR=$(OPTDIR)/../OptimizerBasic - - -.PHONY:all -all: $(OPTDIR)/OptimizerServer.class $(BASIC_OPT_DIR)/OptimizerServer.class - -$(OPTDIR)/OptimizerServer.class: OptimizerServer.java - $(JAVAC) -classpath $(CLASSPATH) -d $(OPTDIR) OptimizerServer.java - -$(BASIC_OPT_DIR)/OptimizerServer.class: OptimizerServer.java - $(JAVAC) -classpath $(CLASSPATH) -d $(BASIC_OPT_DIR) OptimizerServer.java - - -.PHONY:clean -clean: - rm -f $(OPTDIR)/*.class - rm -f $(BASIC_OPT_DIR)/*.class diff --git a/OptServer/70/OptimizerServer.java b/OptServer/70/OptimizerServer.java deleted file mode 100755 index f78464cfa6..0000000000 --- a/OptServer/70/OptimizerServer.java +++ /dev/null @@ -1,925 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2004, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import java.io.*; -import java.net.*; -import java.util.*; - - -import org.jpl7.*; -import java.nio.charset.Charset; -import java.util.SortedMap; - - - -public class OptimizerServer extends Thread{ - -static { - System.loadLibrary( "jpl" ); - System.loadLibrary( "regSecondo" ); - } - - - public static native int registerSecondo(); - - - - - /** shows a prompt at the console - */ - private static void showPrompt(){ - cout.print("\n opt-server > "); - } - - - /** init prolog - * register the secondo predicate - * loads the optimizer prolog code - */ - private boolean initialize(){ - // later here is to invoke the init function which - // registers the Secondo(command,Result) predicate to prolog - if(registerSecondo()!=0){ - System.err.println("error in registering the secondo predicate "); - return false; - } - //cout.println("registerSecondo successful"); - try{ - - String[] plargs = {"-L256M","-G256M"}; - boolean ok = JPL.init(plargs); - - // VTA - 18.09.2006 - // I added this piece of code in order to run with newer versions - // of prolog. Without this code, the libraries (e.g. lists.pl) are - // not automatically loaded. It seems that something in our code - // (auxiliary.pl and calloptimizer.pl) prevents them to be - // automatically loaded. In order to solve this problem I added - // a call to 'member(x, [x]).' so that the libraries are loaded - // before running our scripts. - Term[] args = new Term[2]; - args[0] = new Atom("x"); - args[1] = org.jpl7.Util.termArrayToList( new Term[] { new Atom("x") } ); - Query q = new Query("member",args); - if(!q.hasSolution()){ - cout.println("error in the member call'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom("auxiliary"); - q = new Query("consult",args); - if(!q.hasSolution()){ - cout.println("error in loading 'auxiliary.pl'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom("calloptimizer"); - q = new Query("consult",args); - if(!q.hasSolution()){ - cout.println("error in loading 'calloptimizer.pl'"); - return false; - } - return true; - } catch(Exception e){ - cout.println("Exception in initialization "+e); - e.printStackTrace(); - return false; - } - } - - - - public static boolean halt(){ - try{ - Query q = new Query("halt"); - boolean res = command(q,null); - return res; - } catch(Exception e){ - System.err.println(" error in shutting down the prolog engine"); - e.printStackTrace(); - return false; - } - } - - /** invokes a prolog predicate - * all terms in variables must be contained in arguments - * variables and results can be null if no result is desired - */ - synchronized private static boolean command(Query pl_query, Vector results){ - if(pl_query==null) - return false; - try{ - if(trace){ - cout.println("execute query: "+pl_query); - } - String ret =""; - int number =0; // the number of solutions - if(results!=null) - results.clear(); - while(pl_query.hasMoreSolutions()){ - number++; - Map solution = pl_query.nextSolution(); - if(results!=null){ - ret = ""; - if(solution.size()<=0){ - results.add("yes"); - } else{ - Set vars = solution.keySet(); - Iterator it = vars.iterator(); - int varnum =0; - while(it.hasNext()){ - String k = it.next(); - if (varnum>0) ret += " $$$ "; - ret += ( k + " = " + solution.get(k)); - varnum++; - } - results.add(ret); - } - } - } - if(number == 0){ - if(trace) - cout.println("no solution found for' "+pl_query.goal() +"/"+pl_query.goal().arity()); - return false; - } else{ - // check if the used database is changed - Query dbQuery = new Query("databaseName(X)"); - if(dbQuery.hasMoreSolutions()){ - Map sol = dbQuery.nextSolution(); - String v = sol.keySet().iterator().next(); - String name = ""+sol.get(v); - if(!name.equals(openedDatabase)){ - if(trace){ - cout.println("use database "+ name); - } - openedDatabase=name; - } - - } else{ // no database open - openedDatabase = ""; - } - - return true; - } - } catch(Exception e){ - if(trace){ - cout.println("exception in calling the "+pl_query.goal()+"-predicate"+e); - e.printStackTrace(); - } - return false; - } - } - - - /** analyzed the given string and extract the command and the argumentlist - *
    then the given command is executed - * all Solutions are stored into the Vector Solution - */ - private synchronized static boolean execute(String command,Vector Solution){ - if(Solution!=null) - Solution.clear(); - - // clients should not have the possibility - // to shut down the Optimizer-Server - command = command.trim(); - if(command.startsWith("halt ") || command.equals("halt")) - return false; - - Vector TMPVars = new Vector(); - if(trace){ - cout.println("analyse command: "+command); - } - command = encode(command); - try{ - Query pl_query = new Query(command); - if(pl_query==null){ - if(trace) - cout.println("error in parsing command: "+command); - return false; - } - boolean res = command(pl_query,Solution); - - if(res & trace & Solution!=null){ // successful - if(Solution.size()==0) - cout.println("Yes"); - else - for(int i=0;i 1){ - allret += "\n"; - } - Map solution = pl_query.nextSolution(); - if(solution.size()!=1){ - if(trace){ - cout.println("Error: optimization returns more than a single binding"); - } - return query; - } - Iterator it = solution.keySet().iterator(); - while(it.hasNext()){ - allret += "" + solution.get(it.next()); - } - if(number==1){ - ret1 = allret; - } - } - if(number>1){ - if(trace){ - cout.println("Error: optimization returns more than one solution"); - cout.println("Solutions are \n" + allret); - } - ret1 = ret1.trim(); - if(ret1.startsWith("'") && ret1.endsWith("'")){ - if(ret1.length()==2){ - ret1 = ""; - } else{ - ret1 = ret1.substring(1,ret1.length()-1); - } - } - - return decode(ret1); - } - - if(number==0){ - if(trace) - cout.println("optimization failed - no solution found"); - return query; - } - else{ - if(trace) - cout.println("\n optimization-result : "+allret+"\n"); - - // free ret from enclosing '' - allret = allret.trim(); - if(allret.startsWith("'") && allret.endsWith("'")){ - if(allret.length()==2){ - allret = ""; - } else{ - allret = allret.substring(1,allret.length()-1); - } - } - - return decode(allret); - } - } catch(Exception e){ - if(trace) { - cout.println("\n Exception :"+e); - e.printStackTrace(); - } - showPrompt(); - return query; - } - - } - - /** if Name is not the database currenty used, - * the opened database is closed and the database - * Name is opened - */ - private synchronized boolean useDatabase(String Name){ - if(openedDatabase.equals(Name)){ - return true; - } - Term[] arg = new Term[1]; - if(!openedDatabase.equals("")){ - if(trace) - cout.println("close the opened database"); - Query Q = new Query("secondo('close database')"); - command(Q,null); - } - - Query Q_open = new Query("secondo('open database "+Name+"')"); - showPrompt(); - boolean res = command(Q_open,null); - openedDatabase = res?Name:""; - return res; - } - - - - /** a class for communicate with a client */ - private class Server extends Thread{ - - /** creates a new Server from given socket */ - public Server(Socket S){ - this.S = S; - //cout.println("requesting from client"); - try{ - // communication with client, always use UTF-8 encoding - try{ - in = new BufferedReader(new InputStreamReader(S.getInputStream(),"UTF-8")); - } catch(UnsupportedEncodingException e){ - System.err.println("Encoding UTF-8 not supported"); - in = new BufferedReader(new InputStreamReader(S.getInputStream())); - } - try{ - out = new BufferedWriter(new OutputStreamWriter(S.getOutputStream(),"UTF-8")); - } catch(UnsupportedEncodingException e){ - System.err.println("Encoding UTF-8 not supported"); - out = new BufferedWriter(new OutputStreamWriter(S.getOutputStream())); - } - String First = in.readLine(); - //cout.println("receive :"+First); - if(First==null){ - if(trace) - cout.println("connection broken"); - showPrompt(); - running=false; - return; - } - if(First.equals("")){ - out.write("\n",0,12); - out.flush(); - running = true; - }else{ - if(trace) - cout.println("protocol-error , close connection (expect: , received :"+First); - showPrompt(); - running = false; - } - }catch(Exception e){ - if(trace){ - cout.println("Exception occured "+e); - e.printStackTrace(); - } - showPrompt(); - running = false; - } - } - - /** disconnect this server from a client */ - private void disconnect(){ - // close Connection if possible - try{ - if(S!=null) - S.close(); - }catch(Exception e){ - if(trace){ - cout.println("Exception in closing connection "+e); - e.printStackTrace(); - } - } - OptimizerServer.Clients--; - if(trace){ - cout.println("\nbye client"); - cout.println("number of clients is :"+ OptimizerServer.Clients); - } - if((OptimizerServer.Clients==0) && OptimizerServer.quitAfterDisconnect){ - // OptimizerServer.halt(); // not allowed from this tread - System.exit(0); - } - showPrompt(); - } - - - - - /** processes requests from clients until the client - * finish the connection or an error occurs - */ - public void run(){ - if(!running){ - disconnect(); - return; - } - - boolean execFlag=false; // flags for control execute or optimize request - try{ - String input = in.readLine(); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - while(!input.equals("")){ - - if(!input.equals("") && !input.equals("") ){ // protocol_error - if(trace) - cout.println("protocol error( expect: or , found:"+input); - disconnect(); - return; - } - //cout.println("receive "+input+" from client"); - - execFlag = input.equals(""); - // read the database name - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - if(!input.equals("")){ // protocol_error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - String Database = in.readLine(); - - //cout.println("receive "+Database+" from client"); - - if(Database==null){ - cout.println("connection is broken"); - disconnect(); - return; - }else { - Database = Database.trim(); - } - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - }else{ - input = input.trim(); - } - if(!input.equals("")){ // protocol error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - }else{ - input = input.trim(); - } - if(!input.equals("")){ // protocol error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - - StringBuffer res = new StringBuffer(); - // build the query from the next lines - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - //cout.println("receive"+input); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - while(!input.equals("")){ - res.append(input + "\n"); - input = in.readLine(); - //cout.println("receive"+input); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - } - - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - cout.println("connection is broken"); - disconnect(); - return; - } - - if(! (input.equals("") & !execFlag) & !(input.equals("") & execFlag)){ //protocol-error - if(trace) - cout.println("protocol error( expect: or , found:"+input); - disconnect(); - return; - } - - String Request = res.toString().trim(); - - //cout.println("Request is " + Request ); - - Vector V = new Vector(); - synchronized(SyncObj){ - useDatabase(Database); - if(!execFlag){ - String opt = OptimizerServer.this.optimize(Request); - if(!opt.equals(Request)) - V.add(opt); - }else{ - execute(Request,V); - } - } - - showPrompt(); - - out.write("\n",0,9); - String answer; - for(int i=0;i\n",0,10); - out.flush(); - input = in.readLine().trim(); - - //cout.println("receive "+input+" from client"); - - if (input==null){ - cout.println("connection broken"); - showPrompt(); - disconnect(); - return; - } - } // while - cout.println("connection ended normally"); - showPrompt(); - }catch(IOException e){ - cout.println("error in socket-communication" + e); - - disconnect(); - showPrompt(); - return; - } - disconnect(); - } - - - private BufferedReader in; - private BufferedWriter out; - private boolean running; - private Socket S; - - - - - } - - - - /** creates the server process */ - private boolean createServer(){ - SS=null; - try{ - SS = new ServerSocket(PortNr); - } catch(java.net.BindException be){ - cout.println("BindException occured"); - cout.println("check if the port "+PortNr+" is already in use"); - return false; - } catch(Exception e){ - cout.println("unable to create a ServerSocket" + e); - e.printStackTrace(); - return false; - } - return true; - } - - /** waits for request from clients - * for each new client a new socket communicationis created - */ - public void run(){ - cout.println("\nwaiting for requests"); - showPrompt(); - while(running){ - try{ - Socket S = SS.accept(); - Clients++; - if(trace){ - cout.println("\na new client is connected"); - cout.println("number of clients :"+Clients); - showPrompt(); - } - (new Server(S)).start(); - } catch(Exception e){ - cout.println("error in communication" + e); - showPrompt(); - } - } - - } - - - private static void showUsage(){ - cout.println("java -classpath .: OptimizerServer PORT [options] "); - cout.println(" : jar file containing the JPL (prolog) API"); - cout.println("PORT : port for the server"); - cout.println("[Options can be :"); - cout.println(" -autoquit : exits the server if the last client disconnects"); - cout.println(" -trace_methods : enables tracing of method calls (for debugging)"); - cout.println(" -trace_instructions : enables tracing of instructions (for debugging)"); - cout.println(" -trace_commands : enables tracing of input/output"); - cout.println(" -encoding enc : switch the output encoding"); - } - - - /** creates a new server object - * process inputs from the user - * available commands are - * client : prints out the number of connected clients - * quit : shuts down the server - */ - public static void main(String[] args){ - cout = System.out; - if(args.length<1){ - showUsage(); - System.exit(1); - } - // process options - Runtime rt = Runtime.getRuntime(); - int pos = 1; - String console_enc = "utf-8"; // standard - while(pos=args.length){ - showUsage(); - System.exit(1); - } - console_enc = args[pos+1]; - pos++; - pos++; - } else if(args[pos].equals("-trace_commands")){ - trace=true; - pos++; - } else { - cout.println("unknown option " + args[pos]); - showUsage(); - System.exit(1); - } - } - - if(!console_enc.equals("utf-8")){ - SortedMap available = Charset.availableCharsets(); - if(!available.containsKey(console_enc)){ - cout.println("encoding " + console_enc + " unknown"); - cout.println(" Available encodinga are : "); - cout.println(available.keySet()); - System.exit(1); - } - try { - cout = new PrintStream(System.out, true, console_enc); - } catch(Exception e){ - cout = System.out; - cout.println("Problem in changing output encoding, use utf-8"); - e.printStackTrace(); - } - } - - - cout.println("\n\n"); - printLicence(cout); - cout.println("\n"); - String arg = args[0]; - OptimizerServer OS = new OptimizerServer(); - try{ - int P = java.lang.Integer.parseInt(arg); - if(P<=0){ - System.err.println("the Portnumber must be greater then zero"); - System.exit(1); - } - OS.PortNr=P; - }catch(Exception e){ - System.err.println("the Portnumber must be an integer"); - System.exit(1); - } - - try{ - Class.forName("org.jpl7.fli.Prolog"); // ensure to load the jpl library - } catch(Exception e){ - System.err.println("loading prolog class failed"); - System.exit(1); - } - - if(! OS.initialize()){ - cout.println("initialization failed"); - System.exit(1); - } - if(!OS.createServer()){ - cout.println("creating Server failed"); - System.exit(1); - } - OS.running = true; - OS.start(); - try{ - BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); - cout.print("optserver >"); - String command = ""; - Vector ResVector = new Vector(); - while(!command.equals("quit")){ - command = in.readLine(); - if(command==null){ - command = ""; - continue; - } - command = command.trim(); - if(command.equals("clients")){ - cout.println("Number of Clients: "+ Clients); - }else if(command.equals("quit")){ - if( Clients > 0){ - cout.print("clients exists ! shutdown anyway (y/n) >"); - String answer = in.readLine().trim().toLowerCase(); - if(!answer.startsWith("y")) - command=""; - } - } else if(command.equals("trace-on")){ - trace=true; - cout.println("tracing is activated"); - } else if(command.equals("trace-off")){ - trace=false; - cout.println("tracing is deactivated"); - } else if(command.equals("help") | command.equals("?") ){ - cout.println("quit : quits the server "); - cout.println("clients : prints out the number of connected clients"); - cout.println("trace-on : prints out messages about command, optimized command, open database"); - cout.println("trace-off : disable messages"); - } else if(command.startsWith("exec")){ - String cmdline = command.substring(4,command.length()).trim(); - execute(cmdline,ResVector); - }else if(!command.equals("")){ - cout.println("unknow command, try help show a list of valid commands"); - } - if(!command.equals("quit")) - showPrompt(); - - } - OS.running = false; - }catch(Exception e){ - OS.running = false; - cout.println("error in reading commands"); - if(trace) - e.printStackTrace(); - } - try{ - Query q = new Query("halt"); - command(q,null); - } catch(Exception e){ - System.err.println(" error in shutting down the prolog engine"); - } - - } - - - /** Prints out the licence information of this software **/ - public static void printLicence(PrintStream out){ - cout.println(" Copyright (C) 2006, University in Hagen, "); - cout.println(" Faculty of Mathematics and Computer Science, "); - cout.println(" Database Systems for New Applications. \n"); - - cout.println(" This is free software; see the source for copying conditions."); - cout.println(" There is NO warranty; not even for MERCHANTABILITY or FITNESS "); - cout.println(" FOR A PARTICULAR PURPOSE."); - } - - /** Converts a string into OS_pl_encoding **/ - private static String encode(String src){ - if(OS_pl_encoding==null){ - return src; - } - try{ - byte[] encodedBytes = src.getBytes(OS_pl_encoding); - return new String(encodedBytes, "UTF-8"); - } catch(Exception e){ - System.err.println("Used encoding not supported\n" + e); - return src; - } - } - - /** Converts a string from OS_pl_encoding **/ - private static String decode(String src){ - if(OS_pl_encoding==null){ - return src; - } - try{ - byte[] encodedBytes = src.getBytes("UTF-8"); - return new String(encodedBytes, OS_pl_encoding); - } catch(Exception e){ - System.err.println("Used encoding not supported\n" + e); - return src; - } - } - - - - - private static String OS_pl_encoding = null; - - - private boolean optimizer_loaded = false; - private int PortNr = 1235; - private static int Clients = 0; - private static boolean quitAfterDisconnect = false; - private ServerSocket SS; - private boolean running; - private static String openedDatabase =""; - private static boolean trace = true; - private static Object SyncObj = new Object(); - private static PrintStream cout; - -} - - - - diff --git a/OptServer/70/makefile b/OptServer/70/makefile deleted file mode 100755 index 2de2dc82b8..0000000000 --- a/OptServer/70/makefile +++ /dev/null @@ -1,44 +0,0 @@ -#This file is part of SECONDO. - -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. - -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. - -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../makefile.env - -ifdef JPL_JAR -CLASSPATH=$(JPL_JAR) -else -CLASSPATH=$(JPL_CLASSPATH) -endif - -BASIC_OPT_DIR=$(OPTDIR)/../OptimizerBasic - - -.PHONY:all -all: $(OPTDIR)/OptimizerServer.class $(BASIC_OPT_DIR)/OptimizerServer.class - -$(OPTDIR)/OptimizerServer.class: OptimizerServer.java - $(JAVAC) -classpath $(CLASSPATH) -d $(OPTDIR) OptimizerServer.java - -$(BASIC_OPT_DIR)/OptimizerServer.class: OptimizerServer.java - $(JAVAC) -classpath $(CLASSPATH) -d $(BASIC_OPT_DIR) OptimizerServer.java - - -.PHONY:clean -clean: - rm -f $(OPTDIR)/*.class - rm -f $(BASIC_OPT_DIR)/*.class diff --git a/OptServer/82/OptimizerServer.java b/OptServer/82/OptimizerServer.java deleted file mode 100755 index 0d6a45330c..0000000000 --- a/OptServer/82/OptimizerServer.java +++ /dev/null @@ -1,925 +0,0 @@ -//This file is part of SECONDO. - -//Copyright (C) 2021, University in Hagen, Department of Computer Science, -//Database Systems for New Applications. - -//SECONDO is free software; you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation; either version 2 of the License, or -//(at your option) any later version. - -//SECONDO is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with SECONDO; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import java.io.*; -import java.net.*; -import java.util.*; - - -import org.jpl7.*; -import java.nio.charset.Charset; -import java.util.SortedMap; - - - -public class OptimizerServer extends Thread{ - -static { - System.loadLibrary( "jpl" ); - System.loadLibrary( "regSecondo" ); - } - - - public static native int registerSecondo(); - - - - - /** shows a prompt at the console - */ - private static void showPrompt(){ - cout.print("\n opt-server > "); - } - - - /** init prolog - * register the secondo predicate - * loads the optimizer prolog code - */ - private boolean initialize(){ - // later here is to invoke the init function which - // registers the Secondo(command,Result) predicate to prolog - if(registerSecondo()!=0){ - System.err.println("error in registering the secondo predicate "); - return false; - } - //cout.println("registerSecondo successful"); - try{ - - String[] plargs = {"--stack-limit=256M"}; - boolean ok = JPL.init(plargs); - - // VTA - 18.09.2006 - // I added this piece of code in order to run with newer versions - // of prolog. Without this code, the libraries (e.g. lists.pl) are - // not automatically loaded. It seems that something in our code - // (auxiliary.pl and calloptimizer.pl) prevents them to be - // automatically loaded. In order to solve this problem I added - // a call to 'member(x, [x]).' so that the libraries are loaded - // before running our scripts. - Term[] args = new Term[2]; - args[0] = new Atom("x"); - args[1] = org.jpl7.Util.termArrayToList( new Term[] { new Atom("x") } ); - Query q = new Query("member",args); - if(!q.hasSolution()){ - cout.println("error in the member call'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom("auxiliary"); - q = new Query("consult",args); - if(!q.hasSolution()){ - cout.println("error in loading 'auxiliary.pl'"); - return false; - } - - args = new Term[1]; - args[0] = new Atom("calloptimizer"); - q = new Query("consult",args); - if(!q.hasSolution()){ - cout.println("error in loading 'calloptimizer.pl'"); - return false; - } - return true; - } catch(Exception e){ - cout.println("Exception in initialization "+e); - e.printStackTrace(); - return false; - } - } - - - - public static boolean halt(){ - try{ - Query q = new Query("halt"); - boolean res = command(q,null); - return res; - } catch(Exception e){ - System.err.println(" error in shutting down the prolog engine"); - e.printStackTrace(); - return false; - } - } - - /** invokes a prolog predicate - * all terms in variables must be contained in arguments - * variables and results can be null if no result is desired - */ - synchronized private static boolean command(Query pl_query, Vector results){ - if(pl_query==null) - return false; - try{ - if(trace){ - cout.println("execute query: "+pl_query); - } - String ret =""; - int number =0; // the number of solutions - if(results!=null) - results.clear(); - while(pl_query.hasMoreSolutions()){ - number++; - Map solution = pl_query.nextSolution(); - if(results!=null){ - ret = ""; - if(solution.size()<=0){ - results.add("yes"); - } else{ - Set vars = solution.keySet(); - Iterator it = vars.iterator(); - int varnum =0; - while(it.hasNext()){ - String k = it.next(); - if (varnum>0) ret += " $$$ "; - ret += ( k + " = " + solution.get(k)); - varnum++; - } - results.add(ret); - } - } - } - if(number == 0){ - if(trace) - cout.println("no solution found for' "+pl_query.goal() +"/"+pl_query.goal().arity()); - return false; - } else{ - // check if the used database is changed - Query dbQuery = new Query("databaseName(X)"); - if(dbQuery.hasMoreSolutions()){ - Map sol = dbQuery.nextSolution(); - String v = sol.keySet().iterator().next(); - String name = ""+sol.get(v); - if(!name.equals(openedDatabase)){ - if(trace){ - cout.println("use database "+ name); - } - openedDatabase=name; - } - - } else{ // no database open - openedDatabase = ""; - } - - return true; - } - } catch(Exception e){ - if(trace){ - cout.println("exception in calling the "+pl_query.goal()+"-predicate"+e); - e.printStackTrace(); - } - return false; - } - } - - - /** analyzed the given string and extract the command and the argumentlist - *
    then the given command is executed - * all Solutions are stored into the Vector Solution - */ - private synchronized static boolean execute(String command,Vector Solution){ - if(Solution!=null) - Solution.clear(); - - // clients should not have the possibility - // to shut down the Optimizer-Server - command = command.trim(); - if(command.startsWith("halt ") || command.equals("halt")) - return false; - - Vector TMPVars = new Vector(); - if(trace){ - cout.println("analyse command: "+command); - } - command = encode(command); - try{ - Query pl_query = new Query(command); - if(pl_query==null){ - if(trace) - cout.println("error in parsing command: "+command); - return false; - } - boolean res = command(pl_query,Solution); - - if(res & trace & Solution!=null){ // successful - if(Solution.size()==0) - cout.println("Yes"); - else - for(int i=0;i 1){ - allret += "\n"; - } - Map solution = pl_query.nextSolution(); - if(solution.size()!=1){ - if(trace){ - cout.println("Error: optimization returns more than a single binding"); - } - return query; - } - Iterator it = solution.keySet().iterator(); - while(it.hasNext()){ - allret += "" + solution.get(it.next()); - } - if(number==1){ - ret1 = allret; - } - } - if(number>1){ - if(trace){ - cout.println("Error: optimization returns more than one solution"); - cout.println("Solutions are \n" + allret); - } - ret1 = ret1.trim(); - if(ret1.startsWith("'") && ret1.endsWith("'")){ - if(ret1.length()==2){ - ret1 = ""; - } else{ - ret1 = ret1.substring(1,ret1.length()-1); - } - } - - return decode(ret1); - } - - if(number==0){ - if(trace) - cout.println("optimization failed - no solution found"); - return query; - } - else{ - if(trace) - cout.println("\n optimization-result : "+allret+"\n"); - - // free ret from enclosing '' - allret = allret.trim(); - if(allret.startsWith("'") && allret.endsWith("'")){ - if(allret.length()==2){ - allret = ""; - } else{ - allret = allret.substring(1,allret.length()-1); - } - } - - return decode(allret); - } - } catch(Exception e){ - if(trace) { - cout.println("\n Exception :"+e); - e.printStackTrace(); - } - showPrompt(); - return query; - } - - } - - /** if Name is not the database currenty used, - * the opened database is closed and the database - * Name is opened - */ - private synchronized boolean useDatabase(String Name){ - if(openedDatabase.equals(Name)){ - return true; - } - Term[] arg = new Term[1]; - if(!openedDatabase.equals("")){ - if(trace) - cout.println("close the opened database"); - Query Q = new Query("secondo('close database')"); - command(Q,null); - } - - Query Q_open = new Query("secondo('open database "+Name+"')"); - showPrompt(); - boolean res = command(Q_open,null); - openedDatabase = res?Name:""; - return res; - } - - - - /** a class for communicate with a client */ - private class Server extends Thread{ - - /** creates a new Server from given socket */ - public Server(Socket S){ - this.S = S; - //cout.println("requesting from client"); - try{ - // communication with client, always use UTF-8 encoding - try{ - in = new BufferedReader(new InputStreamReader(S.getInputStream(),"UTF-8")); - } catch(UnsupportedEncodingException e){ - System.err.println("Encoding UTF-8 not supported"); - in = new BufferedReader(new InputStreamReader(S.getInputStream())); - } - try{ - out = new BufferedWriter(new OutputStreamWriter(S.getOutputStream(),"UTF-8")); - } catch(UnsupportedEncodingException e){ - System.err.println("Encoding UTF-8 not supported"); - out = new BufferedWriter(new OutputStreamWriter(S.getOutputStream())); - } - String First = in.readLine(); - //cout.println("receive :"+First); - if(First==null){ - if(trace) - cout.println("connection broken"); - showPrompt(); - running=false; - return; - } - if(First.equals("")){ - out.write("\n",0,12); - out.flush(); - running = true; - }else{ - if(trace) - cout.println("protocol-error , close connection (expect: , received :"+First); - showPrompt(); - running = false; - } - }catch(Exception e){ - if(trace){ - cout.println("Exception occured "+e); - e.printStackTrace(); - } - showPrompt(); - running = false; - } - } - - /** disconnect this server from a client */ - private void disconnect(){ - // close Connection if possible - try{ - if(S!=null) - S.close(); - }catch(Exception e){ - if(trace){ - cout.println("Exception in closing connection "+e); - e.printStackTrace(); - } - } - OptimizerServer.Clients--; - if(trace){ - cout.println("\nbye client"); - cout.println("number of clients is :"+ OptimizerServer.Clients); - } - if((OptimizerServer.Clients==0) && OptimizerServer.quitAfterDisconnect){ - // OptimizerServer.halt(); // not allowed from this tread - System.exit(0); - } - showPrompt(); - } - - - - - /** processes requests from clients until the client - * finish the connection or an error occurs - */ - public void run(){ - if(!running){ - disconnect(); - return; - } - - boolean execFlag=false; // flags for control execute or optimize request - try{ - String input = in.readLine(); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - while(!input.equals("")){ - - if(!input.equals("") && !input.equals("") ){ // protocol_error - if(trace) - cout.println("protocol error( expect: or , found:"+input); - disconnect(); - return; - } - //cout.println("receive "+input+" from client"); - - execFlag = input.equals(""); - // read the database name - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - if(!input.equals("")){ // protocol_error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - String Database = in.readLine(); - - //cout.println("receive "+Database+" from client"); - - if(Database==null){ - cout.println("connection is broken"); - disconnect(); - return; - }else { - Database = Database.trim(); - } - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - }else{ - input = input.trim(); - } - if(!input.equals("")){ // protocol error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - }else{ - input = input.trim(); - } - if(!input.equals("")){ // protocol error - if(trace) - cout.println("protocol error( expect: , found:"+input); - disconnect(); - return; - } - - StringBuffer res = new StringBuffer(); - // build the query from the next lines - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - //cout.println("receive"+input); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - while(!input.equals("")){ - res.append(input + "\n"); - input = in.readLine(); - //cout.println("receive"+input); - if(input==null){ - if(trace) - cout.println("connection is broken"); - disconnect(); - return; - } - } - - input = in.readLine(); - - //cout.println("receive "+input+" from client"); - - if(input==null){ - cout.println("connection is broken"); - disconnect(); - return; - } - - if(! (input.equals("") & !execFlag) & !(input.equals("") & execFlag)){ //protocol-error - if(trace) - cout.println("protocol error( expect: or , found:"+input); - disconnect(); - return; - } - - String Request = res.toString().trim(); - - //cout.println("Request is " + Request ); - - Vector V = new Vector(); - synchronized(SyncObj){ - useDatabase(Database); - if(!execFlag){ - String opt = OptimizerServer.this.optimize(Request); - if(!opt.equals(Request)) - V.add(opt); - }else{ - execute(Request,V); - } - } - - showPrompt(); - - out.write("\n",0,9); - String answer; - for(int i=0;i\n",0,10); - out.flush(); - input = in.readLine().trim(); - - //cout.println("receive "+input+" from client"); - - if (input==null){ - cout.println("connection broken"); - showPrompt(); - disconnect(); - return; - } - } // while - cout.println("connection ended normally"); - showPrompt(); - }catch(IOException e){ - cout.println("error in socket-communication" + e); - - disconnect(); - showPrompt(); - return; - } - disconnect(); - } - - - private BufferedReader in; - private BufferedWriter out; - private boolean running; - private Socket S; - - - - - } - - - - /** creates the server process */ - private boolean createServer(){ - SS=null; - try{ - SS = new ServerSocket(PortNr); - } catch(java.net.BindException be){ - cout.println("BindException occured"); - cout.println("check if the port "+PortNr+" is already in use"); - return false; - } catch(Exception e){ - cout.println("unable to create a ServerSocket" + e); - e.printStackTrace(); - return false; - } - return true; - } - - /** waits for request from clients - * for each new client a new socket communicationis created - */ - public void run(){ - cout.println("\nwaiting for requests"); - showPrompt(); - while(running){ - try{ - Socket S = SS.accept(); - Clients++; - if(trace){ - cout.println("\na new client is connected"); - cout.println("number of clients :"+Clients); - showPrompt(); - } - (new Server(S)).start(); - } catch(Exception e){ - cout.println("error in communication" + e); - showPrompt(); - } - } - - } - - - private static void showUsage(){ - cout.println("java -classpath .: OptimizerServer PORT [options] "); - cout.println(" : jar file containing the JPL (prolog) API"); - cout.println("PORT : port for the server"); - cout.println("[Options can be :"); - cout.println(" -autoquit : exits the server if the last client disconnects"); - cout.println(" -trace_methods : enables tracing of method calls (for debugging)"); - cout.println(" -trace_instructions : enables tracing of instructions (for debugging)"); - cout.println(" -trace_commands : enables tracing of input/output"); - cout.println(" -encoding enc : switch the output encoding"); - } - - - /** creates a new server object - * process inputs from the user - * available commands are - * client : prints out the number of connected clients - * quit : shuts down the server - */ - public static void main(String[] args){ - cout = System.out; - if(args.length<1){ - showUsage(); - System.exit(1); - } - // process options - Runtime rt = Runtime.getRuntime(); - int pos = 1; - String console_enc = "utf-8"; // standard - while(pos=args.length){ - showUsage(); - System.exit(1); - } - console_enc = args[pos+1]; - pos++; - pos++; - } else if(args[pos].equals("-trace_commands")){ - trace=true; - pos++; - } else { - cout.println("unknown option " + args[pos]); - showUsage(); - System.exit(1); - } - } - - if(!console_enc.equals("utf-8")){ - SortedMap available = Charset.availableCharsets(); - if(!available.containsKey(console_enc)){ - cout.println("encoding " + console_enc + " unknown"); - cout.println(" Available encodinga are : "); - cout.println(available.keySet()); - System.exit(1); - } - try { - cout = new PrintStream(System.out, true, console_enc); - } catch(Exception e){ - cout = System.out; - cout.println("Problem in changing output encoding, use utf-8"); - e.printStackTrace(); - } - } - - - cout.println("\n\n"); - printLicence(cout); - cout.println("\n"); - String arg = args[0]; - OptimizerServer OS = new OptimizerServer(); - try{ - int P = java.lang.Integer.parseInt(arg); - if(P<=0){ - System.err.println("the Portnumber must be greater then zero"); - System.exit(1); - } - OS.PortNr=P; - }catch(Exception e){ - System.err.println("the Portnumber must be an integer"); - System.exit(1); - } - - try{ - Class.forName("org.jpl7.fli.Prolog"); // ensure to load the jpl library - } catch(Exception e){ - System.err.println("loading prolog class failed"); - System.exit(1); - } - - if(! OS.initialize()){ - cout.println("initialization failed"); - System.exit(1); - } - if(!OS.createServer()){ - cout.println("creating Server failed"); - System.exit(1); - } - OS.running = true; - OS.start(); - try{ - BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); - cout.print("optserver >"); - String command = ""; - Vector ResVector = new Vector(); - while(!command.equals("quit")){ - command = in.readLine(); - if(command==null){ - command = ""; - continue; - } - command = command.trim(); - if(command.equals("clients")){ - cout.println("Number of Clients: "+ Clients); - }else if(command.equals("quit")){ - if( Clients > 0){ - cout.print("clients exists ! shutdown anyway (y/n) >"); - String answer = in.readLine().trim().toLowerCase(); - if(!answer.startsWith("y")) - command=""; - } - } else if(command.equals("trace-on")){ - trace=true; - cout.println("tracing is activated"); - } else if(command.equals("trace-off")){ - trace=false; - cout.println("tracing is deactivated"); - } else if(command.equals("help") | command.equals("?") ){ - cout.println("quit : quits the server "); - cout.println("clients : prints out the number of connected clients"); - cout.println("trace-on : prints out messages about command, optimized command, open database"); - cout.println("trace-off : disable messages"); - } else if(command.startsWith("exec")){ - String cmdline = command.substring(4,command.length()).trim(); - execute(cmdline,ResVector); - }else if(!command.equals("")){ - cout.println("unknow command, try help show a list of valid commands"); - } - if(!command.equals("quit")) - showPrompt(); - - } - OS.running = false; - }catch(Exception e){ - OS.running = false; - cout.println("error in reading commands"); - if(trace) - e.printStackTrace(); - } - try{ - Query q = new Query("halt"); - command(q,null); - } catch(Exception e){ - System.err.println(" error in shutting down the prolog engine"); - } - - } - - - /** Prints out the licence information of this software **/ - public static void printLicence(PrintStream out){ - cout.println(" Copyright (C) 2021, University in Hagen, "); - cout.println(" Faculty of Mathematics and Computer Science, "); - cout.println(" Database Systems for New Applications. \n"); - - cout.println(" This is free software; see the source for copying conditions."); - cout.println(" There is NO warranty; not even for MERCHANTABILITY or FITNESS "); - cout.println(" FOR A PARTICULAR PURPOSE."); - } - - /** Converts a string into OS_pl_encoding **/ - private static String encode(String src){ - if(OS_pl_encoding==null){ - return src; - } - try{ - byte[] encodedBytes = src.getBytes(OS_pl_encoding); - return new String(encodedBytes, "UTF-8"); - } catch(Exception e){ - System.err.println("Used encoding not supported\n" + e); - return src; - } - } - - /** Converts a string from OS_pl_encoding **/ - private static String decode(String src){ - if(OS_pl_encoding==null){ - return src; - } - try{ - byte[] encodedBytes = src.getBytes("UTF-8"); - return new String(encodedBytes, OS_pl_encoding); - } catch(Exception e){ - System.err.println("Used encoding not supported\n" + e); - return src; - } - } - - - - - private static String OS_pl_encoding = null; - - - private boolean optimizer_loaded = false; - private int PortNr = 1235; - private static int Clients = 0; - private static boolean quitAfterDisconnect = false; - private ServerSocket SS; - private boolean running; - private static String openedDatabase =""; - private static boolean trace = true; - private static Object SyncObj = new Object(); - private static PrintStream cout; - -} - - - - diff --git a/OptServer/82/makefile b/OptServer/82/makefile deleted file mode 100755 index 2de2dc82b8..0000000000 --- a/OptServer/82/makefile +++ /dev/null @@ -1,44 +0,0 @@ -#This file is part of SECONDO. - -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. - -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. - -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../../makefile.env - -ifdef JPL_JAR -CLASSPATH=$(JPL_JAR) -else -CLASSPATH=$(JPL_CLASSPATH) -endif - -BASIC_OPT_DIR=$(OPTDIR)/../OptimizerBasic - - -.PHONY:all -all: $(OPTDIR)/OptimizerServer.class $(BASIC_OPT_DIR)/OptimizerServer.class - -$(OPTDIR)/OptimizerServer.class: OptimizerServer.java - $(JAVAC) -classpath $(CLASSPATH) -d $(OPTDIR) OptimizerServer.java - -$(BASIC_OPT_DIR)/OptimizerServer.class: OptimizerServer.java - $(JAVAC) -classpath $(CLASSPATH) -d $(BASIC_OPT_DIR) OptimizerServer.java - - -.PHONY:clean -clean: - rm -f $(OPTDIR)/*.class - rm -f $(BASIC_OPT_DIR)/*.class diff --git a/OptServer/makefile b/OptServer/makefile deleted file mode 100755 index d95edd0eb2..0000000000 --- a/OptServer/makefile +++ /dev/null @@ -1,94 +0,0 @@ -#This file is part of SECONDO. - -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. - -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. - -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -include ../makefile.env -include ../makefile.optimizer -include ../makefile.jni - -ifeq ($(platform),mac_osx) - JH:= $(shell /usr/libexec/java_home) - JNIINCLUDE:= -I $(JH)/include -I $(JH)/include/darwin -endif - -INCLUDEFLAGS := -I. $(JNIINCLUDE) $(PLINCLUDEFLAGS) -I$(INCLUDEDIR) - -REG_SEC_DLL=$(OPTDIR)/$(DLLPREF)regSecondo.$(JNI_DLLEXT) -BASIC_REG_SEC_DLL=$(OPTDIR)/../OptimizerBasic/$(DLLPREF)regSecondo.$(JNI_DLLEXT) - -ifndef JPL_DLL - #JPL_DLL=$(OPTDIR)/$(DLLPREF)jpl.$(JNI_DLLEXT) - JPL_DLL=../Optimizer/$(DLLPREF)jpl.$(JNI_DLLEXT) -endif - -LINKFILES := $(SECONDO_BUILD_DIR)/UserInterfaces/cmsg.o $(SECONDOPL_DIR)/SecondoPLCS.o $(LIBDIR)/SecondoInterfaceCS.o $(LIBDIR)/SecondoInterfaceGeneral.o - -# Some optional switches used for providing a prolog -# predicate which maximizes the entropy. For details -# refer to "SecondoPL.cpp" and the subdirectory "Optimizer/Entropy" - -ifdef ENTROPY - LINKFILES += $(OPTDIR)/Entropy/Iterative_scaling.o -endif - -LINK_FLAGS := $(ENT_LINK_LIBS) $(LD_LINK_LIBS) \ - $(JNI_CCFLAGS) $(PLLDFLAGS) - -LINKFILES += $(JPL_DLL) - -.PHONY:all -all: jsrc $(BASIC_REG_SEC_DLL) - -$(BASIC_REG_SEC_DLL): $(REG_SEC_DLL) - @echo "Build Basic reg sec" - cp $< $@ - -jsrc: - $(MAKE) -C $(JPLVER) all - -regSecondo.o: regSecondo.c - $(CC) -c -fPIC -g -ggdb -o $@ $(INCLUDEFLAGS) $< - -LINKFILES += $(PL_DLL) - -ifeq ($(platform),win32) - -$(REG_SEC_DLL): regSecondo.o $(LINKFILES) regSeg.def - $(CC) $(DLLFLAGS) -Wl,-soname,jpl.$(JNI_DLLEXT) -o $@ \ - $^ -lsdbnl $(LINK_FLAGS) regSeg.def - -regSeg.def: regSecondo.o - dlltool -z $@.tmp $^ - sed -e "s#\(.*\)@\(.*\)@.*#\1 = \1@\2#g" $@.tmp > $@ - rm $@.tmp - -else -$(REG_SEC_DLL): regSecondo.o $(LINKFILES) - $(CC) $(DLLFLAGS) $(EXEFLAGS) $(LDFLAGS) -o $@ $^ -lsdbnl $(LINK_FLAGS) $(COMMON_LD_FLAGS) -endif - -.PHONY:clean -clean: - $(MAKE) -C 10 clean - $(MAKE) -C 30 clean - $(MAKE) -C 70 clean - $(MAKE) -C 82 clean - rm -f regSecondo.o - rm -f $(REG_SEC_DLL) - rm -f $(BASIC_REG_SEC_DLL) - diff --git a/OptServer/regSecondo.c b/OptServer/regSecondo.c deleted file mode 100644 index a85f876e41..0000000000 --- a/OptServer/regSecondo.c +++ /dev/null @@ -1,20 +0,0 @@ - -#include - - -#include - - -/* - * Class: OptimizerServer - * Method: registerSecondo - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_OptimizerServer_registerSecondo( - JNIEnv * env , - jclass cl){ - int res = registerSecondo(); - return res; - -} - diff --git a/Optimizer/SecondoPLCS b/Optimizer/SecondoPLCS deleted file mode 100755 index 5ea536a010..0000000000 --- a/Optimizer/SecondoPLCS +++ /dev/null @@ -1,5 +0,0 @@ -# -# Startup script for running SECONDOTTY in optimizer mode - -../bin/SecondoCS -pl $* - diff --git a/Optimizer/SecondoPLTTY b/Optimizer/SecondoPLTTY deleted file mode 100755 index bf918e554b..0000000000 --- a/Optimizer/SecondoPLTTY +++ /dev/null @@ -1,30 +0,0 @@ -# -# Startup script for running SECONDOTTY in optimizer mode - -VALGRIND_STD_OPTIONS=" --num-callers=25 --suppressions=../bin/vgs.txt --error-limit=no " -SEC=../bin/SecondoBDB - -if [ "$1" == "--valgrind" ]; then - shift - runner="valgrind $VALGRIND_STD_OPTIONS $SEC" -else -if [ "$1" == "--valgrindlc" ]; then - shift - runner="valgrind $VALGRIND_STD_OPTIONS --leak-check=full $SEC" -else -if [ "$1" == "--profile" ]; then - shift - runner="valgrind --tool=callgrind --dump-instr=yes --trace-jump=yes $SEC" -else - runner="$SEC" -fi -fi -fi - - -if [ $(swipl --help 2>&1 | grep stack-limit | wc -l) -gt 0 ]; then - $runner -pltty $* pl -g true --stack-limit=256M -else - $runner -pltty -L256M -G256M $* pl -g true -fi - diff --git a/Optimizer/SecondoPLTTYCS b/Optimizer/SecondoPLTTYCS deleted file mode 100755 index bd1ca2ec30..0000000000 --- a/Optimizer/SecondoPLTTYCS +++ /dev/null @@ -1,5 +0,0 @@ -# -# Startup script for running SECONDOTTY in optimizer mode - -../bin/SecondoCS -pltty $* - diff --git a/Optimizer/SecondoPLTTYNT b/Optimizer/SecondoPLTTYNT deleted file mode 100755 index 7c649032eb..0000000000 --- a/Optimizer/SecondoPLTTYNT +++ /dev/null @@ -1,32 +0,0 @@ -# -# Startup script for running SECONDOTTY in optimizer mode - -export SECONDO_PARAM_RTFlags="DEBUG:DemangleStackTrace,CMSG:Color,SMI:NoTransactions,CTLG:SkipExamples,SI:PrintCmdTimes" - - -VALGRIND_STD_OPTIONS=" --num-callers=25 --suppressions=../bin/vgs.txt --error-limit=no " -SEC=../bin/SecondoBDB - -if [ "$1" == "--valgrind" ]; then - shift - runner="valgrind $VALGRIND_STD_OPTIONS $SEC" -else -if [ "$1" == "--valgrindlc" ]; then - shift - runner="valgrind $VALGRIND_STD_OPTIONS --leak-check=full $SEC" -else -if [ "$1" == "--profile" ]; then - shift - runner="valgrind --tool=callgrind --dump-instr=yes --trace-jump=yes $SEC" -else - runner="$SEC" -fi -fi -fi - -if [ $(swipl --help 2>&1 | grep stack-limit | wc -l) -gt 0 ]; then - $runner -pltty $* pl -g true --stack-limit=256M -else - $runner -pltty -L256M -G256M $* pl -g true -fi - diff --git a/Optimizer/StartOptServer b/Optimizer/StartOptServer deleted file mode 100755 index 8475cab49a..0000000000 --- a/Optimizer/StartOptServer +++ /dev/null @@ -1,169 +0,0 @@ -# !/bin/bash -#This file is part of SECONDO. - -#Copyright (C) 2004, University in Hagen, Department of Computer Science, -#Database Systems for New Applications. - -#SECONDO is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2 of the License, or -#(at your option) any later version. - -#SECONDO is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with SECONDO; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -# variables of the client part - -AUTOQUIT="" -TRACE="" -HOST="" -PORT="" -CONFIG="" -PSWD="" -USER="" - - -while getopts "h:p:u:s:c:q" Option -do - case $Option in - h ) HOST=$OPTARG ;; - p ) PORT=$OPTARG ;; - c ) CONFIG=$OPTARG ;; - s ) PSWD=$OPTARG ;; - u ) USER=$OPTARG ;; - q ) AUTOQUIT="-autoquit" ;; - t ) TRACE="-trace_commands" ;; - * ) - esac -done - - - -shift $(($OPTIND - 1)) - -# port of the server part - -if [ -z $BASH_ARGV ]; then - S_PORT=1235 -else -# check for integer - x=$1 - if [ "${x/[0-9]*/x}" == "x" ]; then - S_PORT=$x - shift - else - S_PORT=1235 - fi -fi - - -if [ "$SECONDO_PLATFORM" != win32 ]; then - echo"" # unset SWI_HOME_DIR -fi - -if [ "$SECONDO_JAVA" != "" ]; then - JAVA=$SECONDO_JAVA - CLASSPATH=$SECONDO_JAVART -else - JAVA=java -fi - -CLASSPATH=. -if [ "$JPL_JAR" != "" ]; then - CLASSPATH=$CLASSPATH:$JPL_JAR; -else - CLASSPATH=../Jpl/lib/classes:$CLASSPATH -fi - -LIB_PATH=. -if [ "$JPL_DLL" != "" ]; then - if [ -n "$PL_DLL_DIR" ]; then - LIB_PATH=$PL_DLL_DIR:$LIB_PATH - elif [ -n "$PL_LIB_DIR" ]; then - LIB_PATH=$PL_LIB_DIR:$LIB_PATH - fi - LIB_PATH=$(dirname $LIB_PATH:$JPL_DLL) -fi - -OLD_HOST=$SECONDO_HOST -OLD_PORT=$SECONDO_PORT -OLD_CONFIG=$SECONDO_CONFIG -OLD_USER=$SECONDO_USER -OLD_PSWD=$SECONDO_PSWD - -if [ -n "$CONFIG" ]; then - export SECONDO_CONFIG=$CONFIG -fi -if [ -n "$HOST" ]; then - export SECONDO_HOST=$HOST -fi -if [ -n "$PORT" ]; then - export SECONDO_PORT=$PORT -fi -if [ -n "$USER" ]; then - export SECONDO_USER=$USER -fi -if [ -n "$PSWD" ]; then - export SECONDO_PSWD=$PSWD -fi - - -# The JVM handles some SIGSEGVs itself (implicit null checks, stack banging). -# Prolog installs its SIGSEGV handler on top of the JVM's and the next -# JVM-internal SIGSEGV reaches Prolog, which aborts with "received fatal signal 11". -# libjsig chains the two handlers and avoids the crash. -if [ "$SECONDO_PLATFORM" == mac_osx ]; then - JSIG=$(find -L $J2SDK_ROOT -name libjsig.dylib | head -n 1) - if [ -n "$JSIG" ]; then - export DYLD_INSERT_LIBRARIES=$JSIG${DYLD_INSERT_LIBRARIES:+:$DYLD_INSERT_LIBRARIES} - fi -else - JSIG=$(find -L $J2SDK_ROOT -name libjsig.so | head -n 1) - if [ -n "$JSIG" ]; then - export LD_PRELOAD=$JSIG${LD_PRELOAD:+:$LD_PRELOAD} - fi -fi - -if [ -z "$JSIG" ]; then - echo "Warning: libjsig not found under J2SDK_ROOT=$J2SDK_ROOT;" \ - "the JVM and SWI-Prolog will fight over SIGSEGV." -else - JAVAPATH=$(dirname $JSIG) - export LD_LIBRARY_PATH=$JAVAPATH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} -fi - -cmd="$JAVA -Djava.library.path=$LIB_PATH -classpath $CLASSPATH OptimizerServer $S_PORT $AUTOQUIT $TRACE $*" - -echo $cmd - -if [ -n "$FILE" ]; then - $cmd <$FILE -else - $cmd -fi - -if [ -n "$CONFIG" ]; then - export SECONDO_CONFIG=$OLD_CONFIG -fi -if [ -n "$HOST" ]; then - export SECONDO_HOST=$OLD_HOST -fi -if [ -n "$PORT" ]; then - export SECONDO_PORT=$OLD_PORT -fi -if [ -n "$USER" ]; then - export SECONDO_USER=$OLD_USER -fi -if [ -n "$PSWD" ]; then - export SECONDO_PSWD=$OLD_PSWD -fi - - - diff --git a/Optimizer/TestOptServer b/Optimizer/TestOptServer deleted file mode 100755 index 257f49740b..0000000000 --- a/Optimizer/TestOptServer +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash -# -# Functional test for the JPL optimizer server (OptServer). -# -# TestOptimizer drives the optimizer through the embedded Prolog interface -# (SecondoBDB -pl). This test instead exercises the *server* path used by the -# Java GUI: it starts a Secondo server plus the OptServer (OptimizerServer + -# regSecondo, talking to Prolog via JPL), connects a socket client, and asks -# the server to optimize an SQL query. That validates the whole JPL bridge -# (jpl.jar / libjpl, regSecondo, the Prolog optimizer and the wire protocol) -# end to end. - -set -u - -buildDir=${SECONDO_BUILD_DIR:-} -if [ -z "$buildDir" ]; then - echo "Error: SECONDO_BUILD_DIR is not set." - exit 1 -fi - -# python3 speaks the OptServer's line protocol below. Skip (do not fail) if it -# is unavailable, matching how optional tests are handled elsewhere. -if ! command -v python3 >/dev/null 2>&1; then - echo "SKIP: python3 not found, cannot run the OptServer protocol client." - exit 0 -fi - -export SECONDO_CONFIG=${SECONDO_CONFIG:-$buildDir/bin/SecondoConfig.ini} -export PATH="$buildDir/bin:$PATH" - -# The Secondo server and the OptServer use the ports from SecondoConfig.ini -# (defaults: 1234 for the Secondo server, 1235 for the OptServer). -SEC_PORT=1234 -OPT_PORT=1235 -DBNAME=opt -QUERY="select * from ten" - -# Explicit template so this works with both GNU and BSD/macOS mktemp. -home=$(mktemp -d "${TMPDIR:-/tmp}/TestOptServer.XXXXXX") -export SECONDO_PARAM_SecondoHome="$home" -client="$home/optclient.py" -monPid="" optPid="" - -cleanup() { - # Stop the OptServer (StartOptServer + its java child) and the Secondo server - # (SecondoMonitor + the SecondoBDB it forks) by killing each process together - # with its children, then reap them so their termination signals do not - # disturb this script. Only PIDs we started are targeted (no broad pkill -f). - local pid - for pid in "$optPid" "$monPid"; do - [ -n "$pid" ] || continue - pkill -P "$pid" 2>/dev/null - kill "$pid" 2>/dev/null - done - wait 2>/dev/null - rm -rf "$home" -} -trap cleanup EXIT - -# Wait until a TCP port accepts connections (bash /dev/tcp, no extra tools). -wait_port() { - local port=$1 tries=$2 i - for ((i = 0; i < tries; i++)); do - if (exec 3<>"/dev/tcp/127.0.0.1/$port") 2>/dev/null; then - exec 3>&- 3<&- - return 0 - fi - sleep 1 - done - return 1 -} - -echo "*** OptServer test: creating database '$DBNAME' ***" -SecondoTTYBDB >"$home/db.log" 2>&1 </dev/null -SecondoMonitor -s >"$home/monitor.log" 2>&1 & -monPid=$! -popd >/dev/null -if ! wait_port "$SEC_PORT" 30; then - echo "Secondo server did not come up on port $SEC_PORT:"; cat "$home/monitor.log"; exit 1 -fi - -echo "*** OptServer test: starting OptServer ***" -pushd "$buildDir/Optimizer" >/dev/null -./StartOptServer >"$home/optserver.log" 2>&1 & -optPid=$! -popd >/dev/null -if ! wait_port "$OPT_PORT" 60; then - echo "OptServer did not come up on port $OPT_PORT:"; cat "$home/optserver.log"; exit 1 -fi - -echo "*** OptServer test: optimizing \"$QUERY\" on database '$DBNAME' ***" -cat >"$client" <<'PYEOF' -import socket, sys -host, port, db, query = "127.0.0.1", int(sys.argv[1]), sys.argv[2], sys.argv[3] -s = socket.create_connection((host, port), timeout=60) -s.settimeout(60) -f = s.makefile("rw", encoding="utf-8", newline="\n") -def send(line): f.write(line + "\n"); f.flush() - -send("") -who = f.readline().strip() -if who != "": - print("handshake failed, expected , got:", repr(who)); sys.exit(2) - -send(""); send(""); send(db); send("") -send(""); send(query); send(""); send("") - -ans = f.readline().strip() -if ans != "": - print("protocol error, expected , got:", repr(ans)); sys.exit(3) - -plan = [] -while True: - line = f.readline() - if line == "": - print("connection broken while reading plan"); sys.exit(4) - if line.strip() == "": - break - plan.append(line.rstrip("\n")) -send("") - -plan = "".join(plan).strip() -print("optimized plan:", plan) -# select * from a relation must yield a plan that feeds the relation. -if not plan or "feed" not in plan: - print("unexpected / empty plan"); sys.exit(5) -print("OptServer test OK") -PYEOF - -python3 "$client" "$OPT_PORT" "$DBNAME" "$QUERY" -rc=$? -if [ $rc -ne 0 ]; then - echo "OptServer client failed (rc=$rc). OptServer log:" - tail -40 "$home/optserver.log" -fi -exit $rc diff --git a/Optimizer/TestSecondoPLStartup b/Optimizer/TestSecondoPLStartup index 3b6f7751c4..67fe8eeb7b 100755 --- a/Optimizer/TestSecondoPLStartup +++ b/Optimizer/TestSecondoPLStartup @@ -16,6 +16,12 @@ # # See UserInterfaces/SecondoPLMode.cpp (the library(error) preload) and # UserInterfaces/SecondoPL.cpp (initEmbeddedOptimizer, same fix). +# +# The second half of the test covers the standalone TTY (SecondoBDB) on the same +# database. That binary is the one client with no server to ask which of the +# three input languages a typed command is written in, so it applies the shared +# rules (include/SQLLanguage.h) itself -- which makes it the place where a +# misrouted command shows up first. libFile="libutil.sh" buildDir=${SECONDO_BUILD_DIR} @@ -36,9 +42,11 @@ export SECONDO_CONFIG=$buildDir/bin/SecondoConfig.ini # TestSecondoPLStartup.log, so keep our own diagnostics out of that file. logFile="${buildDir}/Optimizer/TestSecondoPLStartup.restore.log" plLog="${buildDir}/Optimizer/TestSecondoPLStartup.secondopl.log" +ttyLog="${buildDir}/Optimizer/TestSecondoPLStartup.tty.log" : > "$logFile" printf "%s\n" "Restore log: $logFile" printf "%s\n" "SecondoPL log: $plLog" +printf "%s\n" "SecondoTTYBDB log: $ttyLog" declare -i error=0 @@ -83,10 +91,96 @@ if ! grep -qE "^No : [0-9]+" "$plLog"; then let error++ fi +# --------------------------------------------------------------------------- +# The standalone TTY: language routing and the optimizer's cost estimate. +# --------------------------------------------------------------------------- +# +# Everything below is typed the way a user types it -- no "sql" prefix, no +# command level -- so it is the routing itself that is under test. Note that +# "delete database opt" is a *kernel* command even though it starts with a word +# the optimizer also uses; it must reach the kernel and be told that a database +# is still open, not be handed to the optimizer. +cd "$buildDir/bin" || exit 1 +./SecondoTTYBDB > "$ttyLog" 2>&1 <<'EOF' +open database opt; +query ten count; +(list databases); +select * from ten; +select * from ten as t where [t.No > 5]; +showOptions; +optimizer select * from ten; +delete database opt; +drop database opt; +close database; +q; +EOF + +cat "$ttyLog" >> "$logFile" + +# 3) A plain kernel command in text syntax still runs at the kernel. +if ! grep -qE "^10$" "$ttyLog"; then + printf "%s\n" "FAILED: 'query ten count' did not return 10." + let error++ +fi + +# 4) A command in nested list syntax still parses as a list. +if ! grep -q "OPT" "$ttyLog"; then + printf "%s\n" "FAILED: '(list databases)' did not list the opt database." + let error++ +fi + +# 5) SQL is recognized without any prefix: the plan is reported and executed. +if ! grep -q "Optimized plan: query ten feed consume" "$ttyLog"; then + printf "%s\n" "FAILED: 'select * from ten' was not optimized." + let error++ +fi +if ! grep -qE "^No : 10$" "$ttyLog"; then + printf "%s\n" "FAILED: 'select * from ten' did not return the ten tuples." + let error++ +fi + +# 6) The optimizer's cost estimate reaches the user. "select * from ten" alone +# is not enough: the optimizer costs a plain scan at 0, which is suppressed. +# A query with a predicate has a real estimate, so this is what proves the +# costs element of the answer is carried through and displayed. +if ! grep -qE "Estimated costs: [0-9]+(\.[0-9]+)?" "$ttyLog"; then + printf "%s\n" "FAILED: no cost estimate for 'select * from ten as t where [t.No > 5]'." + let error++ +fi + +# 7) A bare optimizer directive is routed to the optimizer, not to the kernel. +if ! grep -q "Optimizer options (and sub-options):" "$ttyLog"; then + printf "%s\n" "FAILED: 'showOptions' did not reach the optimizer." + let error++ +fi + +# 8) The "optimizer " prefix in front of SQL optimizes without executing. +if ! grep -q "Plan only -- not executed." "$ttyLog"; then + printf "%s\n" "FAILED: 'optimizer select ...' did not stop after optimizing." + let error++ +fi + +# 9) Dropping a database is the kernel's business, but both spellings a user +# reaches for start with a word the optimizer also uses ("delete from ...", +# "drop table ..."). A classifier that looks only at that first word hands +# them to the optimizer, and the user gets "no plan found" or "no database is +# open; cannot use the optimizer" instead of the real answer. So: the kernel +# must report the open database, and nothing here may produce an optimizer +# error -- every command above is either a kernel command or valid SQL. +if ! grep -q "A database is open." "$ttyLog"; then + printf "%s\n" "FAILED: 'delete database opt' did not reach the kernel." + let error++ +fi +if grep -qE "cannot use the optimizer|Optimization failed" "$ttyLog"; then + printf "%s\n" "FAILED: a kernel command was routed to the optimizer." + grep -nE "cannot use the optimizer|Optimization failed" "$ttyLog" | head + let error++ +fi + rm -rf "$tempDir" if [ $error -gt 0 ]; then - printf "%s\n" "*** TestSecondoPLStartup: ${error} error(s), see ${plLog} ***" + printf "%s\n" "*** TestSecondoPLStartup: ${error} error(s), see ${plLog} and ${ttyLog} ***" exit 1 fi diff --git a/QueryProcessor/SecondoInterfaceGeneral.cpp b/QueryProcessor/SecondoInterfaceGeneral.cpp index 93912fe855..3aba919623 100755 --- a/QueryProcessor/SecondoInterfaceGeneral.cpp +++ b/QueryProcessor/SecondoInterfaceGeneral.cpp @@ -145,6 +145,9 @@ std::map InitErrorMessages() errors[ERR_CMD_NOT_IMPL_AT_THIS_LEVEL] = "Command not yet implemented at this level."; + errors[ERR_OPTIMIZER_NOT_AVAILABLE] + = "The optimizer (SQL dialect) is not available on this server."; + /* The parameters diff --git a/QueryProcessor/SecondoInterfaceTTY.cpp b/QueryProcessor/SecondoInterfaceTTY.cpp index a04efc50f0..57aad513ff 100755 --- a/QueryProcessor/SecondoInterfaceTTY.cpp +++ b/QueryProcessor/SecondoInterfaceTTY.cpp @@ -143,6 +143,7 @@ transactions of errorneous queries were not aborted. #include "Counter.h" #include "DerivedObj.h" #include "NList.h" +#include "SQLLanguage.h" #include "CharTransform.h" #include "version.h" @@ -817,7 +818,7 @@ Command\_. switch (commandLevel) { - case 0: // executable, list form + case CMD_LEVEL_NESTED_LIST: // executable, list form { if ( commandAsText ) { @@ -832,7 +833,7 @@ Command\_. } break; } - case 1: // executable, text form + case CMD_LEVEL_TEXT: // executable, text form { SecParser sp; // translates SECONDO syntax into nested list USE_AUTO_BUFFER = RTFlag::isActive("SI:AUTO_BUFFER"); diff --git a/README.md b/README.md index d9ec9e0205..1327c685d5 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ the full list: | Target | Builds | | --- | --- | | `make TTY` | Kernel and the single-user shell interface only | -| `make optimizer` | `SecondoPL`, `SecondoPLCS` and `OptServer` | +| `make optimizer` | `SecondoPL` and the embedded optimizer engine | | `make java` | The Java GUI | | `make runtests` | The automatic test suite | | `make clean` | All objects, libraries and applications | @@ -173,10 +173,13 @@ The GUI is a client, so a server has to be running first: ```bash cd bin && ./SecondoMonitor -s # start the database server -cd Optimizer && ./StartOptServer # optional: SQL support in the GUI cd Javagui && ./sgui # start the GUI ``` +SQL support in the GUI no longer needs a separate optimizer server: the kernel server +runs the optimizer itself. Enable it with `ENABLE_OPTIMIZER` in `Javagui/gui.cfg` (or via +the GUI's Optimizer ▸ Enable menu). + `Javagui` shows query results in viewers — including a spatial viewer that renders points, lines and regions, and animates moving objects. @@ -270,7 +273,6 @@ The full walk-through, including the GUI steps and the display styles to pick, i | `SecondoTTYBDB` | `bin/` | single user | Textual shell linked directly against the kernel. | | `SecondoTTYCS` | `bin/` | client | Same shell, but talks to `SecondoMonitor` over TCP/IP. | | `SecondoPL` | `Optimizer/` | single user | Prolog shell with SQL-like queries and the optimizer. | -| `SecondoPLCS` | `Optimizer/` | client | Client version of `SecondoPL`. | | `Javagui` (`sgui`) | `Javagui/` | client | Graphical interface with pluggable viewers. | | `TestRunner` | `bin/` | — | Runs `.test` scripts and checks expected results. | diff --git a/UserInterfaces/MainTTY.cpp b/UserInterfaces/MainTTY.cpp index 0a8f815ed9..fbac6a9508 100644 --- a/UserInterfaces/MainTTY.cpp +++ b/UserInterfaces/MainTTY.cpp @@ -1,8 +1,8 @@ /* ----- +---- This file is part of SECONDO. -Copyright (C) 2004, University in Hagen, Department of Computer Science, +Copyright (C) 2004, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify @@ -20,30 +20,30 @@ along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- -Feb. 2006 M. Spiekermann. The TestRunner is now a command option for SecondoTTY and -not an stand alone program. This saves time for linking and saves diskspace, since both -applications hav minimal differences. +Feb. 2006 M. Spiekermann. The TestRunner is now a command option for SecondoTTY +and not an stand alone program. This saves time for linking and saves diskspace, +since both applications hav minimal differences. */ /* Feb 2006, M. Spiekermann - + 1 The Main Routine -Main routine for ~SecondoBDB~ and ~SecondoCS~. This source file will be compiled twice. The -resulting object files will be used to link together ~SecondoBDB~ and ~SecondoCS~. There will -be some shell scripts which invoke the above programs with different options, e.g. +Main routine for ~SecondoBDB~ and ~SecondoCS~. This source file will be compiled +twice. The resulting object files will be used to link together ~SecondoBDB~ and +~SecondoCS~. There will be some shell scripts which invoke the above programs +with different options, e.g. SecondoTTYBDB SecondoPL TestRunner SecondoTTYCS -SecondoPLCS TestRunnerCS - -*/ + +*/ #include @@ -55,115 +55,114 @@ TestRunnerCS using namespace std; // forward declarations -extern int SecondoTTYMode(const TTYParameter&); -extern int SecondoTestRunner(const TTYParameter&); +extern int SecondoTTYMode(const TTYParameter &); +extern int SecondoTestRunner(const TTYParameter &); #ifndef NO_OPTIMIZER -extern int SecondoPLMode(TTYParameter&); -extern int SecondoPLTTYMode(TTYParameter&); +extern int SecondoPLMode(TTYParameter &); #endif #ifndef SEC_TTYCS -extern int SecondoServerMode( const int, const char**); +extern int SecondoServerMode(const int, const char **); #endif - class Simple2Handler : public MessageHandler { - public: - virtual bool handleMsg(NestedList* nl, ListExpr list, - int source __attribute__((unused))){ - #ifdef THREAD_SAFE - boost::lock_guard guard(mtx); - #endif - - if(!nl->HasMinLength(list,2)){ - return false; - } - if(!nl->IsEqual(nl->First(list),"simple2")){ - return false; - } - list = nl->Rest(list); - if(nl->HasLength(list,1)){ - list = nl->First(list); - switch(nl->AtomType(list)){ - case SymbolType : std::cout << nl->SymbolValue(list); - break; - case StringType : std::cout << nl->SymbolValue(list); - break; - - case TextType : std::cout << nl->TextValue(list); - break; - case IntType : std::cout << nl->IntValue(list); - break; - case RealType : std::cout << nl->RealValue(list); - break; - default : std::cout << nl->ToString(list); - } - } else { - std::cout << nl->ToString(list); - } - std::cout << endl; - return true; +public: + virtual bool handleMsg(NestedList *nl, ListExpr list, + int source __attribute__((unused))) { +#ifdef THREAD_SAFE + boost::lock_guard guard(mtx); +#endif + + if (!nl->HasMinLength(list, 2)) { + return false; + } + if (!nl->IsEqual(nl->First(list), "simple2")) { + return false; + } + list = nl->Rest(list); + if (nl->HasLength(list, 1)) { + list = nl->First(list); + switch (nl->AtomType(list)) { + case SymbolType: + std::cout << nl->SymbolValue(list); + break; + case StringType: + std::cout << nl->SymbolValue(list); + break; + + case TextType: + std::cout << nl->TextValue(list); + break; + case IntType: + std::cout << nl->IntValue(list); + break; + case RealType: + std::cout << nl->RealValue(list); + break; + default: + std::cout << nl->ToString(list); + } + } else { + std::cout << nl->ToString(list); + } + std::cout << endl; + return true; } - + Simple2Handler() {}; ~Simple2Handler() {}; - -}; - - +}; -int -main( const int argc, char* argv[] ) -{ - try { +int main(const int argc, char *argv[]) { + try { - TTYParameter tp(argc,argv); + TTYParameter tp(argc, argv); #ifndef SEC_TTYCS - if ( tp.isServerMode() ) - return SecondoServerMode(tp.numArgs, (const char**)tp.argValues); + if (tp.isServerMode()) + return SecondoServerMode(tp.numArgs, (const char **)tp.argValues); #endif - // Add message handlers - MessageCenter* msg = MessageCenter::GetInstance(); - - // uncomment the lines below in order to - // activate the example handler. The operator - // count2 demonstrates how to send messages. - SimpleHandler* sh = new SimpleHandler(); - msg->AddHandler(sh); - - Simple2Handler* s2h = new Simple2Handler(); - msg->AddHandler(s2h); - - ProgMesHandler* pmh = new ProgMesHandler(); - msg->AddHandler(pmh); - -#ifdef SECONDO_PL - if ( tp.isPLMode() ) - return SecondoPLMode(tp); + // Add message handlers + MessageCenter *msg = MessageCenter::GetInstance(); + + // uncomment the lines below in order to + // activate the example handler. The operator + // count2 demonstrates how to send messages. + SimpleHandler *sh = new SimpleHandler(); + msg->AddHandler(sh); + + Simple2Handler *s2h = new Simple2Handler(); + msg->AddHandler(s2h); + + ProgMesHandler *pmh = new ProgMesHandler(); + msg->AddHandler(pmh); + +// -pl starts the raw Prolog shell (used for optimizer development). It is only +// meaningful for the standalone kernel binary; the client/server build +// (SEC_TTYCS, i.e. SecondoCS) is a pure network client. The former -pltty +// (mixed SQL + kernel TTY) mode has been retired: the regular TTY now runs the +// SQL dialect directly, both embedded and over the network (see +// SecondoTTY::CallSecondo). +#if defined(SECONDO_PL) && !defined(SEC_TTYCS) + if (tp.isPLMode()) + return SecondoPLMode(tp); #endif + cout << License::getStr() << endl; -#ifdef SECONDO_PL - if ( tp.isPLTTYMode() ) - return SecondoPLTTYMode(tp); -#endif + // Testrunner or TTY or TTYCS + if (!tp.CheckConfiguration()) + return 1; + + if (tp.isTestRunnerMode()) + return SecondoTestRunner(tp); + + return SecondoTTYMode(tp); - cout << License::getStr() << endl; - - // Testrunner or TTY or TTYCS - if ( !tp.CheckConfiguration() ) - return 1; - - if ( tp.isTestRunnerMode() ) - return SecondoTestRunner(tp); - - return SecondoTTYMode(tp); - - } catch (exception& e) { + } catch (exception &e) { cerr << e.what() << endl; } } diff --git a/UserInterfaces/SQLLanguage.cpp b/UserInterfaces/SQLLanguage.cpp new file mode 100644 index 0000000000..75ed17fef0 --- /dev/null +++ b/UserInterfaces/SQLLanguage.cpp @@ -0,0 +1,180 @@ +/* +---- +This file is part of SECONDO. + +Copyright (C) 2026, +University in Hagen, +Faculty of Mathematics and Computer Science, +Database Systems for New Applications. + +SECONDO is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +SECONDO is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with SECONDO; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +---- + +1 Language detection for typed commands + +The single definition of the rules described in ~SQLLanguage.h~. The rule set is +the one the retired hybrid TTY (~SecondoPLTTYMode::isSqlCommand~) and the +JavaGUI (~CommandPanel.optimize~) independently arrived at; it now exists once. + +*/ + +#include "SQLLanguage.h" + +#include +#include + +using namespace std; + +const string SQL_BLANKS = " \t\n\r\f\v\b\a"; + +/* +2 Tokenizing + +Split ~cmd~ into at most ~maxTok~ lower-cased tokens. The delimiter set includes +the bracket and assignment characters, so that "let r5=select ..." and +"create table t(a)" tokenize the way the rules below expect. + +*/ +static void sqlTokens(const string& cmd, vector& toks, size_t maxTok) +{ + const string delims = SQL_BLANKS + "([{=.,;"; + size_t pos = 0; + while ( toks.size() < maxTok ) + { + size_t s = cmd.find_first_not_of(delims, pos); + if ( s == string::npos ) break; + size_t e = cmd.find_first_of(delims, s); + string t = cmd.substr(s, (e==string::npos) ? string::npos : e - s); + for ( size_t i = 0; i < t.size(); i++ ) + { + t[i] = tolower((unsigned char) t[i]); + } + toks.push_back(t); + if ( e == string::npos ) break; + pos = e; + } +} + +/* +3 SQL + +*/ +bool looksLikeSql(const string& cmd) +{ + size_t s = cmd.find_first_not_of(SQL_BLANKS); + if ( s == string::npos ) return false; + // nested list command or command sequence: always the kernel + if ( cmd[s] == '(' || cmd[s] == '{' ) return false; + + vector t; + sqlTokens( cmd, t, 3 ); + if ( t.empty() ) return false; + + // unambiguous openers + if ( t[0] == "sql" || t[0] == "select" || t[0] == "union" + || t[0] == "intersection" ) return true; + + // ambiguous with kernel commands: need the second token + if ( t.size() < 2 ) return false; + if ( t[0] == "delete" && t[1] == "from" ) return true; + if ( t[0] == "insert" && t[1] == "into" ) return true; + // The optimizer knows exactly two things to create and to drop. Everything + // else the two words open is the kernel's -- notably "delete database X", + // which is how a database is dropped, and which must reach the kernel to be + // told that one is still open (ERR_DATABASE_OPEN). + if ( t[0] == "create" && (t[1] == "table" || t[1] == "index") ) return true; + if ( t[0] == "drop" && (t[1] == "table" || t[1] == "index") ) return true; + + // ... or the third + if ( t.size() < 3 ) return false; + if ( t[0] == "update" && t[2] == "set" ) return true; + // "let = select|union|intersection ...": an SQL right-hand side. The + // server splits the prefix off and re-wraps the generated plan. + if ( t[0] == "let" && ( t[2] == "select" || t[2] == "union" + || t[2] == "intersection" ) ) return true; + + return false; +} + +/* +4 Optimizer control directives + +The goals the optimizer offers besides SQL. Recognized when typed bare; with an +explicit optimizer prefix any non-SQL text is a directive, so this list is +only the convenience case. + +*/ +bool isOptimizerDirective(const string& cmd) +{ + size_t s = cmd.find_first_not_of(SQL_BLANKS); + if ( s == string::npos ) return false; + size_t nameEnd = cmd.find_first_of(SQL_BLANKS + "(", s); + string name = cmd.substr(s, (nameEnd==string::npos) ? string::npos + : nameEnd - s); + // The directive names are Prolog atoms, matched case-sensitively; the + // argument (if any) starts at the '('. + static const char* const directives[] = { + "setOption", "delOption", "showOptions", + "loadOptions", "saveOptions", "defaultOptions", + "updateCatalog", "resetKnowledgeDB", + "helpMe" }; // advertised by the showOptions listing itself + for ( size_t i = 0; i < sizeof(directives)/sizeof(directives[0]); i++ ) + { + if ( name == directives[i] ) return true; + } + return false; +} + +/* +5 Everything else is a kernel command + +~deriveKernelCommandLevel~ is inline in the header; see the note there. + +*/ +int resolveCommandLevel(const string& cmd, bool optimizerAddressed) +{ + if ( looksLikeSql( cmd ) ) return CMD_LEVEL_SQL; + if ( optimizerAddressed || isOptimizerDirective( cmd ) ) + { + return CMD_LEVEL_OPT_DIRECTIVE; + } + return deriveKernelCommandLevel( cmd ); +} + +/* +6 The ~optimizer~ prefix + +*/ +bool stripOptimizerPrefix(const string& cmd, string& rest) +{ + rest = cmd; + size_t s = cmd.find_first_not_of(SQL_BLANKS); + if ( s == string::npos ) return false; + + const string kw = "optimizer"; + if ( cmd.size() - s < kw.size() + 1 ) return false; + for ( size_t i = 0; i < kw.size(); i++ ) + { + if ( tolower((unsigned char) cmd[s+i]) != kw[i] ) return false; + } + // must be a whole word, and something has to follow it + size_t after = s + kw.size(); + if ( !isspace((unsigned char) cmd[after]) ) return false; + size_t r = cmd.find_first_not_of(SQL_BLANKS, after); + if ( r == string::npos ) return false; + + rest = cmd.substr(r); + return true; +} diff --git a/UserInterfaces/SecondoPL.cpp b/UserInterfaces/SecondoPL.cpp index 620aa80eaa..dbebd8e090 100755 --- a/UserInterfaces/SecondoPL.cpp +++ b/UserInterfaces/SecondoPL.cpp @@ -73,6 +73,7 @@ support for calling Secondo from PROLOG. #include "License.h" #include "TTYParameter.h" #include "NList.h" +#include "SQLLanguage.h" #include "../OptParser/OptimizerChecker.h" @@ -581,13 +582,13 @@ pl_call_secondo(term_t command, term_t result) error = false; commandStr = commandCStr; /* executable command in text syntax */ - commandLevel = 1; + commandLevel = CMD_LEVEL_TEXT; } else { commandLE = TermToListExpr(command, plnl, error); /* executable command in nested list syntax */ - commandLevel = 0; + commandLevel = CMD_LEVEL_NESTED_LIST; if (error) { cerr << "SecondoPL: TermToListExpr() failed." << endl; @@ -1371,3 +1372,552 @@ int registerSecondo(){ } +/* + +10. Embedding the optimizer into an already running SECONDO process + +The following functions let a server process (a forked ~SecondoBDB -srv~) run +the optimizer in-process, so it can accept the SQL dialect over the network and +turn it into an executable plan. In contrast to ~registerSecondo~ they do NOT +create a second ~SecondoInterface~/SMI environment: the server hands us its own +interface, which the optimizer's ~secondo/2~ callbacks then reuse for catalog +and statistics access against the very database the plan will run on. + +*/ + +static bool embeddedOptimizerInitialized = false; + +bool embeddedOptimizerReady() { + return embeddedOptimizerInitialized; +} + +bool initEmbeddedOptimizer(SecondoInterface* serverSi) { + if ( embeddedOptimizerInitialized ) { + return true; + } + if ( serverSi == 0 ) { + return false; + } + + // Reuse the server's interface for the optimizer's secondo/2 callbacks + // instead of opening a second SMI environment. + si = serverSi; + plnl = serverSi->GetNestedList(); + NList::setNLRef(plnl); + + // Register the foreign predicates (secondo/2, getCosts, ...). + PL_register_extensions(predicates); + + // Start the Prolog engine once for this process. + char* plav[2]; + plav[0] = (char*) "SecondoBDB"; + plav[1] = NULL; + if ( !PL_initialise(1, plav) ) { + si = 0; + plnl = 0; + return false; + } + + // Force the Prolog libraries to be loaded (see SecondoPLMode). + { + term_t t0 = PL_new_term_refs(2); + PL_put_atom_chars(t0, "x"); + if ( !PL_put_list_chars(t0 + 1, "") ) { + cerr << "SecondoPL: problem initializing the prolog interface" << endl; + } + predicate_t p = PL_predicate("member", 2, ""); + PL_call_predicate(NULL, PL_Q_NORMAL, p, t0); + } + + // Preload library(error) before restricting autoloading below. SWI's + // listing.pl (pulled in while the optimizer loads) uses error:must_be/2 at + // term-expansion time; with autoloading restricted to the user module that + // predicate would otherwise fail to resolve and spam "exception handler + // failed to define error:must_be/2" errors during optimizer startup. + { + term_t errLib = PL_new_term_ref(); + term_t errArg = PL_new_term_ref(); + PL_put_atom_chars(errArg, "error"); + if ( PL_cons_functor(errLib, PL_new_functor(PL_new_atom("library"), 1), + errArg) ) { + predicate_t useModule = PL_predicate("use_module", 1, ""); + PL_call_predicate(NULL, PL_Q_NORMAL, useModule, errLib); + } + } + +#if PLVERSION > 80000 + // Restrict autoloading for SWI-Prolog 8.x/9.x compatibility. + { + term_t t = PL_new_term_refs(2); + PL_put_atom_chars(t, "autoload"); + PL_put_atom_chars(t + 1, "user"); + predicate_t p = PL_predicate("set_prolog_flag", 2, ""); + PL_call_predicate(NULL, PL_Q_NORMAL, p, t); + } +#endif + + // The optimizer program lives in $SECONDO_BUILD_DIR/Optimizer and consults + // its parts relative to that directory. A forked server runs in bin/, so + // steer Prolog's working directory there (without changing the process CWD, + // which would disturb the storage manager). + const char* buildDir = getenv("SECONDO_BUILD_DIR"); + if ( buildDir != 0 ) { + string optDir = string(buildDir) + "/Optimizer"; + term_t t = PL_new_term_refs(2); + PL_put_variable(t); + PL_put_atom_chars(t + 1, optDir.c_str()); + predicate_t p = PL_predicate("working_directory", 2, ""); + PL_call_predicate(NULL, PL_Q_NORMAL, p, t); + } + + // Load the optimizer. + { + term_t a0 = PL_new_term_refs(1); + predicate_t p = PL_predicate("consult", 1, ""); + PL_put_atom_chars(a0, "auxiliary"); + PL_call_predicate(NULL, PL_Q_NORMAL, p, a0); + PL_put_atom_chars(a0, "calloptimizer"); + PL_call_predicate(NULL, PL_Q_NORMAL, p, a0); + } + + embeddedOptimizerInitialized = true; + return true; +} + +// Run the optimizer's own secondo/1 predicate (auxiliary.pl) with a single +// command atom. Unlike the foreign secondo/2, this clause also maintains the +// optimizer's databaseName fact and catalog on "open database" / "close +// database". Returns true if the goal succeeded. +static bool runOptimizerSecondo1(const string& command) { + fid_t fid = PL_open_foreign_frame(); + term_t a = PL_new_term_refs(1); + PL_put_atom_chars(a, command.c_str()); + predicate_t p = PL_predicate("secondo", 1, ""); + int rc = PL_call_predicate(NULL, PL_Q_CATCH_EXCEPTION, p, a); + PL_discard_foreign_frame(fid); + return rc != 0; +} + +// True if the optimizer already tracks database dbLower (its databaseName fact, +// which it stores lower-cased). +static bool optimizerHasDatabase(const string& dbLower) { + fid_t fid = PL_open_foreign_frame(); + term_t a = PL_new_term_refs(1); + PL_put_atom_chars(a, dbLower.c_str()); + predicate_t p = PL_predicate("databaseName", 1, ""); + int rc = PL_call_predicate(NULL, PL_Q_CATCH_EXCEPTION, p, a); + PL_discard_foreign_frame(fid); + return rc != 0; +} + +bool embeddedOptimizerUseDatabase(const string& dbName) { + if ( !embeddedOptimizerInitialized ) { + return false; + } + string dbLower = dbName; + for ( size_t i = 0; i < dbLower.size(); i++ ) { + dbLower[i] = tolower((unsigned char) dbLower[i]); + } + if ( optimizerHasDatabase(dbLower) ) { + return true; // schema already loaded for this database + } + // The database is open at the kernel, but the optimizer has not loaded its + // schema. Drive the optimizer's open-database logic (which asserts + // databaseName and runs updateCatalog): close the currently open database, + // then reopen it through the optimizer. The database ends up open again, + // transparently to the client. + runOptimizerSecondo1("close database"); + runOptimizerSecondo1(string("open database ") + dbName); + return optimizerHasDatabase(dbLower); +} + +/* +SQL text normalization. The clients used to do this each for themselves (the +JavaGUI in ~rewriteForOptimizer~/~varToLowerCase~/~replacePoint~), which made the +accepted syntax depend on which client you used. Now that the SQL is optimized +server side it belongs here, so every client -- TTY, GUI, WebUI, JDBC -- accepts +the same input. + +*/ + +static bool isIdentChar(char c) { + return isalnum((unsigned char) c) || c == '_'; +} + +// The optimizer turns identifiers into Prolog atoms, which must start lower +// case. Lower-case the FIRST character of each identifier only (the rest is +// left alone, exactly as the JavaGUI does). Quoted strings ("...") and text +// constants ('...') are never touched. +static string sqlIdentsToLower(const string& str) { + string buf; + buf.reserve(str.size()); + int state = 0; // 0 outside, 1 in "..", 2 in '..', 3 inside an identifier + for ( size_t i = 0; i < str.size(); i++ ) { + char c = str[i]; + switch ( state ) { + case 1: + if ( c == '"' ) { state = 0; } + buf += c; + break; + case 2: + if ( c == '\'' ) { state = 0; } + buf += c; + break; + case 3: + if ( isIdentChar(c) ) { + buf += c; + } else { + buf += c; + if ( c == '"' ) { state = 1; } + else if ( c == '\'' ) { state = 2; } + else { state = 0; } + } + break; + default: + if ( c == '"' ) { state = 1; buf += c; } + else if ( c == '\'' ) { state = 2; buf += c; } + else if ( isalpha((unsigned char) c) ) { + buf += (char) tolower((unsigned char) c); + state = 3; + } + else { buf += c; } + break; + } + } + return buf; +} + +// Users commonly write attribute access as "r.name"; the SQL dialect spells it +// "r:name". Replace a '.' that sits directly inside an identifier and is +// followed by a letter -- so decimal numbers such as 3.14 stay untouched. +static string sqlDotToColon(const string& str) { + string buf; + buf.reserve(str.size()); + int state = 0; // 0 outside, 1 in "..", 2 in '..', 3 inside an identifier + for ( size_t i = 0; i < str.size(); i++ ) { + char c = str[i]; + switch ( state ) { + case 1: + if ( c == '"' ) { state = 0; } + buf += c; + break; + case 2: + if ( c == '\'' ) { state = 0; } + buf += c; + break; + case 3: + if ( isIdentChar(c) ) { buf += c; } + else if ( c == '"' ) { state = 1; buf += c; } + else if ( c == '\'' ) { state = 2; buf += c; } + else if ( c == '.' ) { + if ( i + 1 < str.size() && isalpha((unsigned char) str[i+1]) ) { + buf += ':'; + } else { + buf += c; + } + state = 0; + } + else { buf += c; state = 0; } + break; + default: + if ( c == '"' ) { state = 1; buf += c; } + else if ( c == '\'' ) { state = 2; buf += c; } + else if ( isalpha((unsigned char) c) ) { state = 3; buf += c; } + else { buf += c; } + break; + } + } + return buf; +} + +static string normalizeSqlText(const string& sql) { + return sqlDotToColon( sqlIdentsToLower( sql ) ); +} + +// Lower-cased first whitespace/'('-delimited token of cmd ("" if none). +static string firstToken(const string& cmd) { + size_t s = cmd.find_first_not_of(" \t\n\r\f\v"); + if ( s == string::npos ) { + return ""; + } + size_t e = s; + while ( e < cmd.size() && isalpha((unsigned char) cmd[e]) ) { + e++; + } + string tok = cmd.substr(s, e - s); + for ( size_t i = 0; i < tok.size(); i++ ) { + tok[i] = tolower((unsigned char) tok[i]); + } + return tok; +} + +// Recognize "let = ...". Only the SQL +// on the right-hand side can be optimized; the generated plan is re-wrapped +// as "let = " afterwards. The identifier keeps its spelling +// (it names the object being created), so it is split off before normalization. +static bool splitLetPrefix(const string& sql, string& ident, string& rest) { + size_t p = sql.find_first_not_of(" \t\n\r\f\v"); + if ( p == string::npos || sql.compare(p, 3, "let") != 0 ) { + return false; + } + size_t q = p + 3; + if ( q >= sql.size() || !isspace((unsigned char) sql[q]) ) { + return false; + } + q = sql.find_first_not_of(" \t\n\r\f\v", q); + if ( q == string::npos || !isalpha((unsigned char) sql[q]) ) { + return false; + } + size_t idStart = q; + while ( q < sql.size() && isIdentChar(sql[q]) ) { + q++; + } + string id = sql.substr(idStart, q - idStart); + q = sql.find_first_not_of(" \t\n\r\f\v", q); + if ( q == string::npos || sql[q] != '=' ) { + return false; + } + q = sql.find_first_not_of(" \t\n\r\f\v", q + 1); + if ( q == string::npos ) { + return false; + } + string tail = sql.substr(q); + string tok = firstToken(tail); + if ( tok != "select" && tok != "union" && tok != "intersection" ) { + return false; // not an SQL right-hand side: leave it to the kernel + } + ident = id; + rest = tail; + return true; +} + +bool embeddedOptimizerSqlChangesCatalog(const string& sql) { + string ident = "", rest = ""; + if ( splitLetPrefix( sql, ident, rest ) ) { + return true; // "let X = select ..." creates a new object + } + string first = firstToken( sql ); + if ( first == "drop" ) { + return true; // drop table/index + } + if ( first == "create" ) { + return true; // create table/index + } + return false; +} + +bool embeddedOptimizerRefreshCatalog(string& errMsg) { + string output = ""; + return embeddedOptimizerRunGoal( "updateCatalog", output, errMsg ); +} + +/* +~sqlToPlan/3~ reports a failure as the atom ~::ERROR::~ followed by the message +*written back as a Prolog term* (~term\_to\_atom/2~), so what arrives here is +quoted and escaped, e.g. + +---- +'\\n\\nSQL ERROR (usually a user error): Unknown symbol: \\'x\\' is not recognized!' +---- + +Undo that by reading the text back as a term and taking its text: that reverses +~writeq~ exactly, whatever escapes it used. Only the Secondo Javagui ever +decoded this (its ~formatOptimizerError~ hand-rolled four of the escapes), so +every other client printed the raw form; doing it here gives all of them -- +GUI, JDBC, both TTYs -- a readable message and keeps the decoding in one place. + +*/ +static string prologQuotedToPlain(const string& quoted) { + string plain = quoted; + + fid_t fid = PL_open_foreign_frame(); + term_t t = PL_new_term_ref(); + // PL_chars_to_term expects a term closed by a full stop, as in + // embeddedOptimizerRunGoal below. + string readable = quoted + " ."; + char* text = 0; + if ( PL_chars_to_term( readable.c_str(), t ) + && PL_get_chars( t, &text, CVT_ATOM | CVT_STRING ) ) { + plain = text; + } else { + // A syntax error leaves an exception pending; drop it so it cannot + // surface at the next Prolog call. + PL_clear_exception(); + } + PL_discard_foreign_frame(fid); + + size_t b = plain.find_first_not_of(" \t\r\n"); + if ( b == string::npos ) { + return quoted; // nothing but whitespace: keep the raw + } + size_t e = plain.find_last_not_of(" \t\r\n"); + return plain.substr(b, e - b + 1); +} + +bool embeddedSqlToPlan(const string& sql, string& plan, double& costs, + string& errMsg, bool& alreadyExecuted) { + plan = ""; + costs = 0.0; + errMsg = ""; + alreadyExecuted = false; + if ( !embeddedOptimizerInitialized ) { + errMsg = "optimizer not initialized"; + return false; + } + + // "let = ": optimize only the right-hand side and re-wrap below. + string letIdent = "", sqlPart = sql; + bool isLet = splitLetPrefix( sql, letIdent, sqlPart ); + + string normalized = normalizeSqlText( sqlPart ); + + fid_t fid = PL_open_foreign_frame(); + term_t a0 = PL_new_term_refs(3); // a0 = sql, a0+1 = plan, a0+2 = costs + PL_put_atom_chars(a0, normalized.c_str()); + predicate_t p = PL_predicate("sqlToPlan", 3, ""); + bool ok = true; + // Decoded only after the query is closed, so the nested read stays + // outside it. + string rawError = ""; + bool haveRawError = false; + + try { + qid_t id = PL_open_query(NULL, PL_Q_CATCH_EXCEPTION, p, a0); + if ( PL_next_solution(id) ) { + char* res = 0; + if ( PL_get_atom_chars(a0 + 1, &res) ) { + string answer(res); + if ( answer.compare(0, 9, "::ERROR::") == 0 ) { + rawError = answer.substr(9); + haveRawError = true; + ok = false; + } else { + // sqlToPlan yields the estimate as a Prolog number -- an integer 0 + // where it has none, a float otherwise -- and PL_get_float reads + // both. A non-number would be a contract violation; leave costs at + // 0.0 rather than failing the optimization over it. + double c = 0.0; + if ( PL_get_float(a0 + 2, &c) ) { + costs = c; + } + if ( answer == "done" ) { + // A create/drop command: the optimizer already executed it and + // there is no plan to run. Keep the sentinel for the wire. + plan = "done"; + alreadyExecuted = true; + } else { + // sqlToPlan returns a bare plan expression; make it a command. + plan = isLet ? ("let " + letIdent + " = " + answer) + : ("query " + answer); + } + } + } else { + errMsg = "optimization failed"; + ok = false; + } + } else { + errMsg = "optimization failed (no plan found)"; + ok = false; + } + PL_close_query(id); + } catch (...) { + errMsg = "exception during optimization"; + ok = false; + haveRawError = false; + } + + if ( haveRawError ) { + errMsg = prologQuotedToPlain( rawError ); + } + + PL_discard_foreign_frame(fid); + return ok; +} + +bool embeddedOptimizerRunGoal(const string& goal, string& output, + string& errMsg) { + output = ""; + errMsg = ""; + if ( !embeddedOptimizerInitialized ) { + errMsg = "optimizer not initialized"; + return false; + } + + // PL_chars_to_term expects a term closed by a full stop. Trim trailing + // whitespace and a single trailing '.'/';' (the TTY delimiter), then append + // the terminator ourselves so callers can pass "showOptions", + // "setOption(subqueries)", "showOptions." or "showOptions;" alike. + string goalText = goal; + while ( !goalText.empty() + && (goalText[goalText.size()-1] == '\n' + || goalText[goalText.size()-1] == '\r' + || goalText[goalText.size()-1] == '\t' + || goalText[goalText.size()-1] == ' ') ) { + goalText.erase(goalText.size()-1); + } + if ( !goalText.empty() + && (goalText[goalText.size()-1] == '.' + || goalText[goalText.size()-1] == ';') ) { + goalText.erase(goalText.size()-1); + } + if ( goalText.empty() ) { + errMsg = "empty optimizer directive"; + return false; + } + goalText += " ."; + + fid_t fid = PL_open_foreign_frame(); + bool ok = true; + + try { + // Build with_output_to(string(S), Goal) so the directive's write/1 output + // (the showOptions listing, the setOption/delOption confirmation lines) is + // captured into S instead of going to the server/standalone stdout. + term_t args = PL_new_term_refs(2); // args+0 = string(S), args+1 = Goal + term_t sVar = PL_new_term_ref(); // S (unbound; bound to the output) + if ( !PL_cons_functor(args, PL_new_functor(PL_new_atom("string"), 1), + sVar) ) { + errMsg = "internal error building output sink"; + PL_discard_foreign_frame(fid); + return false; + } + if ( !PL_chars_to_term(goalText.c_str(), args + 1) ) { + errMsg = "could not parse optimizer directive"; + PL_discard_foreign_frame(fid); + return false; + } + + predicate_t p = PL_predicate("with_output_to", 2, ""); + qid_t id = PL_open_query(NULL, PL_Q_CATCH_EXCEPTION, p, args); + int rc = PL_next_solution(id); + + // Read the captured output regardless of success/failure. + char* out = 0; + if ( PL_get_chars(sVar, &out, CVT_ALL) ) { + output = out; + } + if ( rc == 0 ) { + ok = false; + term_t ex = PL_exception(id); + if ( ex ) { + char* exChars = 0; + if ( PL_get_chars(ex, &exChars, CVT_WRITE) ) { + errMsg = exChars; + } else { + errMsg = "optimizer directive raised an exception"; + } + } else if ( output.empty() ) { + errMsg = "optimizer directive failed"; + } + } + PL_close_query(id); + } catch (...) { + errMsg = "exception during optimizer directive"; + ok = false; + } + + PL_discard_foreign_frame(fid); + return ok; +} + + diff --git a/UserInterfaces/SecondoPLTTYMode.cpp b/UserInterfaces/SecondoPLTTYMode.cpp deleted file mode 100644 index 2c050d5496..0000000000 --- a/UserInterfaces/SecondoPLTTYMode.cpp +++ /dev/null @@ -1,1968 +0,0 @@ -/* ----- -This file is part of SECONDO. - -Copyright (C) 2006, University in Hagen, -Faculty of Mathematics and Computer Science, -Database Systems for New Applications. - -SECONDO is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -SECONDO is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with SECONDO; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ----- - - -In this file, the pltty mode is defined. -Is the name of the mode suggest, this mode is a mix between the -optimizer interface and the usual secondo interface. - -In this mode, four different kinds of commands are distinguished. - -The first catefory of commands are internal commands. These commands are -handled directly by the user interface. Examples are '@', 'help' or -'quit'. - -The second category include sql commands. These commands will be translated -into a plan using the sqlToPlan predicate defined in the optimizer. Before -optimization, some rewritings are done within the command. For example, symbols -starting with a upper case letter are replaced by lower case letters. -Furthermore, brackets are checked before optimization. If the optimization -succeds, the generated plan is send to the kernel. The result is displayed -using the kernel display functions. - -The third category of commands are commands that are directly send to the -kernel without aid of the optimizer. - -If a command cannot assigned to one of the categories mentioned before, -it is tried to convert it into a callable prolog term and call it using the -prolog engine. All generated solutions are printed out. - -*/ - -/* -1 Includes - -*/ - -#include -#include -#include - -#define PL_ARITY_AS_SIZE 1 -#include "SWI-Prolog.h" - -#include -#include "SecondoConfig.h" -#include "Application.h" -#include "TTYParameter.h" -#include -#include "StringUtils.h" -#include "SecondoInterface.h" -#include "DisplayTTY.h" - -#include - -#ifndef SECONDO_WIN32 -#include -#endif - -#include - -#include "getCommand.h" - - -#ifdef HAVE_LIBREADLINE - #include - #include - #include - #define HISTORY_FILE ".secondopltty_history" - #define HISTORY_FILE_ENTRIES 200 -#endif - -using namespace std; - - - -string blanks = " \t\n\r"; -string blanks2 = blanks + "[](){}?.,"; - - -/* -2 predicates - -The ~predicates~ array contains all prolog extensions required by -Secondo. These things are defined in SecondoPL. - -*/ - -extern PL_extension predicates[]; -extern void handle_exit(void); -extern bool StartSecondoC(TTYParameter& tp); - -extern SecondoInterface* si; -NestedList* mnl; - -bool globalAbort = false; // used if quit occurs within a script - - -namespace pltty{ - - -bool plttydebug = false; - - -// forward declaration of processCommands -bool processCommands(istream&, bool,bool); - - -/* -~isStdInput~ - -This boolean value describes whether the current input is cin or -a file. - - -*/ - -bool isStdInput = true; -string prompt = ""; - -void ShowPrompt( const bool first ) { - prompt = first ? "SecondoPLTTY => ": "SecondoPLTTY -> "; - #ifdef HAVE_LIBREADLINE - rl_set_prompt( prompt.c_str() ); - #else - cout << prompt; - #endif -} - - -#ifndef SECONDO_WIN32 -char getChar(){ - struct termios old,n; - char res; - tcgetattr(fileno(stdin),&old); - n=old; - n.c_lflag &= ~ICANON; - n.c_lflag &= ~ECHO; - tcsetattr(fileno(stdin),TCSANOW,&n); - res = getc(stdin); - tcsetattr(fileno(stdin),TCSANOW,&old); - return res; -} -#else -char getChar(){ - DWORD mode, cc; - HANDLE h = GetStdHandle( STD_INPUT_HANDLE ); - - if (h == NULL) { - return 0; // console not found - } - - GetConsoleMode( h, &mode ); - SetConsoleMode( h, mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT) ); - TCHAR c = 0; - ReadConsole( h, &c, 1, &cc, NULL ); - SetConsoleMode( h, mode ); - return c; -} -#endif - - - -/* -~isUpperCase~ - -Auxiliary function chinging whether an character is an upper case. - -*/ -bool isUpperCase(char c){ - return (c>='A') && (c <='Z'); -} - -/* -~tolower~ - -This function converts an upper case character into a lower case. - -*/ -char tolower(char c){ - if(!isUpperCase(c)) return c; - return (c + 'a') - 'A'; -} - - -/* -~isIdentChar~ - -This functions checks whether a character is allowed to be part of -an identifier. - -*/ -bool isIdentChar(char c){ - return stringutils::isLetter(c) || stringutils::isDigit(c) || (c=='_'); -} - - - -string term2string(term_t t){ - string res =""; - fid_t fid = PL_open_foreign_frame(); - predicate_t pl_convert = PL_predicate("term_to_atom",2,""); - term_t args = PL_new_term_refs(2); - term_t r = args+1; - - if(!PL_put_term(args, t)) { - std::cerr << "Unable to put term: " << t << endl; - } - - qid_t qid = PL_open_query(NULL, PL_Q_CATCH_EXCEPTION, pl_convert, args); - if(!PL_next_solution(qid)){ - PL_close_query(qid); - PL_discard_foreign_frame(fid); - return res; - } - char* s; - if( PL_get_atom_chars(r,&s)){ - res = string(s); - } - PL_close_query(qid); - PL_discard_foreign_frame(fid); - return res; -} - -bool isWhiteSpace(char c){ - string ws = " \r\n\t"; - for(size_t i=0;i brackets; - - int state = 0; // start of a word - - // states - // 0 begin of a symbol - // 1 within a double quoted string - // 2 within a single quoted string - // 3 within a symbol starting with a capital - // 4 within a symbol starting lower case - stringstream res; - - size_t pos = 0; - - while(pos < cmd.size()){ - char c = cmd[pos]; - switch(state){ // somewhere - case 0: { - if(c=='"'){ - state = 1; - res << c; - } else if(c=='\''){ - state = 2; - res << c; - } else if(stringutils::isLetter(c)){ - if(isUpperCase(c)){ - state = 3; - res << tolower(c); - } else { - state = 4; - res << c; - } - } else { - if((c=='(') || c=='[' || c=='{'){ - brackets.push(c); - } else if(c==')' || c==']' || c=='}'){ - if(brackets.empty()){ - errMsg = string("found closing ") + c + " that was not opened"; - correct = false; - return ""; - } - char open = brackets.top(); - brackets.pop(); - switch(c){ - case ')' : if (open!='(') { - errMsg = string("closing ") + c - + " was opened by " + open; - correct= false; - return ""; - } - break; - case ']' : if (open!='[') { - errMsg = string("closing ") + c - + " was opened by " + open; - correct = false; - return ""; - } - break; - case '}' : if (open!='{') { - errMsg = string("closing ") + c - + " was opened by " + open; - correct = false; - return ""; - } - break; - } - } else if(c=='.') { // replace followed by a letter by a ':' - if(pos1){ - if(cmd[0]=='@'){ - return true; - } - } - return false; -} - -/* -~processQuit~ - -This function is called if a wuit command is executed. - -*/ -bool processQuit(){ - cout << "Thank you for using Secondo." << endl; - globalAbort = true; - return true; -} - -/* -~processHelp~ - -This function is the implementation of the help command. - -*/ -bool processHelp(){ - cout << endl - << "secondo or optimizer command are executed as usual " << endl - << "if an sql select statement ends with a dot, the user is " << endl - << "ask whether the optimized query should be executed " << endl - << "? - show this help" << endl - << "@FILE - read commands from file " << endl - << "@@FILE - read commands from file until an error occurred" << endl - << "@\%FILE - read commands from file ignoring pd comments" << endl - << "@&FILE - read commands from file ignoring pd comments " - << "until an error occurred" << endl - << "debugOn - shows sql commands before sending to prolog" << endl - << "debugOff - switches of debugging messages " << endl - << "quit - exits the program" << endl; - return true; -} - - -bool processDebug(bool enable){ - cout << endl - << "switched debugging " << (enable?"on":"off") << endl; - plttydebug = enable; - return true; -} - - -/* -~processScript~ - -This command is called if the command starts with an @ mentioning the -execution of some script. - -*/ - -bool processScript(const string& cmd){ - bool lastStdInput = isStdInput; - bool isPD = false; - bool haltOnErrors = false; - int pos=1; - char second = cmd[1]; - if(second=='@'){ - haltOnErrors = true; - pos++; - }else if(second=='%'){ - isPD = true; - pos++; - } else if(second=='&'){ - isPD=true; - haltOnErrors = true; - pos++; - } - string filename = cmd.substr(pos); - stringutils::trim(filename); - ifstream in(filename.c_str()); - if(!in){ - cout << "Error: could not open file: " << filename << endl; - return false; - } - - isStdInput = false; - bool res = processCommands(in,haltOnErrors, isPD); - isStdInput = lastStdInput; - - if(!res){ - cout << "there was errors during processing " << filename << endl; - } else { - cout << "file " << filename << " successfull processed" << endl; - } - in.close(); - return res; -} - - -/* -~processInternalCommand~ - -This function is called if an internal command has been recognized. -It checks the kind of the internal command and calles the -appropriate function. - -*/ -bool processInternalCommand(const string& cmd){ - if(cmd=="quit" || cmd=="q"){ - return processQuit(); - } - if(cmd=="?"){ - return processHelp(); - } - if(cmd=="debugOn"){ - return processDebug(true); - } - if(cmd=="debugOff"){ - return processDebug(false); - } - if(cmd.size()>1){ - if(cmd[0]=='@'){ - return processScript(cmd); - } - } - cout << "Error: command " << cmd << " recognized as an internal " - << "command but handled not correctly"; - return false; -} - - - -/* -~getCommand~ - -This function extracts the next command from the input stream. -If the isPD flag is set to true, comments in PD-style are -ignored. - -*/ -string getCommand(istream& in, bool isPD){ - - function showPrompt - = [](const bool first) {ShowPrompt(first); }; - function isInternalCommand - = [](const std::string& c) {return IsInternalCommand(c); }; - std::string cmd; - ::getCommand(in, isPD, cmd, - showPrompt, isInternalCommand, - isStdInput, prompt); - return cmd; -} - -/* -3.1 Function ~isDirectSecondoCommand~ - -Returns true if the command starts with a secondo keyword, -a bracket or a curly bracket - -*/ -bool isDirectSecondoCommand(const string& cmd){ - stringutils::StringTokenizer st(cmd, blanks2, true); - if(!st.hasNextToken()){ - return false; - } - string first = st.nextToken(); - // simple, recognize using the first keyword - if( first=="query" - || first=="if" - || first=="while" - || stringutils::startsWith(cmd,"(") // nl command - || stringutils::startsWith(cmd,"{") // command sequence - ){ - return true; - } - // inquiries - if(first=="list"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if( second=="operators" - || second=="algebras" - || second=="databases" - || second=="types" - || second=="objects"){ - return !st.hasNextToken(); - } - if(second=="type"){ - if(!st.hasNextToken()){ - return false; - } - string third = st.nextToken(); - if(third!="constructors"){ - return false; - } - return !st.hasNextToken(); - } - if(second=="algebra"){ - if(!st.hasNextToken()){ - return false; - } - string third = st.nextToken(); - if(!stringutils::isIdent(third)){ - return false; - } - return !st.hasNextToken(); - } - return false; - } - // transactions - if( first=="begin" - || first=="commit" - || first=="abort"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(second!="transaction"){ - return false; - } - return !st.hasNextToken(); - } - // close database - if(first=="close"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(second!="database"){ - return false; - } - return !st.hasNextToken(); - } - // kill - if(first=="kill"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(!stringutils::isIdent(second)){ - return false; - } - return !st.hasNextToken(); - } - // save - if(first=="save"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(!stringutils::isIdent(second)){ - // not that also 'database' is a valid identifier - return false; - } - if(!st.hasNextToken()){ - return false; - } - if(st.nextToken()!="to"){ - return false; - } - // filename must be given - return st.hasNextToken(); - } - // restore - if(first=="restore"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(!stringutils::isIdent(second)){ - return false; - } - // bring object restore and database restore to the same rest - if(second=="database"){ - if(!st.hasNextToken()){ - return false; - } - second=st.nextToken(); - if(!stringutils::isIdent(second)){ - return false; - } - } - // check from - if(!st.hasNextToken()){ - return false; - } - if(st.nextToken()!="to"){ - return false; - } - return st.hasNextToken(); // the filename - } - // delete variants - if(first=="delete"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(!stringutils::isIdent(second)){ - return false; - } - if(!st.hasNextToken()){ // delete object - return true; - } - if(second!="database" && second != "type"){ - return false; - } - if(!st.hasNextToken()){ // type or database name - return false; - } - string third = st.nextToken(); - if(!stringutils::isIdent(third)){ - return false; - } - return !st.hasNextToken(); - } - // create commands - if(first=="create"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(!stringutils::isIdent(second)){ - return false; - } - if(!st.hasNextToken()){ - return false; - } - string third = st.nextToken(); - if(second=="database"){ - if(!stringutils::isIdent(third)){ - return false; - } - return !st.hasNextToken(); - } - // object creattion - if(third!=":"){ - return false; - } - return st.hasNextToken(); - } - // let, derive & type - if(first=="let" || first=="derive" || first=="type"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(!stringutils::isIdent(second)){ - return false; - } - if(!st.hasNextToken()){ - return false; - } - string third = st.nextToken(); - if(third!="="){ - return false; - } - return st.hasNextToken(); - } - // update - if(first=="update"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(!stringutils::isIdent(second)){ - return false; - } - if(!st.hasNextToken()){ - return false; - } - string third = st.nextToken(); - if(third!=":="){ - return false; - } - return st.hasNextToken(); - } - // currently, no other secondo commands are known - // extend here if this changed - - return false; - -} - - -/* -~catalogChanges~ - -This funciton checks whether a direct secondo command manipulates -the content of a database. In such cases. the optimizer has to be -informed about this. - -*/ -bool catalogChanges(const string& cmd){ - stringutils::StringTokenizer st(cmd, blanks2, true); - if(!st.hasNextToken()){ - return false; - } - string first = st.nextToken(); - if( first=="if" || stringutils::startsWith(cmd, "{") - || first=="kill" || first=="derive" - || first=="let" || stringutils::startsWith(cmd,"(") - || first=="restore"){ - return true; - } - if( first =="create" || first=="delete"){ - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - return second!="database"; - } - - return false; -} - - -/* -~closeOptDB~ - -This function calles the closeDB predicate of the optimizer. - -*/ -bool closeOptDB(){ - fid_t fid = PL_open_foreign_frame(); - static predicate_t p; - p=PL_predicate("closeDB",0,""); - qid_t id; - bool ok= false; - try{ - term_t dummy = PL_new_term_ref(); - id = PL_open_query(NULL, PL_Q_NORMAL, p, dummy); - if(PL_next_solution(id)){ - ok = true; - } - PL_close_query(id); - } catch(...){ - ok = false; - } - PL_discard_foreign_frame(fid); - return ok; -} - - - -/* -~updateOptCatalog~ - -This function updates the optimizer's catalog. - -*/ -bool updateOptCatalog(){ - if(plttydebug){ - cout << "Updating the optimizer's catalog" << endl; - } - - fid_t fid = PL_open_foreign_frame(); - static predicate_t p; - p=PL_predicate("updateCatalog",0,""); - qid_t id; - bool ok= false; - try{ - term_t dummy=PL_new_term_ref(); - id = PL_open_query(NULL, PL_Q_NORMAL, p, dummy); - if(PL_next_solution(id)){ - ok = true; - } - PL_close_query(id); - } catch(...){ - ok = false; - } - if(!ok){ - cout << "update optimizer catalog failed" << endl; - } - PL_discard_foreign_frame(fid); - return ok; -} - - -/* -~showResult~ - -Shows a nested list in a formatted manner. - -*/ -void showResult(ListExpr res){ - if(!mnl->HasLength(res,2)){ - mnl->WriteStringTo(res,cout); - } else { - if(!DisplayTTY::GetInstance().DisplayResult(mnl->First(res), - mnl->Second(res))){ - mnl->WriteStringTo(res,cout); - } - } - cout << endl << endl; -} - - -bool isBlank(char c){ - for(size_t i=0;i > detectSelects(const string& cmd, bool& ok){ - vector > res; - // search for ( * select ... ) within cmd and - // returns the positions of the brackets within cmd - // if several such constrvcts are present in cmd, all - // occurrences will be returned - size_t pos=0; - size_t state = 0; - // 0 = outside select - // 1 = inside double quoted string outside select - // 2 = inside single quoted string outside select - // 3 = after bracket outside select - // 4 = after s - // 5 = after e - // 6 = after l - // 7 = after e - // 8 = after c - // 9 = after t - // 10 = select reached - // 11 = inside double quoted string inside select - // 12 = inside single quoted string inside select - - int open_brackets = 0; // number of open round brackets - // within select - - int begin=-1; - - while(pos < cmd.length()){ - char c = cmd[pos]; - switch(state){ - case 0 : - switch(c){ - case '"' : state = 1; break; - case '\'' : state = 2; break; - case '(' : state = 3; - begin = pos; - break; - // for all other cases, the state is not changed - } - pos++; - break; - case 1 : - if(c=='"'){ - state = 0; - } - pos++; - break; - case 2 : - if(c=='\''){ - state = 0; - } - pos++; - break; - case 3: - if(c=='s'){ - state = 4; - pos++; - } else if(isBlank(c)){ - pos++; - } else { - state = 0; - } - break; - case 4: - if(c=='e'){ - state = 5; - pos++; - } else { - state = 0; - } - break; - case 5: - if(c=='l'){ - state = 6; - pos++; - } else { - state = 0; - } - break; - case 6: - if(c=='e'){ - state = 7; - pos++; - } else { - state = 0; - } - break; - case 7: - if(c=='c'){ - state = 8; - pos++; - } else { - state = 0; - } - break; - case 8: - if(c=='t'){ - state = 9; - pos++; - } else { - state = 0; - } - break; - case 9: - if(isBlank(c)){ - state = 10; - pos++; - } else { - state = 0; - } - break; - - case 10: - switch(c){ - case '"' : state=11; break; - case '\'' : state=12; break; - case '(' : open_brackets++; break; - case ')' : - if(open_brackets==0){ - // end of select reached - res.push_back(pair(begin,pos)); - state = 0; - } else { - open_brackets--; - } - } - pos++; - break; - case 11: - if(c=='"'){ - state=10; - } - pos++; - break; - case 12: - if(c=='\''){ - state=10; - } - pos++; - break; - default : assert(false); - } - } - ok = (state==0) && (open_brackets==0); - return res; -} - - -string select2Secondo(const string& select, bool& correct){ - string errMsg; - string cmd = checkSQLCommand("sql "+select,correct, errMsg); - if(!correct){ - cout << "syntax error in command :" << errMsg << endl; - return ""; - } - fid_t fid = PL_open_foreign_frame(); - term_t a0 = PL_new_term_refs(2); - PL_put_atom_chars(a0, (cmd).c_str()); - predicate_t p = PL_predicate("sqlToPlan",2,""); - qid_t id; - string plan=""; - - try{ - id = PL_open_query(NULL, PL_Q_CATCH_EXCEPTION, p, a0); - if(PL_next_solution(id)){ - char* res; - if(PL_get_atom_chars(a0+1,&res)){ - string answer(res); - if(stringutils::startsWith(answer,"::ERROR::")){ - errMsg = answer.substr(9); - correct = false; - } else { - cmd = answer; - } - } else { - correct = false; - } - } - PL_close_query(id); - } catch(...){ - errMsg = "Exception occurred"; - correct = false; - } - PL_discard_foreign_frame(fid); - return cmd; -} - - -string rewriteSelects(const string& cmd, bool& ok){ - vector > selects = detectSelects(cmd,ok); - if((selects.size()==0) || !ok){ - return cmd; - } - string res=""; - size_t posCmd = 0; - size_t posSel = 0; - while(posCmd < cmd.length() && ok){ - int l = selects[posSel].first - posCmd; - res += cmd.substr(posCmd, l); - res += "( "+ select2Secondo(cmd.substr(selects[posSel].first + 1, - selects[posSel].second - (1 + selects[posSel].first)),ok) - + " )"; - posCmd = selects[posSel].second + 1; - posSel++; - if(posSel==selects.size()){ - res += cmd.substr(posCmd); - posCmd = cmd.length(); - } - } - if(ok){ - cout << endl; - cout << "command after replacing embedded select clauses:" << endl; - cout << res << endl << endl; - } - - return res; -} - - -/* -~processDirectSecondoCommand~ - -This functions sends a command to the kernel and shows the -result. - -*/ -bool processDirectSecondoCommand(string cmd){ - SecErrInfo err; - ListExpr resList; - - if(stringutils::startsWith(cmd,"close")){ - // redirect to close predicate - bool ok = closeOptDB(); - if(ok){ - cout << "database successfully closed" << endl; - } else { - cout << "closing database failed" << endl; - } - return ok; - } else if(stringutils::startsWith(cmd,"(")){ - // assume command in nested list format - ListExpr cmdList; - if(!mnl->ReadFromString(cmd,cmdList)){ - cout << "Error in parsing command in nested list format"; - return false; - } - si->Secondo(cmdList, resList,err); - } else { - // usual secondo command without in user level syntax - bool ok=true; - cmd = rewriteSelects(cmd, ok); - if(!ok){ - cout << "error during detecting embedded select clauses" << endl; - return false; - } - si->Secondo(cmd, resList, err); - } - if(err.code==0){ - // output of result - showResult(resList); - // special treatment for optimizer - if(catalogChanges(cmd)){ - cout << "Catalog has been changed" << endl; - updateOptCatalog(); - } - } else { - cout << "error in command " << cmd << endl; - cout << "error code = " << err.code << endl; - cout << err.msg << endl << endl; - } - return err.code==0; -} - -/* -~show Error~ - -prints ou some error message. - -*/ -void showError(const string& s){ - cerr << s << endl; -} - - -/* -~getBindings~ - -Converts a bindings description into a vector of bindings/term pairs. - -*/ -bool getBindings( term_t bindings, - vector > & res ){ - - - // bindings should be a list of ' = ( name, term )' - if(!PL_is_list(bindings)){ - cerr << "bindings is not a list" << endl; - return false; - } - - while(!PL_get_nil(bindings)){ - term_t head = PL_new_term_ref(); - term_t tail = PL_new_term_ref(); - if(!PL_get_list(bindings, head, tail)){ - cerr << "problem in dividing list" << endl; - return false; - } - bindings = tail; // get the rest of the list - size_t arity; - term_t name = PL_new_term_ref(); - if(!PL_get_name_arity(head, &name, &arity)){ - cerr << "name_arity failed" << endl; - return false; - } - if(arity!=2){ - cerr << "found invalid arity in binding" << endl; - return false; - } - term_t a1 = PL_new_term_ref(); - if(!PL_get_arg(1, head,a1)){ - cerr << "get a1 failed" << endl; - return false; - } - term_t a2 = PL_new_term_ref(); - if(!PL_get_arg (2,head,a2)){ - cerr << "get a2 failed" << endl; - return false; - } - string s1; - char* s; - if(PL_get_chars(a1,&s, CVT_ALL)){ - s1 = string(s); - } else { - cerr << "getting a1's name failed" << endl; - return false; - } - pair p(s1, a2); - res.push_back(p); - } - return true; - } - - - -/* -3.5 ~display~ - -*/ -bool display(term_t t) { - string st = term2string(t); - cout << st; - return true; -} - -/* -~processPrologCommand~ - -This function processes an arbitrary prolog question. -It converts the string into a term and extract the variables -within the term. -After that, the predicate is called and for each existing -solution, the values are printed out. - -*/ -bool processPrologCommand(const string& cmd){ - - - if(plttydebug){ - cout << "process prolog command: " << endl - << cmd - << endl; - } - - fid_t fid = PL_open_foreign_frame(); - - // convert command into a string and get list of bindings - predicate_t conv = PL_predicate("atom_to_term", 3,""); - term_t a0 = PL_new_term_refs(3); - term_t term = a0+1; - term_t bindings = a0+2; - PL_put_atom_chars(a0, cmd.c_str()); - - if(!PL_call_predicate(NULL, PL_Q_NODEBUG, conv, a0)){ - cerr << "converting string to query failed" << endl; - PL_discard_foreign_frame(fid); - return false; - } - - if(!PL_is_callable(term)){ - cerr << "Created term is not a query" << endl; - return false; - } - - // extract variables and there names - vector > b; - if(!getBindings( bindings, b)){ - cerr << "problem in analyisng term" << endl; - PL_discard_foreign_frame(fid); - return false; - } - - // try to avaluate the term using the call predicate - predicate_t pl_call = PL_predicate("call",1,""); - qid_t qid = PL_open_query(NULL, PL_Q_CATCH_EXCEPTION, pl_call, term); - // print all solutions - int count = 0; - bool next = true; - while(next && PL_next_solution(qid)){ - if(count > 0){ - char k = getChar(); - next = k!='.'; - if(next){ - cout << ";" << endl; - } - } - if(next){ - count++; - for(size_t i=0;i0){ - showError(errMsg); - } - return false; - } - if((count !=1)){ - cout << "found no solution in optimization" << endl; - return false; - } - cout << endl; - cout << "Optimized plan is:" << endl << plan << endl; - cout << endl << "Estimated Costs are:" << endl << costs << endl << endl; - - if(isStdInput && isDot){ - char k=' '; - do{ - cout << "execute query ? (y/n) "; - k = getChar(); - k = tolower(k); - } while((k!='n') && (k!='y')); - cout << endl; - if(k=='n'){ - return true; - } - } - - return processDirectSecondoCommand(plan); -}; - - -/* -~isSqlCommand~ - -This function checks whether a command is a sql command. - -*/ - -bool isSqlCommand(string& cmd){ - string cmdcopy = cmd; - stringutils::trim(cmdcopy); - stringutils::toLower(cmdcopy); - if(cmdcopy.length()==0){ // empty command - return false; - } - if(cmdcopy[0]=='{'){ // command sequence - return false; - } - stringutils::StringTokenizer st(cmdcopy, blanks2, true); - if(!st.hasNextToken()){ - return false; - } - string first = st.nextToken(); - // complete sql command - if(first=="sql"){ - return true; // no change required - } - // without sql, first token is sufficient - if(first == "drop"){ - cmd = "sql " + cmd; - return true; - } - if(first == "select"){ - cmd = "sql " + cmd; - return true; - } - if(first == "union"){ - cmd = "sql " + cmd; - return true; - } - if(first == "intersection"){ - cmd = "sql " + cmd; - return true; - } - - // next token required - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - if(first=="delete" && second=="from"){ - cmd = "sql " + cmd; - return true; - } - if(first=="insert" && second=="into"){ - cmd = "sql " + cmd; - return true; - } - if(first=="create" && second=="table"){ - cmd = "sql " + cmd; - return true; - } - if(first=="create" && second=="index"){ - cmd = "sql " + cmd; - return true; - } - // third token required - if(!st.hasNextToken()){ - return false; - } - string third = st.nextToken(); - if(first=="update" && third=="set"){ - cmd = "sql " + cmd; - return true; - } - return false; -} - - -bool rewriteRestore(string& cmd){ - stringutils::StringTokenizer st(cmd," \t\n",true); - if(!st.hasNextToken()) return false; - string first = st.nextToken(); - if(first!="restore"){ - return false; - } - // the restore commands have the following formats - // restore a from b - // restore database a from b - // note that b may contain spaces - if(!st.hasNextToken()){ - return false; - } - string second = st.nextToken(); - string database = ""; - string name =""; - if(second == "database"){ - database = "database "; - if(!st.hasNextToken()){ - return false; - } - name = st.nextToken(); - } else { - name = second; - } - if(!stringutils::isSymbol(name)){ // invalid database or object name - return false; - } - if(!st.hasNextToken()){ - return false; - } - if(st.nextToken()!="from"){ - return false; - } - if(!st.hasNextToken()){ - return false; - } - string filename = st.getRest(); - stringutils::trim(filename); - if(!stringutils::startsWith(filename,"'")){ - filename = "'" + filename + "'"; - } - if(!stringutils::startsWith(name,"'")){ - name = "'" + name + "'"; - } - cmd = "restore " + database + name + " from " + filename; - return true; -} - - -/* -~rewriteLet~ - -This function checkes whether cmd is in form -let IDENT = expr -and expr starts with one of the keywords select, union, or intersection - -In this case, the command is returned as let(IDENT,expr) -Otherwise the command is returns completely unchanged - -*/ - -std::string rewriteLet(std::string& cmd){ - stringutils::StringTokenizer st(cmd," \t\n",true); - if(!st.hasNextToken()){ - return cmd; - } - string first = st.nextToken(); - if(first!="let"){ - return cmd; - } - if(!st.hasNextToken()){ - return cmd; - } - string ident = st.nextToken(); - if(!stringutils::isIdent(ident)){ - return cmd; - } - if(!st.hasNextToken()){ - return cmd; - } - string assign = st.nextToken(); - if(assign!="="){ - return cmd; - } - string rest = st.getRest(); - if(!st.hasNextToken()){ - return cmd; - } - hasOuterBrackets(rest, true); - stringutils::StringTokenizer st2(rest," \t\n",true); - if(!st2.hasNextToken()){ - return cmd; - } - string sqlindicator = st2.nextToken(); - if(sqlindicator == "select" - || sqlindicator == "union" - || sqlindicator == "intersection"){ - - bool correct; - string errMsg; - string conv = checkSQLCommand(rest, correct, errMsg); - if(!correct){ - cout << "sql part of an let command not correct :" << rest << endl; - cout << errMsg << endl; - return cmd; - } - - ident = "'"+ident+"'"; - string res = "let(" + ident+"," + conv+")"; - if(plttydebug){ - cout << "rewite let command to " << res << endl; - } - return res; - } - return cmd; -} - - -/* -~processCommand~ - -This function determines the kind of the command and calles the -appropriate command handler. - -*/ -bool processCommand(string& cmd){ - stringutils::trim(cmd); - - cmd = rewriteLet(cmd); - - bool isDot = !cmd.empty() && (cmd[cmd.length()-1]=='.'); - if(IsInternalCommand(cmd)){ - if(plttydebug){ - cout << "internal command recognized" << endl; - } - return processInternalCommand(cmd); - } else if (isSqlCommand(cmd)) { - if(plttydebug){ - cout << "sql command recognized" << endl; - } - return processSqlCommand(cmd,isDot); - } else if(isDirectSecondoCommand(cmd)){ - if(plttydebug){ - cout << "direct secondo command recognized" << endl; - } - return processDirectSecondoCommand(cmd); - } else { - if(plttydebug){ - cout << "general prolog command recognized" << endl; - } - if(rewriteRestore(cmd)){ - if(plttydebug){ - cout << "restore command recognized and rewritten to " - << cmd << endl; - } - } - return processPrologCommand(cmd); - } -} - - - - - - -/* -~processCommands~ - -This function extracts commands from a stream and executes them. -If haltOnErrors is true, the processing is stoped immediately -if an error is occured. If the flag ~pdstyle~ is set, comments -in pd style in the stream are ignored during processing. - -*/ -bool processCommands(istream& in, bool haltOnErrors, bool pdstyle ){ - string cmd = ""; - bool error = false; - bool stop = false; - while((cmd!="quit") && (cmd!="q") && !globalAbort && !stop && !in.eof()){ - cmd = getCommand(in, pdstyle); - stringutils::trim(cmd); - if(cmd.length()>0){ - if(!processCommand(cmd)){ - cout << "Error occurred during command '" << cmd << "'" << endl; - error = true; - if(haltOnErrors){ - stop = true; - } - } - } - } - return !error; -} - - -} // end of namespace pltty - - -/* -The function ~secondo\_completion~ enables -tab extension if the readline library is used. - -*/ -#ifdef HAVE_LIBREADLINE -extern char** secondo_completion(const char* text, int start, int end); -#endif - - -/* -2 SecondoPLTTYMode - -This function is the ~main~ function of SecondoPLTTY. - -*/ - - -int SecondoPLTTYMode(TTYParameter& tp) -{ - atexit(handle_exit); - - if( !StartSecondoC(tp) ) - { - cout << "Usage : SecondoPL [Secondo-options] [Prolog-options]" - << endl; - exit(1); - } - -#ifdef HAVE_LIBREADLINE - rl_initialize(); - rl_readline_name = "secondopl"; - rl_attempted_completion_function = secondo_completion; - //rl_attempted_completion_function = secondo_completion; - /* read the history from file */ - ifstream hist_file(HISTORY_FILE); - string histline; - if(hist_file){ - string query(""); - while(!hist_file.eof()){ - getline(hist_file,histline); - if(histline.find_last_not_of(" \t\n")!=string::npos){ - if(query!=""){ - query = query + "\n" + histline; - } else { - query = histline; - } - } else if(query.length()>0){ - add_history(query.c_str()); - query = ""; - } - } - if(query!=""){ - add_history(query.c_str()); - query = ""; - } - hist_file.close(); - } -#endif - - /* Start PROLOG interpreter with our extensions. */ - PL_register_extensions(predicates); - - /* initialize the PROLOG engine */ - - int argc = 0; - char** argv = tp.Get_plargs(argc); - - cerr << endl <<__FILE__ << ":" << __LINE__ - << " Calling PL_initialize with "; - - for (int i = 0; i < argc; i++) { - cerr << argv[i] << " "; - } - cerr << endl << endl; - - if( !PL_initialise(argc,argv) ) - { - PL_halt(1); - } - else - { - { - // VTA - 15.11.2005 - // I added this piece of code in order to run with newer versions - // of prolog. Without this code, the libraries (e.g. list.pl) are - // not automatically loaded. It seems that something in our code - // (auxiliary.pl and calloptimizer.pl) prevents them to be - // automatically loaded. In order to solve this problem I added - // a call to 'member(x, []).' so that the libraries are loaded - // before running our scripts. - term_t t0 = PL_new_term_refs(2), - t1 = t0+1; - PL_put_atom_chars(t0, "x"); - if(!PL_put_list_chars(t1, "")){ - assert(false); - } - predicate_t p = PL_predicate("member",2,""); - PL_call_predicate(NULL,PL_Q_NORMAL,p,t0); - // end VTA - } - - /* load the auxiliary and calloptimizer */ - term_t a0 = PL_new_term_refs(1); - static predicate_t p = PL_predicate("consult",1,""); - PL_put_atom_chars(a0,"auxiliary"); - PL_call_predicate(NULL,PL_Q_NORMAL,p,a0); - PL_put_atom_chars(a0,"calloptimizer"); - PL_call_predicate(NULL,PL_Q_NORMAL,p,a0); - /* switch to prolog-user-interface */ - } - - mnl = si->GetNestedList(); - //DisplayTTY::Set_SI(si); - DisplayTTY::Set_NL(mnl); - NList::setNLRef(mnl); - DisplayTTY::Initialize(); - bool ok; - if(tp.iFileName.length()==0){ - ok = pltty::processCommands(cin, false, false); - } else { - ok = pltty::processScript("@"+tp.iFileName); - } - -#ifdef HAVE_LIBREADLINE - /* - * save the last HISTORY_FILE_ENTRIES elements of the - * history to a file - */ - - fstream out_history; - out_history.open(HISTORY_FILE, fstream::out | fstream::trunc); - if(! out_history.bad()) { - HIST_ENTRY* he; - - int start_history = max(history_length - HISTORY_FILE_ENTRIES, 0); - for(int i = start_history; i < history_length; i++) { - he = history_get(i); - if(he) { - out_history << he->line << endl << endl; - } - } - - out_history.close(); - } else { - cerr << "Error: could not write the SECONDO history file" << endl; - } -#endif - - DisplayTTY::Finish(); - - PL_halt(0); - - return ok?0:1; - -} - diff --git a/UserInterfaces/SecondoTTY.cpp b/UserInterfaces/SecondoTTY.cpp index f95c7d7f80..0982777d81 100755 --- a/UserInterfaces/SecondoTTY.cpp +++ b/UserInterfaces/SecondoTTY.cpp @@ -103,6 +103,13 @@ then you will be prompted for the filename. #include "SecondoSMI.h" #include "NestedList.h" #include "DisplayTTY.h" +#include "ErrorCodes.h" +#include "SQLLanguage.h" + +// The embedded build optimizes SQL in-process via these helpers. +#ifndef NO_OPTIMIZER +#include "SecondoPL.h" +#endif #include "CharTransform.h" #include "LogMsg.h" #include "TTYParameter.h" @@ -294,8 +301,14 @@ SecondoTTY::MatchQuery(string& cmdWord, istringstream& is) const size_t pos = cmd.find("query"); size_t pos2 = cmd.find("querynt"); size_t pos3 = cmd.find("pquery"); - - if ((pos == string::npos) && (pos2==string::npos) && (pos3==string::npos)){ + // The SQL dialect ("sql ..." or bare "select ...") produces a result to be + // displayed too. + size_t pos4 = cmd.find("sql"); + size_t pos5 = cmd.find("select"); + size_t pos6 = cmd.find("SELECT"); + + if ((pos == string::npos) && (pos2==string::npos) && (pos3==string::npos) + && (pos4==string::npos) && (pos5==string::npos) && (pos6==string::npos)){ return isQuery; } @@ -305,7 +318,8 @@ SecondoTTY::MatchQuery(string& cmdWord, istringstream& is) const cmdWord = cmdWord.substr(1); } - if ( (cmdWord == "QUERY") || (cmdWord== "QUERYNT") || (cmdWord=="PQUERY") ) + if ( (cmdWord == "QUERY") || (cmdWord== "QUERYNT") || (cmdWord=="PQUERY") + || (cmdWord=="SQL") || (cmdWord=="SELECT") ) { isQuery = true; } @@ -314,7 +328,8 @@ SecondoTTY::MatchQuery(string& cmdWord, istringstream& is) const if ( cmdWord == "" ) { cmdWord = ReadCommand(is); - if((cmdWord == "QUERY") || (cmdWord == "QUERYNT") || (cmdWord=="PQUERY")) + if((cmdWord == "QUERY") || (cmdWord == "QUERYNT") || (cmdWord=="PQUERY") + || (cmdWord=="SQL") || (cmdWord=="SELECT")) isQuery = true; else isQuery = false; @@ -541,6 +556,50 @@ SecondoTTY::ShowQueryResult( ListExpr list ) } +/* +10.1 Reporting what the optimizer did + +The rules that tell the three input languages apart live in ~SQLLanguage.h~ -- +one definition, shared with the server, so that the same typed command routes +the same way whichever client it was typed in. SecondoCS does not apply them at +all: it asks the server (command level ~CMD\_LEVEL\_AUTO~) and is told what the +server decided. The standalone SecondoBDB has no server to ask and calls them +directly. + +The helpers below are the part that is genuinely the TTY's own: how the outcome +is presented. Both binaries share them, so the two look alike. + +*/ + +#if defined(SECONDO_CLIENT_SERVER) || !defined(NO_OPTIMIZER) + +/* +Show the optimizer's cost estimate for the plan it just produced. Printed +separately from the plan so both clients report it the same way, and skipped +when there is no estimate (the optimizer yields 0 for a plan it did not cost, +and for create/drop, which it executes itself). + +*/ +static void showCosts(double costs) +{ + if ( costs <= 0.0 ) return; + cout << color(blue) << "Estimated costs: " << costs + << color(normal) << endl; +} + +/* +Say that the plan was not run, so an empty result is not mistaken for a query +that returned nothing. + +*/ +static void showPlanOnlyNote(bool planOnly) +{ + if ( !planOnly ) return; + cout << color(blue) << "Plan only -- not executed." << color(normal) << endl; +} + +#endif + /* 11 CallSecondo @@ -558,11 +617,200 @@ SecondoTTY::CallSecondo() string errorMessage = ""; string errorText = ""; - if ( cmd[cmd.find_first_not_of(" \n\r\t\v\b\a\f")] == '(' ) + // An explicit "optimizer " prefix addresses the optimizer directly -- the + // same prefix the JavaGUI offers. What follows decides what it means: + // optimizer optimize only, show the plan, do NOT run it + // optimizer run an optimizer control directive + // Without the prefix, SQL is optimized *and* executed, which is the common + // case and what a bare "select ..." does. + // + // optCmd is the command with the prefix removed; it is what gets sent, so + // the optimizer never sees the keyword itself. + string optCmd = cmd; + bool optPrefix = stripOptimizerPrefix( cmd, optCmd ); + +#ifdef SECONDO_CLIENT_SERVER + + // SecondoCS classifies nothing: it sends the command and the server answers + // with the level it resolved it to. The presentation below is picked from + // that answer, so the client cannot disagree with the server about which + // language a command was written in. + int level = CMD_LEVEL_TEXT; + ((SecondoInterfaceCS*) si)->SecondoAuto( optCmd, optPrefix, level, outList, + errorCode, errorPos, errorMessage ); + NList::setNLRef(nl); + + if ( errorCode == 0 && level == CMD_LEVEL_SQL ) + { + // The answer is the list (optimizedPlan result costs). With the + // "optimizer " prefix the server stopped after optimizing, so the result + // half is empty. + // Accept any length from two upwards: costs was appended to the original + // (plan result) shape, so a server that does not send it still works. + if ( nl->ListLength( outList ) >= 2 ) + { + string planStr = ""; + if ( nl->AtomType( nl->First( outList )) == TextType ) + { + nl->Text2String( nl->First( outList ), planStr ); + } + if ( planStr == "done" ) + { + // create/drop: the server's optimizer carried the command out itself + // (same wording as the standalone build, see the embedded branch). + cout << endl << color(blue) + << "Executed by the optimizer (no plan to run)." + << color(normal) << endl; + } + else + { + cout << endl << color(blue) << "Optimized plan: " << planStr + << color(normal) << endl; + if ( nl->ListLength( outList ) >= 3 + && nl->AtomType( nl->Third( outList )) == RealType ) + { + showCosts( nl->RealValue( nl->Third( outList )) ); + } + showPlanOnlyNote( optPrefix ); + } + outList = nl->Second( outList ); + } + } + else if ( errorCode == 0 && level == CMD_LEVEL_OPT_DIRECTIVE ) + { + // An optimizer control goal (showOptions, setOption(X), ...): what it + // produced is the text it printed, returned as a single text atom. + string out = ""; + if ( nl->AtomType( outList ) == TextType ) + { + nl->Text2String( outList, out ); + } + cout << endl << out << endl; + outList = nl->TheEmptyList(); + } + +#else + + size_t cmdStart = cmd.find_first_not_of(" \n\r\t\v\b\a\f"); + + // The standalone SecondoBDB has no server to ask, so it applies the shared + // rules (SQLLanguage.h) itself. Same rules, same routing -- the two clients + // cannot drift apart. + bool isSql = false; + bool isOptDirective = false; +#ifndef NO_OPTIMIZER + isSql = looksLikeSql( optCmd ); + if ( !isSql && cmdStart != string::npos ) + { + isOptDirective = optPrefix ? true : isOptimizerDirective( cmd ); + } +#endif + + // "optimizer ": stop after optimizing and report the plan. + bool planOnly = optPrefix && isSql; + + if ( isSql ) + { +#ifndef NO_OPTIMIZER + // Run the optimizer in-process to turn the SQL into an executable plan, + // then execute the plan. + if ( !initEmbeddedOptimizer( si ) ) + { + errorCode = ERR_OPTIMIZER_NOT_AVAILABLE; + errorMessage = "Could not initialize the optimizer."; + } + else + { + if ( SecondoSystem::GetInstance()->IsDatabaseOpen() ) + { + embeddedOptimizerUseDatabase( + SecondoSystem::GetInstance()->GetDatabaseName() ); + } + string plan = "", optErr = ""; + double costs = 0.0; + bool alreadyExecuted = false; + if ( embeddedSqlToPlan( optCmd, plan, costs, optErr, alreadyExecuted ) ) + { + if ( alreadyExecuted ) + { + // create/drop: the optimizer carried the command out itself. + cout << endl << color(blue) + << "Executed by the optimizer (no plan to run)." + << color(normal) << endl; + } + else + { + cout << endl << color(blue) << "Optimized plan: " << plan + << color(normal) << endl; + showCosts( costs ); + showPlanOnlyNote( planOnly ); + if ( !planOnly ) + { + si->Secondo( plan, cmdList, CMD_LEVEL_TEXT, false, false, + outList, errorCode, errorPos, errorMessage ); + NList::setNLRef(nl); + } + } + // DDL run through the optimizer changes the catalog it has cached; + // refresh it so later queries see the new schema. Not conditional on + // planOnly: sqlToPlan carries create/drop out while translating, so + // "plan only" cannot keep them from changing the catalog. + if ( errorCode == 0 && embeddedOptimizerSqlChangesCatalog( optCmd ) ) + { + string refreshErr = ""; + embeddedOptimizerRefreshCatalog( refreshErr ); + NList::setNLRef(nl); + } + } + else + { + errorCode = ERR_OPTIMIZER_NOT_AVAILABLE; + errorMessage = "Optimization failed: " + optErr; + } + } +#else + // Should be unreachable: isSql is only set when an optimizer is reachable. + errorCode = ERR_OPTIMIZER_NOT_AVAILABLE; + errorMessage = "SQL is not available (optimizer not compiled in)."; +#endif + } + else if ( isOptDirective ) + { +#ifndef NO_OPTIMIZER + // Run the directive in the in-process optimizer. + if ( !initEmbeddedOptimizer( si ) ) + { + errorCode = ERR_OPTIMIZER_NOT_AVAILABLE; + errorMessage = "Could not initialize the optimizer."; + } + else + { + if ( SecondoSystem::GetInstance()->IsDatabaseOpen() ) + { + embeddedOptimizerUseDatabase( + SecondoSystem::GetInstance()->GetDatabaseName() ); + } + string out = "", optErr = ""; + if ( embeddedOptimizerRunGoal( optCmd, out, optErr ) ) + { + cout << endl << out << endl; + } + else + { + // A failing directive may still have printed something useful. + cout << endl << (out.empty() ? optErr : out) << endl; + } + } +#else + errorCode = ERR_OPTIMIZER_NOT_AVAILABLE; + errorMessage = "The optimizer is not available (not compiled in)."; +#endif + } + else if ( cmdStart != string::npos && cmd[cmdStart] == '(' ) { if ( nl->ReadFromString( cmd, cmdList ) ) { - si->Secondo( cmd, cmdList, 0, false, false, + si->Secondo( cmd, cmdList, CMD_LEVEL_NESTED_LIST, false, false, outList, errorCode, errorPos, errorMessage ); NList::setNLRef(nl); } @@ -574,11 +822,13 @@ SecondoTTY::CallSecondo() } else { - si->Secondo( cmd, cmdList, 1, false, false, + si->Secondo( cmd, cmdList, CMD_LEVEL_TEXT, false, false, outList, errorCode, errorPos, errorMessage ); NList::setNLRef(nl); } +#endif + if ( errorCode != 0 ) { si->WriteErrorList( outList ); @@ -710,8 +960,16 @@ SecondoTTY::Execute() if ( isStdInput ) { - cout << endl << "Secondo TTY ready for operation." << endl - << "Type 'HELP' to get a list of available commands." << endl; + cout << endl << "Secondo TTY ready for operation." << endl; +#ifdef SECONDO_CLIENT_SERVER + cout << "Optimizer (SQL dialect): " + << (((SecondoInterfaceCS*)si)->optimizerAvailable() + ? "available" : "not available") + << " on the connected server." << endl; +#elif !defined(NO_OPTIMIZER) + cout << "Optimizer (SQL dialect): available (in-process)." << endl; +#endif + cout << "Type 'HELP' to get a list of available commands." << endl; ProcessCommands( false, false); } else diff --git a/UserInterfaces/TestRunner.cpp b/UserInterfaces/TestRunner.cpp index fad7e571f0..9594b121c1 100755 --- a/UserInterfaces/TestRunner.cpp +++ b/UserInterfaces/TestRunner.cpp @@ -97,6 +97,7 @@ This is the test enviroment for Secondo. The code is derived from SecondoTTY. #include "LogMsg.h" #include "ExampleReader.h" #include "TTYParameter.h" +#include "SQLLanguage.h" using namespace std; @@ -1275,7 +1276,7 @@ TestRunner::CallSecondo() { if ( nl->ReadFromString( cmd, cmdList ) ) { - si->Secondo( cmd, cmdList, 0, false, false, + si->Secondo( cmd, cmdList, CMD_LEVEL_NESTED_LIST, false, false, outList, errorCode, errorPos, errorMessage ); } else @@ -1286,7 +1287,7 @@ TestRunner::CallSecondo() else { cout << cmd << endl; - si->Secondo( cmd, cmdList, 1, false, false, + si->Secondo( cmd, cmdList, CMD_LEVEL_TEXT, false, false, outList, errorCode, errorPos, errorMessage ); } } diff --git a/UserInterfaces/makefile b/UserInterfaces/makefile index 8cead1219f..f0bf7d276b 100755 --- a/UserInterfaces/makefile +++ b/UserInterfaces/makefile @@ -28,7 +28,6 @@ include ../makefile.env LIBXML2 := SECONDOPLMODE1 := SecondoPLMode -SECONDOPLMODE2 := SecondoPLTTYMode APPLOBJECTS := \ SecondoTTY.$(OBJEXT) \ @@ -37,7 +36,8 @@ APPLOBJECTS := \ MainTTY.$(OBJEXT) \ cmsg.$(OBJEXT) \ MainTTYCS.$(OBJEXT) \ - getCommand.$(OBJEXT) + getCommand.$(OBJEXT) \ + SQLLanguage.$(OBJEXT) APPLICATIONS := $(BINDIR)/Secondo$(SMIUP) \ $(BINDIR)/SecondoCS \ @@ -66,10 +66,8 @@ CCFLAGS += -DSECONDO_USE_ENTROPY endif ifeq ($(optimizer),"true") -PLOBJ := SecondoPL.$(OBJEXT) $(SECONDOPLMODE1).$(OBJEXT) $(SECONDOPLMODE2).$(OBJEXT) -PLCSOBJ := SecondoPLCS.$(OBJEXT) $(SECONDOPLMODE1).$(OBJEXT) $(SECONDOPLMODE2).$(OBJEXT) +PLOBJ := SecondoPL.$(OBJEXT) $(SECONDOPLMODE1).$(OBJEXT) PL_OBJECTS := $(PLOBJ) $(ENTROPY_OBJ) -PLCS_OBJECTS := $(PLCSOBJ) $(ENTROPY_OBJ) APPLOBJECTS += $(PLOBJ) CCFLAGS += $(PLINCLUDEFLAGS) -DSECONDO_PL endif @@ -120,7 +118,7 @@ entropy: .PHONY: clean clean: - $(RM) *.dep $(APPLOBJECTS) $(APPLICATIONS) $(ENTROPY_OBJ) $(DEP_FILES) $(PLCSOBJ) $(CS_OBJECTS) + $(RM) *.dep $(APPLOBJECTS) $(APPLICATIONS) $(ENTROPY_OBJ) $(DEP_FILES) $(CS_OBJECTS) $(MAKE) -C InteractiveQueryEditor clean # @@ -135,13 +133,10 @@ MainTTYCS.$(OBJEXT): MainTTY.cpp SecondoPL.$(OBJEXT): $(ENTROPY_OBJ) %.$(OBJEXT): %.cpp - $(CC) -c -o $@ $< $(CCFLAGS) $(JNIINCLUDE) $(CPPSTDOPTION) + $(CC) -c -o $@ $< $(CCFLAGS) $(JNIINCLUDE) $(CPPSTDOPTION) -SecondoPLCS.$(OBJEXT): SecondoPL.cpp - $(CC) -c -DSECONDO_CLIENT_SERVER -o $@ $< $(CCFLAGS) $(CPPSTDOPTION) - -SecondoTTYCS.$(OBJEXT): SecondoTTY.cpp - $(CC) -c -DSECONDO_CLIENT_SERVER -o $@ $< $(CCFLAGS) $(CPPSTDOPTION) +SecondoTTYCS.$(OBJEXT): SecondoTTY.cpp + $(CC) -c -DSECONDO_CLIENT_SERVER -o $@ $< $(CCFLAGS) $(CPPSTDOPTION) TestRunnerCS.$(OBJEXT): TestRunner.cpp $(CC) -c -DSECONDO_CLIENT_SERVER -o $@ $< $(CCFLAGS) $(CPPSTDOPTION) @@ -161,7 +156,12 @@ $(BINDIR)/Secondo$(SMIUP)$(EXEEXT): $(APP_LIB) $(ALG_LIST) $(FLOB) $(PL_OBJECTS # The TTY-Clients, they use special implementations of SecondoInterface and don't # need the algebra libs. # +# SecondoCS is a pure client/server TTY client. It does NOT embed the optimizer +# (no -pl / -pltty); the SQL dialect is sent to the server's optimizer instead. +# It always needs readline (for the interactive history); in optimizer builds +# RL_LD_FLAG is empty because readline used to come in via the (now removed) +# Prolog link flags, so link it explicitly here. $(BINDIR)/SecondoCS$(EXEEXT): $(SECLIBFILES) $(FLOB) -$(BINDIR)/SecondoCS$(EXEEXT): $(CS_OBJECTS) $(APP_LIB) $(PLCS_OBJECTS) $(FLOB) - $(LD) $(EXEFLAGS) $(LDFLAGS) $(PROFILERFLAGS) -o $@ $(filter %.o, $^) -lappCommon -lsdbutils $(OPTLIB_LIBS) $(LD_LINK_LIBS) $(RL_LD_FLAG) $(PLLDFLAGS) $(COMMON_LD_FLAGS) +$(BINDIR)/SecondoCS$(EXEEXT): $(CS_OBJECTS) $(APP_LIB) $(FLOB) + $(LD) $(EXEFLAGS) $(LDFLAGS) $(PROFILERFLAGS) -o $@ $(filter %.o, $^) -lappCommon -lsdbutils $(OPTLIB_LIBS) $(LD_LINK_LIBS) $(RL_LD_FLAG) -lreadline -lncurses $(COMMON_LD_FLAGS) diff --git a/WebUI/README.md b/WebUI/README.md index a551d9e098..466a4c9f89 100644 --- a/WebUI/README.md +++ b/WebUI/README.md @@ -294,9 +294,10 @@ leaves the view exactly where you put it. Use the `⤢` button to re-fit on dema - Streaming large results over the WebSocket (`/api/stream`) and query-history persistence. -- Include the optimizer (add it to the REST backend, implement the port), allow - to run SQL-line queries from the WebUI. In the existing UI, you need to start - the OptServer for that. +- Include the optimizer (add it to the REST backend), allow to run SQL-like + queries from the WebUI. The kernel server now runs the optimizer itself + (command level 2), so the backend can send SQL over its existing connection + instead of talking to a separate server. - Additional projections beyond BerlinMOD as needed. - Remaining long-tail types (network/JNet, precise geometry, raster) still fall back to the textual nested-list view, as `DsplGeneric` does in the Java GUI. diff --git a/bin/TotalTest b/bin/TotalTest index 667e3af054..5ea9e5ea95 100755 --- a/bin/TotalTest +++ b/bin/TotalTest @@ -7,7 +7,6 @@ BIN=$SECONDO_BUILD_DIR/bin LOGFILEMON=$BIN/TotalTest.monitor.log -LOGFILEOPT=$BIN/TotalTest.optserver.log LOGFILE=$BIN/TotalTest.log PID=$$ @@ -93,18 +92,7 @@ fi echo "Monitor is running" sleep 5 -echo "StartOptServer" - -#start OptServer -cd $SECONDO_BUILD_DIR/Optimizer -StartOptServer -q -t >$LOGFILEOPT 2>&1 & - - -echo "Optimizer server is running" - -sleep 3 - -echo "Start Tests" +echo "Start Tests" declare -i err=0 @@ -138,7 +126,6 @@ else fi -echo "Terminate OptServer" echo "Terminate Monitor" kill -SIGTERM $mon 2>/dev/null diff --git a/bin/startSession b/bin/startSession index c1ab727df1..51fa796dc9 100755 --- a/bin/startSession +++ b/bin/startSession @@ -6,11 +6,6 @@ xterm -e "cd $SECONDO_BUILD_DIR/bin/; ./SecondoMonitor -s" & sleep 5 -xterm -e "cd $SECONDO_BUILD_DIR/Optimizer/; StartOptServer" & - - -sleep 5 - xterm -e "cd $SECONDO_BUILD_DIR/Javagui; ./sgui" & diff --git a/include/CSProtocol.h b/include/CSProtocol.h index 87a14de15c..466185ef8f 100644 --- a/include/CSProtocol.h +++ b/include/CSProtocol.h @@ -93,18 +93,38 @@ Afterwards the Client can send one of the requests explained below. The most interesting one is to send a Secondo command to the server. ---- - \n - cmdLevel\n - line1\n + \n + cmdLevel[ flag]...\n + line1\n ... lineN\n \n ---- -"cmdLevel" is an integer, it values could be 0 (list-syntax) or 1 (SOS-syntax). -The command itself can be wrapped into several lines. Every command which is -known by the SecondoInterface (see "SecondoInterface.h") can be used. Note: The -command cannot contain the line "". +"cmdLevel" is an integer: 0 (list syntax), 1 (SOS syntax) or 2 (SQL, which the +server hands to its embedded optimizer). The command itself can be wrapped into +several lines. Every command which is known by the SecondoInterface (see +"SecondoInterface.h") can be used. Note: The command cannot contain the line +"". + +The rest of the level line carries per-command protocol flags, a part the +server has always discarded, so a flag is invisible to a peer that does not +know it. Two are defined (see "SQLLanguage.h"): "planonly" stops an SQL command +after optimizing, and "optimizer" says the user addressed the optimizer +explicitly. + +A client that does not want to decide which of the three languages a typed +command is written in sends the level -1 instead and lets the server classify +it. The server then answers with the level it resolved to, ahead of everything +else: + +---- + level\n +---- + +where "level" is 0, 1, 2 or 3 (an optimizer control goal, whose result is the +text it printed). This line is written only for a client that asked, so the +protocol is unchanged for one sending an explicit level. The response will be a list which may be returned in text or binary representation. diff --git a/include/ErrorCodes.h b/include/ErrorCodes.h index 22b67ec7d1..168b6ef137 100644 --- a/include/ErrorCodes.h +++ b/include/ErrorCodes.h @@ -97,6 +97,7 @@ const SI_Error ERR_IN_LIST_STRUCTURE_IN_FILE = 29; const SI_Error ERR_CMD_NOT_YET_IMPL = 30; const SI_Error ERR_CMD_LEVEL_NOT_YET_IMPL = 31; const SI_Error ERR_CMD_NOT_IMPL_AT_THIS_LEVEL = 32; +const SI_Error ERR_OPTIMIZER_NOT_AVAILABLE = 33; /* The next error messages belong to five groups: diff --git a/include/SQLLanguage.h b/include/SQLLanguage.h new file mode 100644 index 0000000000..129c42a5eb --- /dev/null +++ b/include/SQLLanguage.h @@ -0,0 +1,121 @@ +/* +---- +This file is part of SECONDO. + +Copyright (C) 2026, +University in Hagen, +Faculty of Mathematics and Computer Science, +Database Systems for New Applications. + +SECONDO is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +SECONDO is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with SECONDO; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +---- + +1 Which language is a typed command written in? + +SECONDO understands three input languages: nested lists, the SOS text syntax, +and the SQL handled by the optimizer. Which one a typed command belongs to used +to be decided by every client for itself -- the TTYs, the JavaGUI and +the JDBC driver each carried their own copy of the rules -- and the copies had +to be kept in step, or the same command started behaving differently in the GUI +and in a TTY talking to the same server. + +The classification is a property of the *language*, not of the client, so it +lives here, next to the dispatch it feeds. Clients ask the server to classify by +sending the command level ~CMD\_LEVEL\_AUTO~; the server answers with the level +it resolved to (see ~SecondoServer::CallSecondo~). The one client that has no +server to ask -- the standalone SecondoBDB, which runs the optimizer in-process +-- calls the functions below directly. Two call sites, one rule set. + +*/ + +#ifndef SEC_SQL_LANGUAGE_H +#define SEC_SQL_LANGUAGE_H + +#include + +/* +1.1 Command levels + +The levels 0 to 2 are the ones a command is actually executed at and the only +ones a client may send besides ~CMD\_LEVEL\_AUTO~, the sentinel that asks the +server to classify the command. ~CMD\_LEVEL\_OPT\_DIRECTIVE~ only ever appears +in the server's answer, never in a request. + +Whether the user addressed the optimizer explicitly is not a language but an +intent about execution, so it rides on the per-command protocol flags of the +level line next to ~planonly~, not on a level of its own. + +*/ +const int CMD_LEVEL_NESTED_LIST = 0; // nested list syntax +const int CMD_LEVEL_TEXT = 1; // SOS text syntax +const int CMD_LEVEL_SQL = 2; // SQL, optimized and executed +const int CMD_LEVEL_OPT_DIRECTIVE = 3; // optimizer control goal (reply only) + +const int CMD_LEVEL_AUTO = -1; // server, you decide + +/* +1.2 The rules + +~looksLikeSql~ tells whether a command is written in SQL and therefore has to go +to the optimizer. Deciding this is not a matter of the first keyword alone: +~delete~, ~create~, ~update~ and ~let~ exist in both languages and are told +apart by the following token(s). Anything not recognized falls through to the +kernel -- the fallback is always the kernel. + +~isOptimizerDirective~ recognizes the optimizer's control goals (~showOptions~, +~setOption(X)~, ~updateCatalog~, ...). They are neither SQL nor kernel commands: +they are Prolog goals run by the optimizer, and what they produce is the text +they print. + +~deriveKernelCommandLevel~ picks 0 or 1 for a command that is neither: a leading +~(~ means nested list syntax, anything else is text. It is inline because a pure +client -- one that never classifies, but still has to recognize the ~save~ and +~restore~ commands it carries out itself -- needs this and nothing else; that +way such a client links without the rule set below (see ~SecondoInterfaceCS~, +which the C++ API packages on its own). + +~resolveCommandLevel~ combines the three and is what the server calls. With +~optimizerAddressed~ (the client sent the ~optimizer~ flag because the user +wrote the ~optimizer~ prefix) anything that is not SQL is taken to be a +directive, so arbitrary optimizer goals can be run; without it only the known +directive names are. + +*/ +bool looksLikeSql(const std::string& cmd); + +bool isOptimizerDirective(const std::string& cmd); + +inline int deriveKernelCommandLevel(const std::string& cmd) +{ + size_t s = cmd.find_first_not_of(" \t\n\r\f\v\b\a"); + if ( s != std::string::npos && cmd[s] == '(' ) return CMD_LEVEL_NESTED_LIST; + return CMD_LEVEL_TEXT; +} + +int resolveCommandLevel(const std::string& cmd, bool optimizerAddressed); + +/* +1.3 The ~optimizer~ prefix + +Strips a leading ~optimizer~ keyword -- the way a user addresses the optimizer +explicitly -- and puts the remainder into ~rest~. Returns false and leaves +~rest~ = ~cmd~ if the prefix is not there. What follows the prefix decides what +it means: SQL is optimized but not executed, anything else is run as a +directive. + +*/ +bool stripOptimizerPrefix(const std::string& cmd, std::string& rest); + +#endif diff --git a/include/SecondoInterface.h b/include/SecondoInterface.h index c299b20ce7..82c2ddc8d1 100755 --- a/include/SecondoInterface.h +++ b/include/SecondoInterface.h @@ -138,6 +138,9 @@ in the treatment of the database state in database commands. #include "NestedList.h" #include "StopWatch.h" #include "CSProtocol.h" +// The command levels the Secondo procedure below takes, and the rules that +// decide which one a typed command belongs to. +#include "SQLLanguage.h" @@ -251,14 +254,24 @@ The command is one of a set of "Secondo"[3] commands described below. The parameters have the following meaning. A "Secondo"[3] command can be given at various ~levels~; parameter -~commandLevel~ indicates the level of the current command. The levels -are defined as follows: +~commandLevel~ indicates the level of the current command. The levels are named +in ~SQLLanguage.h~ -- use the constants, not the numbers -- and are defined as +follows: - * 0 -- "Secondo"[3] executable command in nested list syntax (~list~) + * "CMD\_LEVEL\_NESTED\_LIST" (0) -- executable command in nested list syntax + (~list~) - * 1 -- "Secondo"[3] executable command in SOS syntax (~text~) + * "CMD\_LEVEL\_TEXT" (1) -- executable command in SOS syntax (~text~) -If the command is given in ~text~ syntax (command level 1), + * "CMD\_LEVEL\_SQL" (2) -- SQL, which is not executable: only a client/server + connection accepts it, and the server hands it to its embedded optimizer + (see "SecondoInterfaceCS::SecondoSql") + +A client that does not want to decide which of these a typed command is written +in sends "CMD\_LEVEL\_AUTO" instead and lets the server classify it; that is a +protocol level, not one this procedure executes. + +If the command is given in ~text~ syntax ("CMD\_LEVEL\_TEXT"), then the text string must be placed in ~commandText~. If the command is given in ~list~ syntax, it can be passed either as a text string in ~commandText~, in which case ~commandAsText~ must be "true"[4], or as a list diff --git a/include/SecondoInterfaceCS.h b/include/SecondoInterfaceCS.h index bf8b575f7f..5a407e8b37 100644 --- a/include/SecondoInterfaceCS.h +++ b/include/SecondoInterfaceCS.h @@ -220,6 +220,49 @@ class SecondoInterfaceCS : public SecondoInterface , MessageHandler { std::string getHome(); + // Asks the connected server whether the optimizer (SQL dialect, command + // level 2) is available (compiled in and enabled for that server). + bool optimizerAvailable(); + + // Sends a command without saying which language it is written in: the + // server classifies it (see SQLLanguage.h) and reports in resolvedLevel + // what it decided, which tells the caller how to read the answer -- + // CMD_LEVEL_SQL means the list (plan result costs), CMD_LEVEL_OPT_DIRECTIVE + // the text an optimizer goal printed, CMD_LEVEL_NESTED_LIST/_TEXT an + // ordinary result. With optimizerAddressed the "optimizer" protocol flag is + // sent along, saying the user wrote the "optimizer " prefix: SQL is then + // only optimized, not executed, and anything else is taken to be a + // directive. + void SecondoAuto( const std::string& command, + const bool optimizerAddressed, + int& resolvedLevel, + ListExpr& resultList, + int& errorCode, + int& errorPos, + std::string& errorMessage ); + + // Sends an SQL command (command level 2). The server optimizes it + // and answers with the list (plan result costs). With planOnly the + // "planonly" protocol flag is sent along and the server stops after + // optimizing: the plan and its costs come back, the result half is empty. + // (A create/drop is carried out by the optimizer while translating, so + // planOnly cannot suppress those.) + void SecondoSql( const std::string& sql, + const bool planOnly, + ListExpr& resultList, + int& errorCode, + int& errorPos, + std::string& errorMessage ); + + // Runs an optimizer control directive (a Prolog goal such as "showOptions", + // "setOption(subqueries)", "delOption(...)", "updateCatalog") in the + // server's embedded optimizer and returns the text the directive prints. + // On error the returned string carries the server's error message. + // This is the way in for a caller that already knows it wants a directive + // (the JavaGUI's Optimizer menu uses it); a caller that just passes on what + // the user typed uses SecondoAuto and lets the server recognize it. + std::string optimizerCommand(const std::string& directive); + std::string getHost() const; std::string getConnectionInfo() const; @@ -268,6 +311,20 @@ class SecondoInterfaceCS : public SecondoInterface , MessageHandler { std::string user; std::string pswd; bool multiUser; + // Protocol flag for the command currently being sent: ask the server to + // optimize the SQL but not to execute the plan. Set and cleared by + // SecondoSql, never sticky. + bool sqlPlanOnly; + // Protocol flag for the command currently being sent: the user addressed + // the optimizer explicitly. Set and cleared by SecondoAuto. + bool sqlOptimizerAddressed; + // The level the server resolved the last command to. Only meaningful + // after a command sent at one of the auto levels; otherwise it is the + // level that was sent. Read out by SecondoAuto. + int resolvedCmdLevel; + // Reads "n"; falls back to CMD_LEVEL_TEXT + // when the line is not the expected echo. + static int parseCommandLevelEcho(const std::string& line); std::vector messageListener; std::ostream* traceSocketIn; diff --git a/include/SecondoPL.h b/include/SecondoPL.h index 265d1e8f5a..04a67455f0 100755 --- a/include/SecondoPL.h +++ b/include/SecondoPL.h @@ -29,3 +29,90 @@ int registerSecondo(); } #endif +#ifdef __cplusplus +#include +class SecondoInterface; + +/* +Embed the optimizer into an already running SECONDO process (e.g. a forked +server) that owns ~serverSi~. Unlike ~registerSecondo~, this does NOT create a +second SecondoInterface/SMI environment; it reuses ~serverSi~ for the optimizer's +~secondo/2~ callbacks. The Prolog engine is started and the optimizer program +(~auxiliary~, ~calloptimizer~) is consulted with the working directory pointed +at ~SECONDO\_BUILD\_DIR/Optimizer~. Idempotent: a second call is a no-op. +Returns true on success. + +*/ +bool initEmbeddedOptimizer(SecondoInterface* serverSi); + +/* +True once ~initEmbeddedOptimizer~ has successfully loaded the optimizer. + +*/ +bool embeddedOptimizerReady(); + +/* +Translate an SQL-dialect query into an executable plan using the embedded +optimizer's ~sqlToPlan~ predicate. On success returns true and sets ~plan~ (a +~query ...~ command) and ~costs~ (the optimizer's estimate for that plan, 0.0 +when it has none); on failure returns false and sets ~errMsg~. + +~errMsg~ is plain, ready-to-display text. The optimizer reports its failures as +~::ERROR::~ plus the message written back as a Prolog term (quoted, with ~\\n~ +and ~\\'~ escapes); that encoding is undone here, so no client has to know it. + +*/ +/* +DDL note: for ~create ...~ and ~drop ...~ the optimizer's ~sqlToPlan~ performs +the operation itself and yields the sentinel atom ~done~ instead of a plan (see +~sqlToPlan2~ in Optimizer/optimizerNewProperties.pl). In that case this function +succeeds, sets ~plan~ to ~done~ and sets ~alreadyExecuted~ to true: the caller +must NOT execute ~plan~, there is nothing left to run. The sentinel is kept on +the wire because existing clients (e.g. the JDBC driver) already test for it. + +*/ +bool embeddedSqlToPlan(const std::string& sql, std::string& plan, + double& costs, std::string& errMsg, + bool& alreadyExecuted); + +/* +Ensure the embedded optimizer has loaded the schema of database ~dbName~ (the +one currently open at the kernel). The optimizer only learns a database's schema +when it is opened through its own logic, so this drives that (close + reopen) +when needed. Returns true if the optimizer now tracks the database. + +*/ +bool embeddedOptimizerUseDatabase(const std::string& dbName); + +/* +Run an arbitrary optimizer control directive (a Prolog goal given as text, e.g. +~showOptions~, ~setOption(subqueries)~, ~delOption(...)~, ~updateCatalog~, +~resetKnowledgeDB~) in the embedded optimizer. These directives do not produce a +result list; they ~write/1~ their feedback to the current output stream, so the +goal is run wrapped in ~with\_output\_to/2~ and whatever it prints is returned in +~output~. Returns true if the goal succeeded; on a Prolog exception or failure +~errMsg~ is set (the captured ~output~ is still returned, since a failing goal +may have written a useful message first). + +*/ +bool embeddedOptimizerRunGoal(const std::string& goal, std::string& output, + std::string& errMsg); + +/* +True if executing ~sql~ changes the database catalog (~create table~/~index~, +~drop~, or a ~let X = select ...~ that creates a new object). The optimizer +caches the catalog, so after such a command it must be refreshed -- otherwise +subsequent optimizations run against a stale schema. + +*/ +bool embeddedOptimizerSqlChangesCatalog(const std::string& sql); + +/* +Re-read the catalog of the open database into the optimizer (runs its +~updateCatalog~ goal). Call after a catalog-changing command, see +~embeddedOptimizerSqlChangesCatalog~. + +*/ +bool embeddedOptimizerRefreshCatalog(std::string& errMsg); +#endif + diff --git a/makefile b/makefile index 6331b77e0d..3754fd8e4f 100755 --- a/makefile +++ b/makefile @@ -189,40 +189,13 @@ endif .PHONY: optimizer -optimizer: optimizer2 optserver update-config +optimizer: optimizer2 update-config .PHONY: optimizer2 optimizer2: makedirs buildlibs buildAlgebras $(MAKE) -C Optimizer optimizer -.PHONY: optserver -optserver: makedirs buildlibs buildAlgebras buildapps -ifeq ($(compileJava),"true") -ifeq ($(optimizer),"true") -ifeq ($(j2sdkIsPresent),"true") - @echo; echo " *** Building JPL and the optimizer server *** "; echo - $(MAKE) -C Jpl all - $(MAKE) -C OptServer all - @chmod ugo+x Optimizer/StartOptServer -endif -endif -endif - -.PHONY: optsrv-msg -optsrv-msg: -ifeq ($(compileJava),"true") -ifeq ($(j2sdkIsPresent),"false") - @echo ; echo "JPL and the optimizer server were not compiled!" - $(j2sdk-msg) -endif -else - @echo ; echo "JPL and the optimizer server were not compiled!" - $(javac-msg) -endif - - - .PHONY: buildapps buildapps: buildlibs buildAlgebras @echo ; echo " *** Linking Applications *** "; echo @@ -251,9 +224,7 @@ clean: $(MAKE) -C Algebras clean $(MAKE) -C QueryProcessor clean $(MAKE) -C UserInterfaces clean - $(MAKE) -C Jpl clean $(MAKE) -C Javagui clean - $(MAKE) -C OptServer clean $(MAKE) -C OptParser clean $(MAKE) -C Optimizer clean $(MAKE) -C apis clean @@ -297,7 +268,7 @@ include ./makefile.cm ###################################################### .PHONY: update-config -update-config: config optsrv-msg showjni Documents/.Secondo-News.txt +update-config: config showjni Documents/.Secondo-News.txt .PHONY: showjni showjni: @@ -356,7 +327,7 @@ help: @echo "*** ---------------------------------------------------------------------" @echo "*** TTY : Compile only a single user version of Secondo." @echo "*** android : Compile android version of Secondo." - @echo "*** optimizer : Create only SecondoPL, SecondoPLCS and OptServer." + @echo "*** optimizer : Create only SecondoPL and the embedded optimizer." @echo "*** java : The Java-GUI will be created." @echo "*** TestRunner: Compile only the TestRunner, a tool to automate tests." @echo "*** " diff --git a/makefile.libs b/makefile.libs index ff436c1da6..283cc7e143 100755 --- a/makefile.libs +++ b/makefile.libs @@ -52,7 +52,8 @@ LIB_SDBUTILS_BASENAMES:=\ Tools/Flob/PersistentFlobCache \ Tools/Flob/ExternalFileCache \ Tools/Utilities/AlmostEqual \ - UserInterfaces/getCommand + UserInterfaces/getCommand \ + UserInterfaces/SQLLanguage # The following libraries have interdependencies to Nested lists # and Berkeley-DB thus they are only usable in the framework of diff --git a/makefile.optimizer b/makefile.optimizer index b411144916..4429947ef6 100755 --- a/makefile.optimizer +++ b/makefile.optimizer @@ -51,7 +51,11 @@ export OptMsg := "true" endif ifeq ($(optimizer),"true") -OPTIMIZER_SERVER := optserver +# When the optimizer is compiled in, the default build must also generate the +# concatenated optimizer program (Optimizer/optimizer). It is consulted at +# runtime by the kernel server and the TTY, which embed the optimizer to run +# the SQL dialect. optimizer2 builds it. +OPTIMIZER_SERVER := optimizer2 AUXLIBS := $(SECONDO_SDK)/auxtools/lib @@ -72,10 +76,7 @@ endif platform2 := $(subst 64,,$(platform)) ifeq ($(platform2),linux) ifndef GMP_LIB - PLVER := $(shell if [ $(PL_VERSION) -lt 50600 ]; then echo "5x"; else echo "6x"; fi) - ifeq ($(PLVER), 6x) - LD_GMP := -lgmpxx -lgmp - endif + LD_GMP := -lgmpxx -lgmp else LD_GMP := -l$(GMP_LIB) endif @@ -97,44 +98,4 @@ endif PLLDFLAGS += -loptparser -# define directories for using jpl - -ifndef PL_VERSION -JPLVER=10 -else - -ifeq ($(shell test $(PL_VERSION) -lt 50200; echo $$?),0) - JPLVER=10 -endif -ifeq ($(shell test $(PL_VERSION) -lt 70000; echo $$?),0) - JPLVER=30 -endif -ifeq ($(shell test $(PL_VERSION) -lt 80200; echo $$?),0) - JPLVER=70 -endif -ifeq ($(shell test $(PL_VERSION) -ge 80200; echo $$?),0) - JPLVER=82 -endif - -endif - -ifeq ($(JPLVER),10) -JPL_HEADER=jpl_fli_Prolog.h -else -JPL_HEADER=jpl.h -endif - -JPL_ROOT := $(BUILDDIR)/Jpl -JPL_LIB := $(JPL_ROOT)/lib -JPL_CLASS_TARGET := $(JPL_LIB)/classes -JPL_JAVA_SOURCES := $(JPL_ROOT)/jsrc/$(JPLVER) -JPL_DOC_TARGET := $(JPL_ROOT)/doc -JPL_CLASSPATH := .:$(JPL_CLASS_TARGET) -ifdef SECONDO_JAVART - JPL_CLASSPATH := $(JPL_CLASSPATH):$(SECONDO_JAVART) -endif -JPL_SRC := $(JPL_ROOT)/src -# directory which contains SecondoPl.o -SECONDOPL_DIR := $(BUILDDIR)/UserInterfaces - endif diff --git a/packaging/debian/README.md b/packaging/debian/README.md index 31d61dcd5d..99ae9b30cd 100644 --- a/packaging/debian/README.md +++ b/packaging/debian/README.md @@ -77,7 +77,8 @@ Without `--install-deps`, the build dependencies (the `Build-Depends` of Installs the package from `packaging/debian/out` in a pristine container and runs SECONDO in it as a normal user: it runs `secondo_installer.sh`, sources the generated `~/.secondorc`, and queries the shipped `opt` database through -`SecondoTTYBDB` and through the optimizer (`SecondoPLTTY`). +`SecondoTTYBDB` — both an executable-plan query and an SQL-dialect query, the +latter optimized in-process by the embedded optimizer. The container has nothing but the package — no build tree, no build dependencies. Everything SECONDO needs the package has to bring itself or to declare in its diff --git a/packaging/debian/debian/rules b/packaging/debian/debian/rules index d43e73d97a..0639e7b173 100755 --- a/packaging/debian/debian/rules +++ b/packaging/debian/debian/rules @@ -35,8 +35,7 @@ DESTDIR := $(CURDIR)/debian/secondo PREFIX := $(DESTDIR)/opt/secondo # The tools of Optimizer/ that the package makes available in /opt/secondo/bin. -OPTIMIZER_TOOLS := SecondoPL SecondoPLCS SecondoPLNT SecondoPLTTY \ - SecondoPLTTYCS SecondoPLTTYNT StartOptServer +OPTIMIZER_TOOLS := SecondoPL SecondoPLNT %: dh $@ diff --git a/packaging/debian/test-deb.sh b/packaging/debian/test-deb.sh index 3ca7619be0..fc5489b88d 100755 --- a/packaging/debian/test-deb.sh +++ b/packaging/debian/test-deb.sh @@ -57,9 +57,8 @@ printf '\n\n' | /opt/secondo/bin/secondo_installer.sh # shell of every user of the package with it. source ~/.secondorc -echo "PL_VERSION=$PL_VERSION" -echo "JPL_DLL=$JPL_DLL" -[ -f "$JPL_DLL" ] && echo "JPL_DLL_EXISTS=yes" || echo "JPL_DLL_EXISTS=no" +echo "SECONDO_BUILD_DIR=$SECONDO_BUILD_DIR" +echo "SWI_HOME_DIR=$SWI_HOME_DIR" [ -f /opt/secondo/bin/javagui/Javagui.jar ] && echo "JAVAGUI=yes" || echo "JAVAGUI=no" # The kernel, Berkeley DB and the 'opt' database shipped in the package. @@ -69,10 +68,11 @@ count() { sed -n 's/^[[:space:]]*\([0-9][0-9]*\)[[:space:]]*$/\1/p' | tail -1; } echo "TTYBDB_COUNT=$(printf "restore database opt from '/opt/secondo/bin/opt';\nquery ten count;\nquit;\n" \ | SecondoTTYBDB 2>&1 | count)" -# The embedded SWI-Prolog optimizer. This is what breaks when the launchers do -# not match the installed SWI-Prolog. -echo "PLTTY_COUNT=$(printf "open database opt;\nselect count(*) from ten;\nquit.\n" \ - | SecondoPLTTY 2>&1 | count)" +# The embedded SWI-Prolog optimizer, now driven directly from the regular TTY: +# a leading "select" (or "sql") is optimized in-process. This is what breaks +# when the optimizer does not match the installed SWI-Prolog. +echo "PLTTY_COUNT=$(printf "open database opt;\nselect count(*) from ten;\nquit;\n" \ + | SecondoTTYBDB 2>&1 | count)" USER_TESTS result() { sed -n "s/^$1=//p" /tmp/user-tests.log | tail -1; } @@ -80,11 +80,10 @@ result() { sed -n "s/^$1=//p" /tmp/user-tests.log | tail -1; } echo echo "### Results" check "~/.secondorc sources cleanly under set -e" "yes" \ - "$([ -n "$(result PL_VERSION)" ] && echo yes || echo no)" -check "JPL library exists at the detected path" "yes" "$(result JPL_DLL_EXISTS)" + "$([ -n "$(result SECONDO_BUILD_DIR)" ] && echo yes || echo no)" check "Java GUI is shipped" "yes" "$(result JAVAGUI)" check "SecondoTTYBDB: query ten count" "10" "$(result TTYBDB_COUNT)" -check "SecondoPLTTY: select count(*) from ten" "10" "$(result PLTTY_COUNT)" +check "SecondoTTYBDB: select count(*) from ten (embedded optimizer)" "10" "$(result PLTTY_COUNT)" if [ "$failed" -ne 0 ]; then echo diff --git a/packaging/debian/tools/secondo-optimizer b/packaging/debian/tools/secondo-optimizer index 04cadde54d..ae7fdf6639 100755 --- a/packaging/debian/tools/secondo-optimizer +++ b/packaging/debian/tools/secondo-optimizer @@ -9,7 +9,7 @@ # build directory. # # This script is installed under the name of every optimizer tool (SecondoPL, -# SecondoPLTTY, StartOptServer, ...). The name it is called by selects the +# SecondoPLNT, ...). The name it is called by selects the # launcher of the SECONDO sources that is executed -- those launchers know how # to start their tool (which SWI-Prolog stack options the installed swipl # understands, for example), and this script must not repeat that knowledge.