From fd236fe9cd7d55361e37dcf9000cf9bb565c38c3 Mon Sep 17 00:00:00 2001 From: Jan Nidzwetzki Date: Wed, 22 Jul 2026 21:07:55 +0200 Subject: [PATCH 1/4] Run the SQL dialect over the client/server protocol and in the TTY The kernel could only execute plans; the SQL dialect had to be optimized either in the standalone Prolog-embedded binaries (SecondoPL*TTY*) or via the separate Java OptServer. This teaches the server and the TTY to run SQL directly through the embedded optimizer. Protocol: add command level 2 (SQL dialect) to the existing framing. SecondoServer::CallSecondo routes level 2 to the embedded optimizer (before any si->Secondo call, so the optimizer's secondo/2 catalog callbacks are not reentrant), turns the SQL into an executable plan, executes it, and returns the two-element list (plan result) -- a new, backward-compatible shape only level-2 clients see. SecondoInterfaceCS learns to send level 2 and to ask an capability query. Runtime toggle: the server reads Environment/EnableOptimizer (default on; override with SECONDO_PARAM_EnableOptimizer). SecondoMonitor gains a --no-optimizer flag (optimizer builds only) that sets that for the servers it forks. When disabled, level-2 returns ERR_OPTIMIZER_NOT_AVAILABLE and the capability query reports unavailable. Optimizer embedding: initEmbeddedOptimizer/embeddedSqlToPlan/ embeddedOptimizerUseDatabase (UserInterfaces/SecondoPL.cpp) start SWI-Prolog and load the optimizer in-process, sharing the host interface (no second SMI environment) and loading the open database's schema on demand. Preload library(error) so restricted autoloading no longer spams must_be/2 errors while the optimizer loads. TTY: a leading "sql" or "select" token (case-insensitive, prefix optional) is optimized -- over the network in SecondoCS, in-process in SecondoTTYBDB -- and the generated plan is shown. Both report optimizer availability at startup. Consolidation/cleanup: the regular TTY now runs SQL, so retire the hybrids -- remove SecondoPLCS/SecondoPLTTYCS and the -pl/-pltty logic from SecondoCS, and remove SecondoPLTTY/SecondoPLTTYNT and SecondoPLTTYMode (SecondoTTYBDB replaces -pltty). Keep the -pl raw Prolog shell. Build/CI: the default optimizer build now also generates the Optimizer/optimizer program the embedded optimizer consults at runtime (gitignored). A new CI step optimizes and executes an SQL query over the network deterministically. --- .gitignore | 2 + ClientServer/SecondoInterfaceCS.cpp | 97 +- ClientServer/SecondoMonitor.cpp | 24 +- ClientServer/SecondoServer.cpp | 270 ++- ClientServer/TestClientServer | 280 ++- OptServer/makefile | 3 + Optimizer/SecondoPLCS | 5 - Optimizer/SecondoPLTTY | 30 - Optimizer/SecondoPLTTYCS | 5 - Optimizer/SecondoPLTTYNT | 32 - QueryProcessor/SecondoInterfaceGeneral.cpp | 3 + UserInterfaces/MainTTY.cpp | 15 +- UserInterfaces/SecondoPL.cpp | 549 ++++++ UserInterfaces/SecondoPLTTYMode.cpp | 1968 -------------------- UserInterfaces/SecondoTTY.cpp | 375 +++- UserInterfaces/makefile | 32 +- include/ErrorCodes.h | 1 + include/SecondoInterfaceCS.h | 27 + include/SecondoPL.h | 87 + makefile.optimizer | 7 +- packaging/debian/README.md | 3 +- packaging/debian/debian/rules | 3 +- packaging/debian/test-deb.sh | 11 +- packaging/debian/tools/secondo-optimizer | 2 +- 24 files changed, 1738 insertions(+), 2093 deletions(-) delete mode 100755 Optimizer/SecondoPLCS delete mode 100755 Optimizer/SecondoPLTTY delete mode 100755 Optimizer/SecondoPLTTYCS delete mode 100755 Optimizer/SecondoPLTTYNT delete mode 100644 UserInterfaces/SecondoPLTTYMode.cpp 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/ClientServer/SecondoInterfaceCS.cpp b/ClientServer/SecondoInterfaceCS.cpp index 89c5ebfdd6..b91a6aba4b 100755 --- a/ClientServer/SecondoInterfaceCS.cpp +++ b/ClientServer/SecondoInterfaceCS.cpp @@ -90,6 +90,7 @@ SecondoInterfaceCS::SecondoInterfaceCS(bool isServer, /*= false*/ user = ""; pswd = ""; multiUser = false; + sqlPlanOnly = false; traceSocketIn = 0; traceSocketOut = 0; } @@ -514,9 +515,16 @@ For an explanation of the error codes refer to SecondoInterface.h cmdText = commandText; break; } + case 2: // SQL dialect: forwarded verbatim to the server's optimizer + { + dwriter.write(debugSecondoMethod, cout, this, pid, + "commandType 2 (sql)"); + 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; @@ -560,7 +568,8 @@ 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 ( commandType != 2 && + posDatabase != string::npos && posSave != string::npos && posTo != string::npos && posSave < posDatabase && posDatabase < posTo ) @@ -639,7 +648,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 ( commandType != 2 && + posSave != string::npos && // save object to filename posTo != string::npos && posDatabase == string::npos && posSave < posTo ) @@ -726,7 +736,8 @@ For an explanation of the error codes refer to SecondoInterface.h } } - else if ( posRestore != string::npos && + else if ( commandType != 2 && + posRestore != string::npos && posDatabase == string::npos && posFrom != string::npos && posRestore < posFrom ) @@ -802,7 +813,8 @@ For an explanation of the error codes refer to SecondoInterface.h } } - else if ( posDatabase != string::npos && + else if ( commandType != 2 && + posDatabase != string::npos && posRestore != string::npos && posFrom != string::npos && posRestore < posDatabase && posDatabase < posFrom ) @@ -890,7 +902,11 @@ 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" : "") << endl; dwriter.write(debugSecondoMethod, cout, this, pid, "CommandType send "); iosock << cmdText << endl; dwriter.write(debugSecondoMethod, cout, this, pid, "CommandText send "); @@ -1240,6 +1256,75 @@ 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"; +} + +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, 2, 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/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..e76565ab53 100755 --- a/ClientServer/SecondoServer.cpp +++ b/ClientServer/SecondoServer.cpp @@ -71,6 +71,11 @@ are implemented in class ~CSProtocol~ and can be used by inside the #include "CSProtocol.h" #include "NList.h" #include "satof.h" +#include "ErrorCodes.h" + +#ifndef NO_OPTIMIZER +#include "SecondoPL.h" +#endif using namespace std; @@ -144,24 +149,51 @@ 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); + // 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 +229,15 @@ 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. + string flags = ""; + getline( iosock, flags ); + debug_server(flags); + bool planOnly = flags.find("planonly") != string::npos; csp->IgnoreMsg(false); bool ready=false; do @@ -211,16 +251,214 @@ SecondoServer::CallSecondo() } } while (!ready && !iosock.fail()); + + // Command level 2 is the SQL dialect: 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 == 2 ) + { + CallSql( cmdText, !planOnly ); + 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 (command level 1, text syntax). + si->Secondo( plan, commandLE, 1, 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::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() { @@ -1002,6 +1240,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 +1362,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 +1406,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..2ad89f9fd1 100755 --- a/ClientServer/TestClientServer +++ b/ClientServer/TestClientServer @@ -8,7 +8,12 @@ # 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. @@ -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,268 @@ 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 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 +552,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/OptServer/makefile b/OptServer/makefile index d95edd0eb2..825cd2cc05 100755 --- a/OptServer/makefile +++ b/OptServer/makefile @@ -64,6 +64,9 @@ jsrc: regSecondo.o: regSecondo.c $(CC) -c -fPIC -g -ggdb -o $@ $(INCLUDEFLAGS) $< +$(SECONDOPL_DIR)/SecondoPLCS.o: + $(MAKE) -C $(SECONDOPL_DIR) SecondoPLCS.o + LINKFILES += $(PL_DLL) ifeq ($(platform),win32) 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/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/UserInterfaces/MainTTY.cpp b/UserInterfaces/MainTTY.cpp index 0a8f815ed9..6f59341e2d 100644 --- a/UserInterfaces/MainTTY.cpp +++ b/UserInterfaces/MainTTY.cpp @@ -60,7 +60,6 @@ extern int SecondoTestRunner(const TTYParameter&); #ifndef NO_OPTIMIZER extern int SecondoPLMode(TTYParameter&); -extern int SecondoPLTTYMode(TTYParameter&); #endif #ifndef SEC_TTYCS @@ -141,17 +140,17 @@ main( const int argc, char* argv[] ) ProgMesHandler* pmh = new ProgMesHandler(); msg->AddHandler(pmh); -#ifdef SECONDO_PL +// -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 - -#ifdef SECONDO_PL - if ( tp.isPLTTYMode() ) - return SecondoPLTTYMode(tp); -#endif - cout << License::getStr() << endl; // Testrunner or TTY or TTYCS diff --git a/UserInterfaces/SecondoPL.cpp b/UserInterfaces/SecondoPL.cpp index 620aa80eaa..6ce8004ef7 100755 --- a/UserInterfaces/SecondoPL.cpp +++ b/UserInterfaces/SecondoPL.cpp @@ -1371,3 +1371,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) exactly as the OptServer does: 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..01f61af3ab 100755 --- a/UserInterfaces/SecondoTTY.cpp +++ b/UserInterfaces/SecondoTTY.cpp @@ -103,6 +103,12 @@ then you will be prompted for the filename. #include "SecondoSMI.h" #include "NestedList.h" #include "DisplayTTY.h" +#include "ErrorCodes.h" + +// The embedded build optimizes the SQL dialect in-process via these helpers. +#ifndef NO_OPTIMIZER +#include "SecondoPL.h" +#endif #include "CharTransform.h" #include "LogMsg.h" #include "TTYParameter.h" @@ -294,8 +300,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 +317,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 +327,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 +555,157 @@ SecondoTTY::ShowQueryResult( ListExpr list ) } +/* +10.1 Recognizing the SQL dialect + +Deciding whether a typed command belongs to the optimizer or to the kernel 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). The rule +set below is the one the retired hybrid TTY (~SecondoPLTTYMode::isSqlCommand~) +and the JavaGUI (~CommandPanel.optimize~) independently arrived at. + +Anything not recognized here falls through to the kernel -- the fallback is +always the kernel, in every client. + +*/ + +#if defined(SECONDO_CLIENT_SERVER) || !defined(NO_OPTIMIZER) + +// Split cmd into at most maxTok lower-cased tokens. The delimiter set matches +// the JavaGUI's classifier, so that "let r5=select ..." and "create table t(a)" +// tokenize identically there and here. +static void sqlTokens(const std::string& cmd, std::vector& toks, + size_t maxTok) +{ + const string delims = " \t\n\r\f\v\b\a([{=.,;"; + 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; + } +} + +static bool looksLikeSql(const std::string& cmd) +{ + size_t s = cmd.find_first_not_of(" \t\n\r\f\v\b\a"); + if ( s == string::npos ) return false; + // nested list command or command sequence: always the kernel + if ( cmd[s] == '(' || cmd[s] == '{' ) return false; + + std::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" || t[0] == "drop" ) 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; + if ( t[0] == "create" && (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; +} + +/* +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; +} + +/* +Strip a leading ~optimizer~ keyword (the prefix the JavaGUI uses to address the +optimizer directly). Returns true and puts the remainder into ~rest~ if the +prefix was there; otherwise returns false and leaves ~rest~ = ~cmd~. + +*/ +static bool stripOptimizerPrefix(const std::string& cmd, std::string& rest) +{ + rest = cmd; + size_t s = cmd.find_first_not_of(" \t\n\r\f\v\b\a"); + 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(" \t\n\r\f\v\b\a", after); + if ( r == string::npos ) return false; + + rest = cmd.substr(r); + return true; +} + +// The optimizer control directives the TTY routes to the directive channel +// when they are typed bare. With an explicit "optimizer " prefix any non-SQL +// text is treated as a directive, so this list is only the convenience case. +static bool isBareOptimizerDirective(const std::string& cmd) +{ + size_t s = cmd.find_first_not_of(" \n\r\t\v\b\a\f"); + if ( s == string::npos ) return false; + size_t nameEnd = cmd.find_first_of(" \n\r\t\v\b\a\f(", 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; +} + +#endif + /* 11 CallSecondo @@ -558,7 +723,195 @@ SecondoTTY::CallSecondo() string errorMessage = ""; string errorText = ""; - if ( cmd[cmd.find_first_not_of(" \n\r\t\v\b\a\f")] == '(' ) + size_t cmdStart = 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 = false; +#if defined(SECONDO_CLIENT_SERVER) || !defined(NO_OPTIMIZER) + optPrefix = stripOptimizerPrefix( cmd, optCmd ); +#endif + + // Detect a leading "sql" or "select" token: the SQL dialect. Both forms are + // accepted (the "sql" prefix is optional), case insensitively. In the + // client/server build it is sent to the server (command level 2, or level 3 + // when only the plan is wanted) and optimized there; in the embedded build it + // is optimized in-process. The detection is only active where an optimizer is + // reachable. + bool isSql = false; +#if defined(SECONDO_CLIENT_SERVER) || !defined(NO_OPTIMIZER) + isSql = looksLikeSql( optCmd ); +#endif + + // "optimizer ": stop after optimizing and report the plan. + bool planOnly = optPrefix && isSql; + + // Detect an optimizer control directive (setOption(X), delOption(X), + // showOptions, updateCatalog, ...). Like the SQL detection above this is only + // active where an optimizer is reachable, and it is routed to the optimizer's + // directive channel below (over the network in SecondoCS, in-process in the + // standalone SecondoBDB). + // + // Bare, the known directive names are recognized. After an explicit + // "optimizer " prefix anything that is not SQL is a directive, so arbitrary + // optimizer goals can be run -- which is what the prefix does in the JavaGUI. + bool isOptDirective = false; +#if defined(SECONDO_CLIENT_SERVER) || !defined(NO_OPTIMIZER) + if ( !isSql && cmdStart != string::npos ) + { + isOptDirective = optPrefix ? true : isBareOptimizerDirective( cmd ); + } +#endif + + if ( isSql ) + { +#ifdef SECONDO_CLIENT_SERVER + // Client/server: send the SQL to the server, which optimizes it and + // returns the list (optimizedPlan result costs). With planOnly ("optimizer + // ") the server stops after optimizing and the result half comes back + // empty. + ((SecondoInterfaceCS*) si)->SecondoSql( optCmd, planOnly, outList, + errorCode, errorPos, errorMessage ); + NList::setNLRef(nl); + // 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 ( errorCode == 0 && 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( planOnly ); + } + outList = nl->Second( outList ); + } +#elif !defined(NO_OPTIMIZER) + // Embedded: 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, 1, 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 ) + { +#ifdef SECONDO_CLIENT_SERVER + // Client/server (SecondoCS): run the directive on the server's embedded + // optimizer via the channel and print what it wrote. + string out = ((SecondoInterfaceCS*)si)->optimizerCommand( optCmd ); + cout << endl << out << endl; +#elif !defined(NO_OPTIMIZER) + // Standalone (SecondoBDB): 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 ) ) { @@ -710,8 +1063,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/makefile b/UserInterfaces/makefile index 8cead1219f..da95d1e4a0 100755 --- a/UserInterfaces/makefile +++ b/UserInterfaces/makefile @@ -28,7 +28,6 @@ include ../makefile.env LIBXML2 := SECONDOPLMODE1 := SecondoPLMode -SECONDOPLMODE2 := SecondoPLTTYMode APPLOBJECTS := \ SecondoTTY.$(OBJEXT) \ @@ -66,10 +65,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 +117,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) SecondoPLCS.$(OBJEXT) $(MAKE) -C InteractiveQueryEditor clean # @@ -135,13 +132,19 @@ MainTTYCS.$(OBJEXT): MainTTY.cpp SecondoPL.$(OBJEXT): $(ENTROPY_OBJ) %.$(OBJEXT): %.cpp - $(CC) -c -o $@ $< $(CCFLAGS) $(JNIINCLUDE) $(CPPSTDOPTION) - + $(CC) -c -o $@ $< $(CCFLAGS) $(JNIINCLUDE) $(CPPSTDOPTION) + +# SecondoPLCS.o is SecondoPL compiled in client/server mode (SecondoInterfaceCS +# instead of SecondoInterfaceTTY). No TTY client embeds the optimizer anymore, +# so it is not part of this directory's own build; the sole consumer is the +# external Java OptServer's JNI bridge, which builds it on demand via this rule +# (see OptServer/makefile). The rule lives here because the source and the +# correct compile flags do. SecondoPLCS.$(OBJEXT): SecondoPL.cpp - $(CC) -c -DSECONDO_CLIENT_SERVER -o $@ $< $(CCFLAGS) $(CPPSTDOPTION) + $(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 +164,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/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/SecondoInterfaceCS.h b/include/SecondoInterfaceCS.h index bf8b575f7f..b03c640b98 100644 --- a/include/SecondoInterfaceCS.h +++ b/include/SecondoInterfaceCS.h @@ -220,6 +220,29 @@ 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 an SQL-dialect 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. + std::string optimizerCommand(const std::string& directive); + std::string getHost() const; std::string getConnectionInfo() const; @@ -268,6 +291,10 @@ 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; 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.optimizer b/makefile.optimizer index b411144916..9386599971 100755 --- a/makefile.optimizer +++ b/makefile.optimizer @@ -51,7 +51,12 @@ 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 -- not only by the OptServer, but now also by the kernel server and +# the TTY, which embed the optimizer to run the SQL dialect. optimizer2 builds +# it; optserver builds JPL and the (still optional) Java OptServer. +OPTIMIZER_SERVER := optimizer2 optserver AUXLIBS := $(SECONDO_SDK)/auxtools/lib 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..44af28ab71 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 StartOptServer %: dh $@ diff --git a/packaging/debian/test-deb.sh b/packaging/debian/test-deb.sh index 3ca7619be0..f2ce4c27ed 100755 --- a/packaging/debian/test-deb.sh +++ b/packaging/debian/test-deb.sh @@ -69,10 +69,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; } @@ -84,7 +85,7 @@ check "~/.secondorc sources cleanly under set -e" "yes" \ check "JPL library exists at the detected path" "yes" "$(result JPL_DLL_EXISTS)" 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..4231548583 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, StartOptServer, ...). 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. From ccda5fe59cec937a4cafac73ebcbcbca5b638bc0 Mon Sep 17 00:00:00 2001 From: Jan Nidzwetzki Date: Sat, 25 Jul 2026 16:39:34 +0200 Subject: [PATCH 2/4] Rewrite Java to use the new Optimizer protocol --- .../communication/CommunicationInterface.java | 141 ++-- Javagui/communication/makefile | 35 - .../communication/optimizer/ErrorCodes.java | 61 -- Javagui/communication/optimizer/IntObj.java | 24 - .../optimizer/OptimizerInterface.java | 251 ------ .../optimizer/OptimizerSettingsDialog.java | 139 ---- Javagui/communication/optimizer/makefile | 38 - Javagui/gui.cfg.example | 8 +- Javagui/gui/CommandPanel.java | 729 +++++++----------- Javagui/gui/MainWindow.java | 94 +-- Javagui/makefile | 2 - .../secondoInterface/sj/lang/ESInterface.java | 21 +- .../sj/lang/SecondoInterface.java | 138 +++- Javagui/viewer/hoese2/gui/MainWindow.java | 94 +-- 14 files changed, 583 insertions(+), 1192 deletions(-) delete mode 100755 Javagui/communication/makefile delete mode 100755 Javagui/communication/optimizer/ErrorCodes.java delete mode 100755 Javagui/communication/optimizer/IntObj.java delete mode 100755 Javagui/communication/optimizer/OptimizerInterface.java delete mode 100755 Javagui/communication/optimizer/OptimizerSettingsDialog.java delete mode 100755 Javagui/communication/optimizer/makefile diff --git a/Javagui/JDBC/communication/CommunicationInterface.java b/Javagui/JDBC/communication/CommunicationInterface.java index 30de6b061a..90f0f488d1 100644 --- a/Javagui/JDBC/communication/CommunicationInterface.java +++ b/Javagui/JDBC/communication/CommunicationInterface.java @@ -1,6 +1,4 @@ package communication; -import communication.optimizer.OptimizerInterface; -import communication.optimizer.IntObj; import java.sql.SQLException; import tools.Reporter; @@ -18,7 +16,6 @@ public class CommunicationInterface { private final String AlterTempTabName = "typeTesttmp"; //AlterTabTmp - private OptimizerInterface OI; private ESInterface SI; private ListExpr LEresult; private IntByReference ErrCode; @@ -26,7 +23,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 +36,7 @@ public CommunicationInterface() { ErrMess = new StringBuffer(); LEresult = new ListExpr(); - OI = new OptimizerInterface(); SI = new ESInterface(); - OptIO = new IntObj(); connectedToDB = false; } @@ -50,7 +44,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 +64,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 +112,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 +166,80 @@ 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 + * (command level 2) and answers with the list (plan result costs). + * @param command the command in the SQL dialect + * @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, 2, 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 +250,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 +304,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..c2fca95a0d 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 @@ -348,23 +327,6 @@ private boolean isSymbolElement(char c){ - /** 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'); @@ -465,300 +427,131 @@ private boolean checkBrackets(String str, StringBuffer errMsg){ } - private String[] rewriteForOptimizer(String str){ - - String prefix ="query "; - String suffix=""; - if(str.matches("let\\s+[a-z,A-Z][a-z,A-Z,0-9,_]*\\s*=\\s*select(.|\n)*")){ - int ass = str.indexOf('='); - prefix = str.substring(0,ass).trim(); // without = - str = str.substring(ass+1,str.length()).trim(); - String[] cmdVar = prefix.split("\\s+"); - prefix = "let "+cmdVar[1]+" = "; - } - - String res = varToLowerCase(str); - - res = replacePoint(res); - - res = res ; - - if(showRewrittenOptimizerQuery){ - appendText("\nrewritten query: \n"+ res + "\n\n"); - } - String[] r = {prefix,res,suffix}; - return r; - } - - - /** Replaces variables having format a.b by a:b. - **/ - private String replacePoint( String str){ - - // states - // 0 start state - // 1 within double quoted string - // 2 within single quoted string - // 3 within symbol - - StringBuffer buf = new StringBuffer(); - int state = 0; - - for(int i=0;i = select|union|intersection ...": an SQL right hand side. + // The server splits the prefix off and re-wraps the generated plan. + if(t[0].equals("let") && ( t[2].equals("select") || t[2].equals("union") + || t[2].equals("intersection"))){ + return true; + } + return false; + } - private String varToLowerCase(String str) { - StringBuffer buf = new StringBuffer(); - int state = 0; //normal = 0, inDoublequotes = 1 in quotes = 2 - int pos = 0; - - - // the states are the following - // state 0 : begin of a symbol or something other - // state 1 : within a double quoted string - // state 2 : within a single quoted text - // state 3 : within a symbol starting with a capital, all chars are converted to lower case - // state 4 : within a symbol starting with a lower case, all chars are keept - - 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(); - - // 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"); - } + if(OpenedDatabase.length()==0){ + appendText("\nno database open"); showPrompt(); - return ""; - } else { - return pre_command_suf[0] + opt + pre_command_suf[2]; - } - } + return false; + } + StringBuffer buf = new StringBuffer(); + if(!checkBrackets(command,buf)){ + appendText("\n\n"+buf.toString()); + showPrompt(); + return false; + } + return true; + } @@ -830,9 +623,11 @@ 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, exactly as in the TTY clients: + // "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 +637,59 @@ public boolean execUserCommand (String command, return !success; } } + String optCommand = command.substring(OptString.length()).trim(); + + if(isSqlCommand(optCommand)){ + return execServerCommand(optCommand,true,isTest,success,epsilon, + isAbsolute,expectedResult); + } + long starttime=0; if(tools.Environment.MEASURE_TIME) starttime = System.currentTimeMillis(); - int OptCommandLength = eval?EvalString.length():OptString.length(); - - String answer = sendToOptimizer(command.substring(OptCommandLength)); + String answer = sendToOptimizer(optCommand); 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); - } - } + showPrompt(); + if(!isTest){ + return false; + } else{ + return !success; + } + } else { + appendText("\n"+answer); + showPrompt(); + if(!isTest){ + return true; + }else{ + return success; + } } } - - // normal command + + return execServerCommand(command,false,isTest,success,epsilon,isAbsolute, + expectedResult); + } + + + /** Sends one command to the connected server and processes its result. + * An SQL command (auto detected) is optimized by the server at command + * level 2; anything else is sent unchanged at level 0/1. With planOnly the + * server stops after optimizing, so the plan is reported and nothing runs. + * @see #execUserCommand(String,boolean,boolean,double,boolean,ListExpr) + */ + private boolean execServerCommand (String command, + boolean planOnly, + boolean isTest, + boolean success, + double epsilon, + boolean isAbsolute, + ListExpr expectedResult) { ListExpr displayErrorList; int displayErrorCode; @@ -909,25 +702,35 @@ 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; - } - } + int commandLevel = SecondoInterface.DERIVE_COMMAND_LEVEL; + if(isSqlCommand(command)){ + if(!canSendSql(command)){ + if(!isTest){ + return false; + } else{ + return !success; + } + } + commandLevel = 2; // SQL dialect: the server optimizes it + } 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, + planOnly); + + if(commandLevel==2 && errorCode.value==0){ + // the answer is (plan result costs); render the result half + resultList.setValueTo(unwrapSqlAnswer(resultList,planOnly)); + } if(tools.Environment.MEASURE_TIME){ Reporter.writeInfo("used time for query: "+ @@ -1010,18 +813,45 @@ 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); + if(!sendCommandToServer(cmd,resultList,errorCode,errorPos,errorMessage)){ + return false; + } return errorCode.value==0; } + /** Sends a command to the server at the level it belongs to: an SQL command + * (auto detected) is optimized by the server at command level 2, anything + * else is sent unchanged. A level 2 answer is unwrapped to its result half, + * so the caller sees the same shape as for a kernel command. + * Returns false when an SQL command could not be sent at all; the reason + * has then been written to the panel. + */ + private boolean sendCommandToServer(String command, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage){ + boolean isSql = isSqlCommand(command); + if(isSql && !canSendSql(command)){ + return false; + } + Secondointerface.secondo(command,resultList,errorCode,errorPos,errorMessage, + isSql?2:SecondoInterface.DERIVE_COMMAND_LEVEL, + false); + if(isSql && errorCode.value==0){ + resultList.setValueTo(unwrapSqlAnswer(resultList,false)); + } + return true; + } + + /** 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 +865,9 @@ public int internCommand (String command) { starttime = System.currentTimeMillis(); // Executes the remote command. - Secondointerface.secondo(command, //Command to execute. - resultList, - errorCode, - errorPos, - errorMessage); + if(!sendCommandToServer(command,resultList,errorCode,errorPos,errorMessage)){ + return -1; + } if(tools.Environment.MEASURE_TIME){ Reporter.writeInfo("used time for query: "+(System.currentTimeMillis()-starttime)+" ms"); } @@ -1060,7 +888,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 +902,9 @@ public ListExpr getCommandResult (String command) { starttime = System.currentTimeMillis(); // Executes the remote command. - Secondointerface.secondo(command, //Command to execute. - resultList, - errorCode, errorPos, errorMessage); + if(!sendCommandToServer(command,resultList,errorCode,errorPos,errorMessage)){ + return null; + } if(tools.Environment.MEASURE_TIME){ Reporter.writeInfo("used time for query: "+(System.currentTimeMillis()-starttime)+" ms"); } @@ -1124,14 +952,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 +983,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 +1133,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 +1498,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..ead80ffb3e 100755 --- a/Javagui/secondoInterface/sj/lang/ESInterface.java +++ b/Javagui/secondoInterface/sj/lang/ESInterface.java @@ -147,7 +147,26 @@ public void secondo(String command, if(errorCode.value==81) terminate(); } - + + /** calls super.secondo with an explicit command level (2 = SQL dialect) + * 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){ + + super.secondo(command,resultList,errorCode,errorPos,errorMessage, + commandLevel,planOnly); + 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..024d19f4a0 100755 --- a/Javagui/secondoInterface/sj/lang/SecondoInterface.java +++ b/Javagui/secondoInterface/sj/lang/SecondoInterface.java @@ -614,32 +614,66 @@ private void callSaveCommand(String command, */ +/** command level to be derived from the command text itself */ +public static final int DERIVE_COMMAND_LEVEL = -1; + protected void secondo(String command, ListExpr resultList, IntByReference errorCode, IntByReference errorPos, StringBuffer errorMessage){ + secondo(command, resultList, errorCode, errorPos, errorMessage, + DERIVE_COMMAND_LEVEL, false); +} + +/** Sends a command at an explicitly given command level. + * The levels are 0 (nested list), 1 (SOS text) and 2 (SQL dialect: 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. + * 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){ // 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("(")?0:1; + } 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, commandType != 2). + if(commandLevel==2){ + sendCommand(command, commandLevel, planOnly, resultList, errorCode, + errorPos, errorMessage); + return; + } if(command.startsWith("restore ")){ callRestoreCommand(command, resultList, errorCode, errorPos, errorMessage); return; @@ -658,20 +692,35 @@ 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, 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, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage) throws IOException { + outSocketStream.write( "\n"); + outSocketStream.write( commandLevel + (planOnly?" planonly":"") + "\n" ); + outSocketStream.write(command); + outSocketStream.write("\n\n" ); + outSocketStream.flush(); + receiveResponse(resultList, errorCode, errorPos, errorMessage); +} + public boolean setHeartbeat(int heart1, int heart2){ try{ outSocketStream.write("\n"); @@ -1163,6 +1212,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); From b3cd12e6f64e51e7995c54ea24aef0e0e8945f14 Mon Sep 17 00:00:00 2001 From: Jan Nidzwetzki Date: Thu, 23 Jul 2026 23:18:51 +0200 Subject: [PATCH 3/4] Remove OptServer / JPL Since the SECONDO kernel is now able to drive the Optimizer directly, and the JavaGUI is using this code path, this commit cleans up the unneeded data and removes the custom SWI prolog build on OS X. --- .github/workflows/build.yml | 64 +- CM-Scripts/initdemo.sh | 28 - CM-Scripts/run-tests.sh | 6 +- CM-Scripts/secondo-detect.sh | 63 +- ClientServer/TestClientServer | 10 +- Documents/SecondoVM-FAQ.txt | 121 - Jpl/jsrc/10/jpl/Atom.java | 239 - Jpl/jsrc/10/jpl/Compound.java | 693 -- Jpl/jsrc/10/jpl/Float.java | 234 - Jpl/jsrc/10/jpl/Integer.java | 230 - Jpl/jsrc/10/jpl/JPL.java | 165 - Jpl/jsrc/10/jpl/JPLException.java | 70 - Jpl/jsrc/10/jpl/List.java | 502 -- Jpl/jsrc/10/jpl/Long.java | 236 - Jpl/jsrc/10/jpl/PrologException.java | 83 - Jpl/jsrc/10/jpl/Query.java | 1189 --- Jpl/jsrc/10/jpl/QueryInProgressException.java | 104 - Jpl/jsrc/10/jpl/String.java | 226 - Jpl/jsrc/10/jpl/Term.java | 469 -- Jpl/jsrc/10/jpl/Tuple.java | 534 -- Jpl/jsrc/10/jpl/Util.java | 297 - Jpl/jsrc/10/jpl/Variable.java | 233 - Jpl/jsrc/10/jpl/Version.java | 9 - Jpl/jsrc/10/jpl/fli/DoubleHolder.java | 60 - Jpl/jsrc/10/jpl/fli/IntHolder.java | 60 - Jpl/jsrc/10/jpl/fli/LongHolder.java | 60 - Jpl/jsrc/10/jpl/fli/PointerHolder.java | 63 - Jpl/jsrc/10/jpl/fli/Prolog.java | 249 - Jpl/jsrc/10/jpl/fli/StringHolder.java | 60 - Jpl/jsrc/10/jpl/fli/atom_t.java | 75 - Jpl/jsrc/10/jpl/fli/fid_t.java | 60 - Jpl/jsrc/10/jpl/fli/functor_t.java | 61 - Jpl/jsrc/10/jpl/fli/makefile | 37 - Jpl/jsrc/10/jpl/fli/module_t.java | 61 - Jpl/jsrc/10/jpl/fli/predicate_t.java | 61 - Jpl/jsrc/10/jpl/fli/qid_t.java | 60 - Jpl/jsrc/10/jpl/fli/term_t.java | 133 - Jpl/jsrc/10/jpl/makefile | 50 - Jpl/jsrc/10/makefile | 27 - Jpl/jsrc/30/jpl/Atom.java | 157 - Jpl/jsrc/30/jpl/Compound.java | 324 - Jpl/jsrc/30/jpl/Float.java | 295 - Jpl/jsrc/30/jpl/Integer.java | 269 - Jpl/jsrc/30/jpl/JBoolean.java | 217 - Jpl/jsrc/30/jpl/JPL.java | 199 - Jpl/jsrc/30/jpl/JPLException.java | 61 - Jpl/jsrc/30/jpl/JRef.java | 215 - Jpl/jsrc/30/jpl/JVoid.java | 185 - Jpl/jsrc/30/jpl/PrologException.java | 74 - Jpl/jsrc/30/jpl/Query.java | 791 -- Jpl/jsrc/30/jpl/Term.java | 671 -- Jpl/jsrc/30/jpl/Util.java | 172 - Jpl/jsrc/30/jpl/Variable.java | 301 - Jpl/jsrc/30/jpl/Version.java | 9 - Jpl/jsrc/30/jpl/fli/BooleanHolder.java | 60 - Jpl/jsrc/30/jpl/fli/DoubleHolder.java | 60 - Jpl/jsrc/30/jpl/fli/IntHolder.java | 60 - Jpl/jsrc/30/jpl/fli/LongHolder.java | 61 - Jpl/jsrc/30/jpl/fli/ObjectHolder.java | 60 - Jpl/jsrc/30/jpl/fli/PointerHolder.java | 63 - Jpl/jsrc/30/jpl/fli/Prolog.java | 240 - Jpl/jsrc/30/jpl/fli/StringHolder.java | 60 - Jpl/jsrc/30/jpl/fli/atom_t.java | 82 - Jpl/jsrc/30/jpl/fli/engine_t.java | 56 - Jpl/jsrc/30/jpl/fli/fid_t.java | 60 - Jpl/jsrc/30/jpl/fli/functor_t.java | 61 - Jpl/jsrc/30/jpl/fli/makefile | 37 - Jpl/jsrc/30/jpl/fli/module_t.java | 61 - Jpl/jsrc/30/jpl/fli/predicate_t.java | 61 - Jpl/jsrc/30/jpl/fli/qid_t.java | 60 - Jpl/jsrc/30/jpl/fli/term_t.java | 133 - Jpl/jsrc/30/jpl/makefile | 50 - Jpl/jsrc/30/makefile | 27 - Jpl/jsrc/makefile | 29 - Jpl/lib/classes/jpl/fli/makefile | 22 - Jpl/lib/classes/jpl/makefile | 23 - Jpl/lib/classes/makefile | 24 - Jpl/lib/makefile | 23 - Jpl/makefile | 39 - Jpl/readme.txt | 69 - Jpl/src/10/jpl.c | 1888 ----- Jpl/src/30/jpl.c | 6515 ----------------- Jpl/src/makefile | 83 - OptParser/OptTest/30/OptTest.java | 973 --- OptParser/OptTest/30/berlintest.tspec | 62 - OptParser/OptTest/30/dbopt.tspec | 22 - OptParser/OptTest/30/dmltest.tspec | 138 - OptParser/OptTest/30/makefile | 44 - OptParser/OptTest/30/optimize.tspec | 148 - OptParser/OptTest/30/optparse.tspec | 126 - OptParser/OptTest/30/sqltest.tspec | 155 - OptParser/OptTest/createBerlintest | 6 - OptParser/OptTest/createDMLTest | 6 - OptParser/OptTest/createOptParseTest | 6 - OptParser/OptTest/createOptimizerTest | 6 - OptParser/OptTest/createSQLTest | 12 - OptParser/OptTest/makefile | 87 - OptParser/OptTest/regSecondo.c | 37 - OptParser/OptTest/startOptTest | 15 - OptParser/OptTest/testDML | 5 - OptParser/OptTest/testOptParse | 5 - OptParser/OptTest/testOptimize | 5 - OptParser/OptTest/testSQL | 6 - OptParser/makefile | 2 - OptServer/10/NamedVariable.java | 80 - OptServer/10/OptimizerServer.java | 696 -- OptServer/10/PrologParser.java | 361 - OptServer/10/makefile | 58 - OptServer/30/OptimizerServer.java | 937 --- OptServer/30/makefile | 44 - OptServer/70/OptimizerServer.java | 925 --- OptServer/70/makefile | 44 - OptServer/82/OptimizerServer.java | 925 --- OptServer/82/makefile | 44 - OptServer/makefile | 97 - OptServer/regSecondo.c | 20 - Optimizer/StartOptServer | 169 - Optimizer/TestOptServer | 149 - README.md | 8 +- UserInterfaces/MainTTY.cpp | 184 +- UserInterfaces/SecondoPL.cpp | 6 +- UserInterfaces/makefile | 11 +- WebUI/README.md | 7 +- bin/TotalTest | 15 +- bin/startSession | 5 - makefile | 35 +- makefile.optimizer | 52 +- packaging/debian/debian/rules | 2 +- packaging/debian/test-deb.sh | 8 +- packaging/debian/tools/secondo-optimizer | 2 +- 130 files changed, 145 insertions(+), 27594 deletions(-) delete mode 100644 CM-Scripts/initdemo.sh delete mode 100644 Documents/SecondoVM-FAQ.txt delete mode 100755 Jpl/jsrc/10/jpl/Atom.java delete mode 100755 Jpl/jsrc/10/jpl/Compound.java delete mode 100755 Jpl/jsrc/10/jpl/Float.java delete mode 100755 Jpl/jsrc/10/jpl/Integer.java delete mode 100755 Jpl/jsrc/10/jpl/JPL.java delete mode 100755 Jpl/jsrc/10/jpl/JPLException.java delete mode 100755 Jpl/jsrc/10/jpl/List.java delete mode 100755 Jpl/jsrc/10/jpl/Long.java delete mode 100755 Jpl/jsrc/10/jpl/PrologException.java delete mode 100755 Jpl/jsrc/10/jpl/Query.java delete mode 100755 Jpl/jsrc/10/jpl/QueryInProgressException.java delete mode 100755 Jpl/jsrc/10/jpl/String.java delete mode 100755 Jpl/jsrc/10/jpl/Term.java delete mode 100755 Jpl/jsrc/10/jpl/Tuple.java delete mode 100755 Jpl/jsrc/10/jpl/Util.java delete mode 100755 Jpl/jsrc/10/jpl/Variable.java delete mode 100755 Jpl/jsrc/10/jpl/Version.java delete mode 100755 Jpl/jsrc/10/jpl/fli/DoubleHolder.java delete mode 100755 Jpl/jsrc/10/jpl/fli/IntHolder.java delete mode 100755 Jpl/jsrc/10/jpl/fli/LongHolder.java delete mode 100755 Jpl/jsrc/10/jpl/fli/PointerHolder.java delete mode 100755 Jpl/jsrc/10/jpl/fli/Prolog.java delete mode 100755 Jpl/jsrc/10/jpl/fli/StringHolder.java delete mode 100755 Jpl/jsrc/10/jpl/fli/atom_t.java delete mode 100755 Jpl/jsrc/10/jpl/fli/fid_t.java delete mode 100755 Jpl/jsrc/10/jpl/fli/functor_t.java delete mode 100755 Jpl/jsrc/10/jpl/fli/makefile delete mode 100755 Jpl/jsrc/10/jpl/fli/module_t.java delete mode 100755 Jpl/jsrc/10/jpl/fli/predicate_t.java delete mode 100755 Jpl/jsrc/10/jpl/fli/qid_t.java delete mode 100755 Jpl/jsrc/10/jpl/fli/term_t.java delete mode 100755 Jpl/jsrc/10/jpl/makefile delete mode 100755 Jpl/jsrc/10/makefile delete mode 100644 Jpl/jsrc/30/jpl/Atom.java delete mode 100644 Jpl/jsrc/30/jpl/Compound.java delete mode 100644 Jpl/jsrc/30/jpl/Float.java delete mode 100644 Jpl/jsrc/30/jpl/Integer.java delete mode 100644 Jpl/jsrc/30/jpl/JBoolean.java delete mode 100644 Jpl/jsrc/30/jpl/JPL.java delete mode 100644 Jpl/jsrc/30/jpl/JPLException.java delete mode 100644 Jpl/jsrc/30/jpl/JRef.java delete mode 100644 Jpl/jsrc/30/jpl/JVoid.java delete mode 100644 Jpl/jsrc/30/jpl/PrologException.java delete mode 100644 Jpl/jsrc/30/jpl/Query.java delete mode 100644 Jpl/jsrc/30/jpl/Term.java delete mode 100644 Jpl/jsrc/30/jpl/Util.java delete mode 100644 Jpl/jsrc/30/jpl/Variable.java delete mode 100644 Jpl/jsrc/30/jpl/Version.java delete mode 100644 Jpl/jsrc/30/jpl/fli/BooleanHolder.java delete mode 100644 Jpl/jsrc/30/jpl/fli/DoubleHolder.java delete mode 100644 Jpl/jsrc/30/jpl/fli/IntHolder.java delete mode 100644 Jpl/jsrc/30/jpl/fli/LongHolder.java delete mode 100644 Jpl/jsrc/30/jpl/fli/ObjectHolder.java delete mode 100644 Jpl/jsrc/30/jpl/fli/PointerHolder.java delete mode 100644 Jpl/jsrc/30/jpl/fli/Prolog.java delete mode 100644 Jpl/jsrc/30/jpl/fli/StringHolder.java delete mode 100644 Jpl/jsrc/30/jpl/fli/atom_t.java delete mode 100644 Jpl/jsrc/30/jpl/fli/engine_t.java delete mode 100644 Jpl/jsrc/30/jpl/fli/fid_t.java delete mode 100644 Jpl/jsrc/30/jpl/fli/functor_t.java delete mode 100755 Jpl/jsrc/30/jpl/fli/makefile delete mode 100644 Jpl/jsrc/30/jpl/fli/module_t.java delete mode 100644 Jpl/jsrc/30/jpl/fli/predicate_t.java delete mode 100644 Jpl/jsrc/30/jpl/fli/qid_t.java delete mode 100644 Jpl/jsrc/30/jpl/fli/term_t.java delete mode 100755 Jpl/jsrc/30/jpl/makefile delete mode 100755 Jpl/jsrc/30/makefile delete mode 100755 Jpl/jsrc/makefile delete mode 100755 Jpl/lib/classes/jpl/fli/makefile delete mode 100755 Jpl/lib/classes/jpl/makefile delete mode 100755 Jpl/lib/classes/makefile delete mode 100755 Jpl/lib/makefile delete mode 100755 Jpl/makefile delete mode 100755 Jpl/readme.txt delete mode 100755 Jpl/src/10/jpl.c delete mode 100644 Jpl/src/30/jpl.c delete mode 100755 Jpl/src/makefile delete mode 100755 OptParser/OptTest/30/OptTest.java delete mode 100644 OptParser/OptTest/30/berlintest.tspec delete mode 100644 OptParser/OptTest/30/dbopt.tspec delete mode 100644 OptParser/OptTest/30/dmltest.tspec delete mode 100755 OptParser/OptTest/30/makefile delete mode 100644 OptParser/OptTest/30/optimize.tspec delete mode 100644 OptParser/OptTest/30/optparse.tspec delete mode 100644 OptParser/OptTest/30/sqltest.tspec delete mode 100755 OptParser/OptTest/createBerlintest delete mode 100755 OptParser/OptTest/createDMLTest delete mode 100755 OptParser/OptTest/createOptParseTest delete mode 100755 OptParser/OptTest/createOptimizerTest delete mode 100755 OptParser/OptTest/createSQLTest delete mode 100644 OptParser/OptTest/makefile delete mode 100644 OptParser/OptTest/regSecondo.c delete mode 100755 OptParser/OptTest/startOptTest delete mode 100755 OptParser/OptTest/testDML delete mode 100755 OptParser/OptTest/testOptParse delete mode 100755 OptParser/OptTest/testOptimize delete mode 100755 OptParser/OptTest/testSQL delete mode 100644 OptServer/10/NamedVariable.java delete mode 100755 OptServer/10/OptimizerServer.java delete mode 100644 OptServer/10/PrologParser.java delete mode 100755 OptServer/10/makefile delete mode 100755 OptServer/30/OptimizerServer.java delete mode 100755 OptServer/30/makefile delete mode 100755 OptServer/70/OptimizerServer.java delete mode 100755 OptServer/70/makefile delete mode 100755 OptServer/82/OptimizerServer.java delete mode 100755 OptServer/82/makefile delete mode 100755 OptServer/makefile delete mode 100644 OptServer/regSecondo.c delete mode 100755 Optimizer/StartOptServer delete mode 100755 Optimizer/TestOptServer 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/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/TestClientServer b/ClientServer/TestClientServer index 2ad89f9fd1..50f96a5106 100755 --- a/ClientServer/TestClientServer +++ b/ClientServer/TestClientServer @@ -15,8 +15,8 @@ # 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 @@ -34,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 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/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/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 825cd2cc05..0000000000 --- a/OptServer/makefile +++ /dev/null @@ -1,97 +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) $< - -$(SECONDOPL_DIR)/SecondoPLCS.o: - $(MAKE) -C $(SECONDOPL_DIR) SecondoPLCS.o - -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/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/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 6f59341e2d..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,90 +55,90 @@ 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 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); + // 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 @@ -147,22 +147,22 @@ main( const int argc, char* argv[] ) // 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); + if (tp.isPLMode()) + return SecondoPLMode(tp); #endif - 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) { + 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) { cerr << e.what() << endl; } } diff --git a/UserInterfaces/SecondoPL.cpp b/UserInterfaces/SecondoPL.cpp index 6ce8004ef7..ab1bba1b92 100755 --- a/UserInterfaces/SecondoPL.cpp +++ b/UserInterfaces/SecondoPL.cpp @@ -1522,9 +1522,9 @@ bool embeddedOptimizerUseDatabase(const string& dbName) { } // 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) exactly as the OptServer does: close - // the currently open database, then reopen it through the optimizer. The - // database ends up open again, transparently to the client. + // 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); diff --git a/UserInterfaces/makefile b/UserInterfaces/makefile index da95d1e4a0..e8582c8227 100755 --- a/UserInterfaces/makefile +++ b/UserInterfaces/makefile @@ -117,7 +117,7 @@ entropy: .PHONY: clean clean: - $(RM) *.dep $(APPLOBJECTS) $(APPLICATIONS) $(ENTROPY_OBJ) $(DEP_FILES) $(CS_OBJECTS) SecondoPLCS.$(OBJEXT) + $(RM) *.dep $(APPLOBJECTS) $(APPLICATIONS) $(ENTROPY_OBJ) $(DEP_FILES) $(CS_OBJECTS) $(MAKE) -C InteractiveQueryEditor clean # @@ -134,15 +134,6 @@ SecondoPL.$(OBJEXT): $(ENTROPY_OBJ) %.$(OBJEXT): %.cpp $(CC) -c -o $@ $< $(CCFLAGS) $(JNIINCLUDE) $(CPPSTDOPTION) -# SecondoPLCS.o is SecondoPL compiled in client/server mode (SecondoInterfaceCS -# instead of SecondoInterfaceTTY). No TTY client embeds the optimizer anymore, -# so it is not part of this directory's own build; the sole consumer is the -# external Java OptServer's JNI bridge, which builds it on demand via this rule -# (see OptServer/makefile). The rule lives here because the source and the -# correct compile flags do. -SecondoPLCS.$(OBJEXT): SecondoPL.cpp - $(CC) -c -DSECONDO_CLIENT_SERVER -o $@ $< $(CCFLAGS) $(CPPSTDOPTION) - SecondoTTYCS.$(OBJEXT): SecondoTTY.cpp $(CC) -c -DSECONDO_CLIENT_SERVER -o $@ $< $(CCFLAGS) $(CPPSTDOPTION) 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/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.optimizer b/makefile.optimizer index 9386599971..4429947ef6 100755 --- a/makefile.optimizer +++ b/makefile.optimizer @@ -53,10 +53,9 @@ endif ifeq ($(optimizer),"true") # When the optimizer is compiled in, the default build must also generate the # concatenated optimizer program (Optimizer/optimizer). It is consulted at -# runtime -- not only by the OptServer, but now also by the kernel server and -# the TTY, which embed the optimizer to run the SQL dialect. optimizer2 builds -# it; optserver builds JPL and the (still optional) Java OptServer. -OPTIMIZER_SERVER := optimizer2 optserver +# 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 @@ -77,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 @@ -102,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/debian/rules b/packaging/debian/debian/rules index 44af28ab71..0639e7b173 100755 --- a/packaging/debian/debian/rules +++ b/packaging/debian/debian/rules @@ -35,7 +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 SecondoPLNT StartOptServer +OPTIMIZER_TOOLS := SecondoPL SecondoPLNT %: dh $@ diff --git a/packaging/debian/test-deb.sh b/packaging/debian/test-deb.sh index f2ce4c27ed..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. @@ -81,8 +80,7 @@ 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 "SecondoTTYBDB: select count(*) from ten (embedded optimizer)" "10" "$(result PLTTY_COUNT)" diff --git a/packaging/debian/tools/secondo-optimizer b/packaging/debian/tools/secondo-optimizer index 4231548583..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, -# SecondoPLNT, 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. From e25a39046f0c4da63634ccb8e9b459c0a2d55b3e Mon Sep 17 00:00:00 2001 From: Jan Nidzwetzki Date: Fri, 24 Jul 2026 17:37:12 +0200 Subject: [PATCH 4/4] Kernel: Implement language level auto detection. So far, the client had to determine which language level should be used. This leads to different language detection implementations in C and Java. This commit introduces server-side auto-detection and unifies the existing approaches in one central place. --- ClientServer/SecondoInterfaceCS.cpp | 102 ++++- ClientServer/SecondoInterfaceREPLAY.cpp | 15 +- ClientServer/SecondoServer.cpp | 107 +++++- ClientServer/TestClientServer | 84 +++++ .../communication/CommunicationInterface.java | 8 +- Javagui/gui/CommandPanel.java | 349 ++++-------------- .../secondoInterface/sj/lang/ESInterface.java | 26 +- .../sj/lang/SecondoInterface.java | 115 +++++- OptParser/OptSecUtils.cpp | 19 +- Optimizer/TestSecondoPLStartup | 96 ++++- QueryProcessor/SecondoInterfaceTTY.cpp | 5 +- UserInterfaces/SQLLanguage.cpp | 180 +++++++++ UserInterfaces/SecondoPL.cpp | 5 +- UserInterfaces/SecondoTTY.cpp | 249 ++++--------- UserInterfaces/TestRunner.cpp | 5 +- UserInterfaces/makefile | 3 +- include/CSProtocol.h | 34 +- include/SQLLanguage.h | 121 ++++++ include/SecondoInterface.h | 23 +- include/SecondoInterfaceCS.h | 32 +- makefile.libs | 3 +- 21 files changed, 1038 insertions(+), 543 deletions(-) create mode 100644 UserInterfaces/SQLLanguage.cpp create mode 100644 include/SQLLanguage.h diff --git a/ClientServer/SecondoInterfaceCS.cpp b/ClientServer/SecondoInterfaceCS.cpp index b91a6aba4b..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; @@ -91,6 +92,8 @@ SecondoInterfaceCS::SecondoInterfaceCS(bool isServer, /*= false*/ pswd = ""; multiUser = false; sqlPlanOnly = false; + sqlOptimizerAddressed = false; + resolvedCmdLevel = CMD_LEVEL_TEXT; traceSocketIn = 0; traceSocketOut = 0; } @@ -487,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 ) @@ -509,19 +512,26 @@ 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 2: // SQL dialect: forwarded verbatim to the server's optimizer + 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, @@ -560,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 " ); @@ -568,13 +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 ( commandType != 2 && + 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 + ")"; } @@ -648,7 +668,7 @@ For an explanation of the error codes refer to SecondoInterface.h errorCode = ERR_SYNTAX_ERROR; } } - else if ( commandType != 2 && + else if ( specialCmdLevel != CMD_LEVEL_SQL && posSave != string::npos && // save object to filename posTo != string::npos && posDatabase == string::npos && @@ -657,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 + ")"; } @@ -736,14 +756,14 @@ For an explanation of the error codes refer to SecondoInterface.h } } - else if ( commandType != 2 && + 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 + ")"; } @@ -813,7 +833,7 @@ For an explanation of the error codes refer to SecondoInterface.h } } - else if ( commandType != 2 && + else if ( specialCmdLevel != CMD_LEVEL_SQL && posDatabase != string::npos && posRestore != string::npos && posFrom != string::npos && @@ -821,7 +841,7 @@ For an explanation of the error codes refer to SecondoInterface.h { dwriter.write(debugSecondoMethod, cout, this, pid, "check for restore db"); - if ( commandType == 1 ) + if ( specialCmdLevel == CMD_LEVEL_TEXT ) { cmdText = string( "(" ) + commandText + ")"; } @@ -906,14 +926,31 @@ For an explanation of the error codes refer to SecondoInterface.h // 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" : "") << endl; + 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, @@ -1269,6 +1306,41 @@ bool SecondoInterfaceCS::optimizerAvailable(){ 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, @@ -1279,7 +1351,7 @@ void SecondoInterfaceCS::SecondoSql(const std::string& sql, // into an unrelated command. ListExpr cmdList = nl->TheEmptyList(); sqlPlanOnly = planOnly; - Secondo( sql, cmdList, 2, false, false, + Secondo( sql, cmdList, CMD_LEVEL_SQL, false, false, resultList, errorCode, errorPos, errorMessage ); sqlPlanOnly = false; } 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/SecondoServer.cpp b/ClientServer/SecondoServer.cpp index e76565ab53..143b10b0fd 100755 --- a/ClientServer/SecondoServer.cpp +++ b/ClientServer/SecondoServer.cpp @@ -72,6 +72,7 @@ are implemented in class ~CSProtocol~ and can be used by inside the #include "NList.h" #include "satof.h" #include "ErrorCodes.h" +#include "SQLLanguage.h" #ifndef NO_OPTIMIZER #include "SecondoPL.h" @@ -166,6 +167,13 @@ class SecondoServer : public Application // 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 @@ -233,11 +241,14 @@ SecondoServer::CallSecondo() // 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. + // 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 @@ -252,16 +263,46 @@ SecondoServer::CallSecondo() } while (!ready && !iosock.fail()); - // Command level 2 is the SQL dialect: it is not an executable command, so it + // 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 == 2 ) + 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; @@ -333,8 +374,8 @@ SecondoServer::CallSql(const string& sqlText, bool executePlan) string errorMessage=""; if ( executePlan && !alreadyExecuted ) { - // Execute the generated executable plan (command level 1, text syntax). - si->Secondo( plan, commandLE, 1, true, false, + // Execute the generated executable plan (text syntax). + si->Secondo( plan, commandLE, CMD_LEVEL_TEXT, true, false, planResult, errorCode, errorPos, errorMessage ); NList::setNLRef(nl); } @@ -403,6 +444,58 @@ SecondoServer::ensureOptimizerReady(string& errMsg, bool requireDb) } #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() { @@ -1013,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); @@ -1083,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); } diff --git a/ClientServer/TestClientServer b/ClientServer/TestClientServer index 50f96a5106..0f4baa860f 100755 --- a/ClientServer/TestClientServer +++ b/ClientServer/TestClientServer @@ -508,6 +508,90 @@ SQL 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: diff --git a/Javagui/JDBC/communication/CommunicationInterface.java b/Javagui/JDBC/communication/CommunicationInterface.java index 90f0f488d1..db460afd55 100644 --- a/Javagui/JDBC/communication/CommunicationInterface.java +++ b/Javagui/JDBC/communication/CommunicationInterface.java @@ -4,6 +4,7 @@ import tools.Reporter; //import Verbindungstest.Declarations; import sj.lang.ESInterface; +import sj.lang.SecondoInterface; import sj.lang.ListExpr; import sj.lang.IntByReference; /** @@ -206,15 +207,16 @@ public boolean executeCommand(String command) { /** * Task of this method
    * Sends an SQL command to the Secondo server, which optimizes it itself - * (command level 2) and answers with the list (plan result costs). - * @param command the command in the SQL dialect + * 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, 2, planOnly); + SI.secondo(command, answer, ErrCode, ErrPos, ErrMess, + SecondoInterface.SQL_COMMAND_LEVEL, planOnly); if (ErrCode.value != 0) { Reporter.writeError(ErrMess.toString()); return null; diff --git a/Javagui/gui/CommandPanel.java b/Javagui/gui/CommandPanel.java index c2fca95a0d..1cff6f22bc 100755 --- a/Javagui/gui/CommandPanel.java +++ b/Javagui/gui/CommandPanel.java @@ -306,191 +306,6 @@ 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'); - } - - - - - private char toLower(char c){ - if(c>='A' && c<='Z'){ - return (char)(c - 'A' + 'a'); - } - 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 = select|union|intersection ...": an SQL right hand side. - // The server splits the prefix off and re-wraps the generated plan. - if(t[0].equals("let") && ( t[2].equals("select") || t[2].equals("union") - || t[2].equals("intersection"))){ - return true; - } - return false; - } - - /** 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 @@ -530,27 +345,38 @@ private ListExpr unwrapSqlAnswer(ListExpr answer, boolean planOnly){ } - /** Checks the preconditions for sending an SQL command and reports the - * reason it cannot be sent. Returns true if it may be sent. + /** 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 boolean canSendSql(String command){ - if(!useOptimizer()){ - appendText("\noptimizer not available"); - showPrompt(); - return false; - } - if(OpenedDatabase.length()==0){ - appendText("\nno database open"); - showPrompt(); - return false; + private int commandLevel(){ + return useOptimizer() ? SecondoInterface.AUTO_COMMAND_LEVEL + : SecondoInterface.DERIVE_COMMAND_LEVEL; + } + + + /** Turns the answer of the command just sent into the list to be rendered, + * according to the level the server resolved that command to. An SQL answer + * is the triple (plan result costs), an optimizer directive answers with the + * text it printed, and an ordinary command answers with its result. + */ + private ListExpr unwrapAnswer(ListExpr answer, boolean optimizerAddressed){ + int level = Secondointerface.getResolvedCommandLevel(); + if(level==SecondoInterface.SQL_COMMAND_LEVEL){ + // The "optimizer " prefix means plan only: the server stopped after + // optimizing, so there is no result half to render. + return unwrapSqlAnswer(answer,optimizerAddressed); } - StringBuffer buf = new StringBuffer(); - if(!checkBrackets(command,buf)){ - appendText("\n\n"+buf.toString()); - showPrompt(); - return false; + if(level==SecondoInterface.OPT_DIRECTIVE_COMMAND_LEVEL){ + appendText("\n"+(answer.atomType()==ListExpr.TEXT_ATOM + ? answer.textValue() : answer.toString())); + return ListExpr.theEmptyList(); } - return true; + return answer; } @@ -623,8 +449,9 @@ public boolean execUserCommand (String command, } - // A command addressed to the optimizer explicitly. What follows the - // prefix decides what it means, exactly as in the TTY clients: + // 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)){ @@ -637,39 +464,9 @@ public boolean execUserCommand (String command, return !success; } } - String optCommand = command.substring(OptString.length()).trim(); - - if(isSqlCommand(optCommand)){ - return execServerCommand(optCommand,true,isTest,success,epsilon, - isAbsolute,expectedResult); - } - - long starttime=0; - if(tools.Environment.MEASURE_TIME) - starttime = System.currentTimeMillis(); - - String answer = sendToOptimizer(optCommand); - - 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 { - appendText("\n"+answer); - showPrompt(); - if(!isTest){ - return true; - }else{ - return success; - } - } + return execServerCommand(command.substring(OptString.length()).trim(), + true,isTest,success,epsilon,isAbsolute, + expectedResult); } return execServerCommand(command,false,isTest,success,epsilon,isAbsolute, @@ -678,13 +475,15 @@ public boolean execUserCommand (String command, /** Sends one command to the connected server and processes its result. - * An SQL command (auto detected) is optimized by the server at command - * level 2; anything else is sent unchanged at level 0/1. With planOnly the - * server stops after optimizing, so the plan is reported and nothing runs. + * 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 planOnly, + boolean optimizerAddressed, boolean isTest, boolean success, double epsilon, @@ -702,17 +501,6 @@ private boolean execServerCommand (String command, // Executes the remote command. if(Secondointerface.isInitialized()){ - int commandLevel = SecondoInterface.DERIVE_COMMAND_LEVEL; - if(isSqlCommand(command)){ - if(!canSendSql(command)){ - if(!isTest){ - return false; - } else{ - return !success; - } - } - commandLevel = 2; // SQL dialect: the server optimizes it - } appendText("\n" + command + "..."); long starttime=0; if(tools.Environment.MEASURE_TIME){ @@ -724,12 +512,13 @@ private boolean execServerCommand (String command, errorCode, errorPos, errorMessage, - commandLevel, - planOnly); + commandLevel(), + false, + optimizerAddressed); - if(commandLevel==2 && errorCode.value==0){ - // the answer is (plan result costs); render the result half - resultList.setValueTo(unwrapSqlAnswer(resultList,planOnly)); + if(errorCode.value==0){ + resultList.setValueTo( + unwrapAnswer(resultList,optimizerAddressed)); } if(tools.Environment.MEASURE_TIME){ @@ -814,36 +603,26 @@ public boolean execCommand(String cmd, IntByReference errorCode, ListExpr result return false; } IntByReference errorPos=new IntByReference(); - if(!sendCommandToServer(cmd,resultList,errorCode,errorPos,errorMessage)){ - return false; - } + sendCommandToServer(cmd,resultList,errorCode,errorPos,errorMessage); return errorCode.value==0; } - /** Sends a command to the server at the level it belongs to: an SQL command - * (auto detected) is optimized by the server at command level 2, anything - * else is sent unchanged. A level 2 answer is unwrapped to its result half, - * so the caller sees the same shape as for a kernel command. - * Returns false when an SQL command could not be sent at all; the reason - * has then been written to the panel. + /** 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 boolean sendCommandToServer(String command, - ListExpr resultList, - IntByReference errorCode, - IntByReference errorPos, - StringBuffer errorMessage){ - boolean isSql = isSqlCommand(command); - if(isSql && !canSendSql(command)){ - return false; - } + private void sendCommandToServer(String command, + ListExpr resultList, + IntByReference errorCode, + IntByReference errorPos, + StringBuffer errorMessage){ Secondointerface.secondo(command,resultList,errorCode,errorPos,errorMessage, - isSql?2:SecondoInterface.DERIVE_COMMAND_LEVEL, - false); - if(isSql && errorCode.value==0){ - resultList.setValueTo(unwrapSqlAnswer(resultList,false)); + commandLevel(), false); + if(errorCode.value==0){ + resultList.setValueTo(unwrapAnswer(resultList,false)); } - return true; } @@ -865,9 +644,7 @@ public int internCommand (String command) { starttime = System.currentTimeMillis(); // Executes the remote command. - if(!sendCommandToServer(command,resultList,errorCode,errorPos,errorMessage)){ - return -1; - } + sendCommandToServer(command,resultList,errorCode,errorPos,errorMessage); if(tools.Environment.MEASURE_TIME){ Reporter.writeInfo("used time for query: "+(System.currentTimeMillis()-starttime)+" ms"); } @@ -902,9 +679,7 @@ public ListExpr getCommandResult (String command) { starttime = System.currentTimeMillis(); // Executes the remote command. - if(!sendCommandToServer(command,resultList,errorCode,errorPos,errorMessage)){ - return null; - } + sendCommandToServer(command,resultList,errorCode,errorPos,errorMessage); if(tools.Environment.MEASURE_TIME){ Reporter.writeInfo("used time for query: "+(System.currentTimeMillis()-starttime)+" ms"); } diff --git a/Javagui/secondoInterface/sj/lang/ESInterface.java b/Javagui/secondoInterface/sj/lang/ESInterface.java index ead80ffb3e..6aba1f1648 100755 --- a/Javagui/secondoInterface/sj/lang/ESInterface.java +++ b/Javagui/secondoInterface/sj/lang/ESInterface.java @@ -148,9 +148,10 @@ public void secondo(String command, terminate(); } - /** calls super.secondo with an explicit command level (2 = SQL dialect) - * and the optional "planonly" protocol flag; behaves like the five - * argument version on a lost connection + /** 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, @@ -160,8 +161,25 @@ public void secondo(String command, 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); + commandLevel,planOnly,optimizerAddressed); if(errorCode.value==81) terminate(); } diff --git a/Javagui/secondoInterface/sj/lang/SecondoInterface.java b/Javagui/secondoInterface/sj/lang/SecondoInterface.java index 024d19f4a0..57330c9bad 100755 --- a/Javagui/secondoInterface/sj/lang/SecondoInterface.java +++ b/Javagui/secondoInterface/sj/lang/SecondoInterface.java @@ -614,8 +614,28 @@ private void callSaveCommand(String command, */ -/** command level to be derived from the command text itself */ -public static final int DERIVE_COMMAND_LEVEL = -1; +/* 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, @@ -626,11 +646,23 @@ protected void secondo(String command, 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 dialect: the - * server optimizes the command itself and answers with the list + * 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. + * 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. @@ -642,6 +674,24 @@ protected void secondo(String command, 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){ @@ -663,15 +713,19 @@ protected void secondo(String command, // check for restore command command=command.trim(); if(commandLevel==DERIVE_COMMAND_LEVEL){ - commandLevel = command.startsWith("(")?0:1; + 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, commandType != 2). - if(commandLevel==2){ - sendCommand(command, commandLevel, planOnly, resultList, errorCode, - errorPos, errorMessage); + // 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 ")){ @@ -693,8 +747,8 @@ protected void secondo(String command, } // not a special command - sendCommand(command, commandLevel, planOnly, resultList, errorCode, - errorPos, errorMessage); + sendCommand(command, commandLevel, planOnly, optimizerAddressed, + resultList, errorCode, errorPos, errorMessage); } catch(IOException e){ errorCode.value=81; return; @@ -709,18 +763,53 @@ protected void secondo(String command, 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":"") + "\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"); 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/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/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/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 ab1bba1b92..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; diff --git a/UserInterfaces/SecondoTTY.cpp b/UserInterfaces/SecondoTTY.cpp index 01f61af3ab..0982777d81 100755 --- a/UserInterfaces/SecondoTTY.cpp +++ b/UserInterfaces/SecondoTTY.cpp @@ -104,8 +104,9 @@ then you will be prompted for the filename. #include "NestedList.h" #include "DisplayTTY.h" #include "ErrorCodes.h" +#include "SQLLanguage.h" -// The embedded build optimizes the SQL dialect in-process via these helpers. +// The embedded build optimizes SQL in-process via these helpers. #ifndef NO_OPTIMIZER #include "SecondoPL.h" #endif @@ -556,77 +557,22 @@ SecondoTTY::ShowQueryResult( ListExpr list ) /* -10.1 Recognizing the SQL dialect +10.1 Reporting what the optimizer did -Deciding whether a typed command belongs to the optimizer or to the kernel 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). The rule -set below is the one the retired hybrid TTY (~SecondoPLTTYMode::isSqlCommand~) -and the JavaGUI (~CommandPanel.optimize~) independently arrived at. +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. -Anything not recognized here falls through to the kernel -- the fallback is -always the kernel, in every client. +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) -// Split cmd into at most maxTok lower-cased tokens. The delimiter set matches -// the JavaGUI's classifier, so that "let r5=select ..." and "create table t(a)" -// tokenize identically there and here. -static void sqlTokens(const std::string& cmd, std::vector& toks, - size_t maxTok) -{ - const string delims = " \t\n\r\f\v\b\a([{=.,;"; - 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; - } -} - -static bool looksLikeSql(const std::string& cmd) -{ - size_t s = cmd.find_first_not_of(" \t\n\r\f\v\b\a"); - if ( s == string::npos ) return false; - // nested list command or command sequence: always the kernel - if ( cmd[s] == '(' || cmd[s] == '{' ) return false; - - std::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" || t[0] == "drop" ) 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; - if ( t[0] == "create" && (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; -} - /* 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 @@ -652,58 +598,6 @@ static void showPlanOnlyNote(bool planOnly) cout << color(blue) << "Plan only -- not executed." << color(normal) << endl; } -/* -Strip a leading ~optimizer~ keyword (the prefix the JavaGUI uses to address the -optimizer directly). Returns true and puts the remainder into ~rest~ if the -prefix was there; otherwise returns false and leaves ~rest~ = ~cmd~. - -*/ -static bool stripOptimizerPrefix(const std::string& cmd, std::string& rest) -{ - rest = cmd; - size_t s = cmd.find_first_not_of(" \t\n\r\f\v\b\a"); - 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(" \t\n\r\f\v\b\a", after); - if ( r == string::npos ) return false; - - rest = cmd.substr(r); - return true; -} - -// The optimizer control directives the TTY routes to the directive channel -// when they are typed bare. With an explicit "optimizer " prefix any non-SQL -// text is treated as a directive, so this list is only the convenience case. -static bool isBareOptimizerDirective(const std::string& cmd) -{ - size_t s = cmd.find_first_not_of(" \n\r\t\v\b\a\f"); - if ( s == string::npos ) return false; - size_t nameEnd = cmd.find_first_of(" \n\r\t\v\b\a\f(", 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; -} - #endif /* @@ -723,8 +617,6 @@ SecondoTTY::CallSecondo() string errorMessage = ""; string errorText = ""; - size_t cmdStart = 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 @@ -735,55 +627,27 @@ SecondoTTY::CallSecondo() // 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 = false; -#if defined(SECONDO_CLIENT_SERVER) || !defined(NO_OPTIMIZER) - optPrefix = stripOptimizerPrefix( cmd, optCmd ); -#endif - - // Detect a leading "sql" or "select" token: the SQL dialect. Both forms are - // accepted (the "sql" prefix is optional), case insensitively. In the - // client/server build it is sent to the server (command level 2, or level 3 - // when only the plan is wanted) and optimized there; in the embedded build it - // is optimized in-process. The detection is only active where an optimizer is - // reachable. - bool isSql = false; -#if defined(SECONDO_CLIENT_SERVER) || !defined(NO_OPTIMIZER) - isSql = looksLikeSql( optCmd ); -#endif + bool optPrefix = stripOptimizerPrefix( cmd, optCmd ); - // "optimizer ": stop after optimizing and report the plan. - bool planOnly = optPrefix && isSql; +#ifdef SECONDO_CLIENT_SERVER - // Detect an optimizer control directive (setOption(X), delOption(X), - // showOptions, updateCatalog, ...). Like the SQL detection above this is only - // active where an optimizer is reachable, and it is routed to the optimizer's - // directive channel below (over the network in SecondoCS, in-process in the - // standalone SecondoBDB). - // - // Bare, the known directive names are recognized. After an explicit - // "optimizer " prefix anything that is not SQL is a directive, so arbitrary - // optimizer goals can be run -- which is what the prefix does in the JavaGUI. - bool isOptDirective = false; -#if defined(SECONDO_CLIENT_SERVER) || !defined(NO_OPTIMIZER) - if ( !isSql && cmdStart != string::npos ) - { - isOptDirective = optPrefix ? true : isBareOptimizerDirective( cmd ); - } -#endif + // 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 ( isSql ) + if ( errorCode == 0 && level == CMD_LEVEL_SQL ) { -#ifdef SECONDO_CLIENT_SERVER - // Client/server: send the SQL to the server, which optimizes it and - // returns the list (optimizedPlan result costs). With planOnly ("optimizer - // ") the server stops after optimizing and the result half comes back - // empty. - ((SecondoInterfaceCS*) si)->SecondoSql( optCmd, planOnly, outList, - errorCode, errorPos, errorMessage ); - NList::setNLRef(nl); + // 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 ( errorCode == 0 && nl->ListLength( outList ) >= 2 ) + if ( nl->ListLength( outList ) >= 2 ) { string planStr = ""; if ( nl->AtomType( nl->First( outList )) == TextType ) @@ -807,13 +671,49 @@ SecondoTTY::CallSecondo() { showCosts( nl->RealValue( nl->Third( outList )) ); } - showPlanOnlyNote( planOnly ); + showPlanOnlyNote( optPrefix ); } outList = nl->Second( outList ); } -#elif !defined(NO_OPTIMIZER) - // Embedded: run the optimizer in-process to turn the SQL into an - // executable plan, then execute the plan. + } + 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; @@ -846,7 +746,7 @@ SecondoTTY::CallSecondo() showPlanOnlyNote( planOnly ); if ( !planOnly ) { - si->Secondo( plan, cmdList, 1, false, false, + si->Secondo( plan, cmdList, CMD_LEVEL_TEXT, false, false, outList, errorCode, errorPos, errorMessage ); NList::setNLRef(nl); } @@ -876,13 +776,8 @@ SecondoTTY::CallSecondo() } else if ( isOptDirective ) { -#ifdef SECONDO_CLIENT_SERVER - // Client/server (SecondoCS): run the directive on the server's embedded - // optimizer via the channel and print what it wrote. - string out = ((SecondoInterfaceCS*)si)->optimizerCommand( optCmd ); - cout << endl << out << endl; -#elif !defined(NO_OPTIMIZER) - // Standalone (SecondoBDB): run the directive in the in-process optimizer. +#ifndef NO_OPTIMIZER + // Run the directive in the in-process optimizer. if ( !initEmbeddedOptimizer( si ) ) { errorCode = ERR_OPTIMIZER_NOT_AVAILABLE; @@ -915,7 +810,7 @@ SecondoTTY::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 ); NList::setNLRef(nl); } @@ -927,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 ); 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 e8582c8227..f0bf7d276b 100755 --- a/UserInterfaces/makefile +++ b/UserInterfaces/makefile @@ -36,7 +36,8 @@ APPLOBJECTS := \ MainTTY.$(OBJEXT) \ cmsg.$(OBJEXT) \ MainTTYCS.$(OBJEXT) \ - getCommand.$(OBJEXT) + getCommand.$(OBJEXT) \ + SQLLanguage.$(OBJEXT) APPLICATIONS := $(BINDIR)/Secondo$(SMIUP) \ $(BINDIR)/SecondoCS \ 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/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 b03c640b98..5a407e8b37 100644 --- a/include/SecondoInterfaceCS.h +++ b/include/SecondoInterfaceCS.h @@ -224,7 +224,24 @@ class SecondoInterfaceCS : public SecondoInterface , MessageHandler { // level 2) is available (compiled in and enabled for that server). bool optimizerAvailable(); - // Sends an SQL-dialect command (command level 2). The server optimizes it + // 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. @@ -241,6 +258,9 @@ class SecondoInterfaceCS : public SecondoInterface , MessageHandler { // "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; @@ -295,6 +315,16 @@ class SecondoInterfaceCS : public SecondoInterface , MessageHandler { // 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/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