[rkward-cvs] SF.net SVN: rkward: [1577] trunk/rkward
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Wed Mar 14 13:23:27 UTC 2007
Revision: 1577
http://svn.sourceforge.net/rkward/?rev=1577&view=rev
Author: tfry
Date: 2007-03-14 06:23:26 -0700 (Wed, 14 Mar 2007)
Log Message:
-----------
Make sure never to run parts of incomplete user commands
Modified Paths:
--------------
trunk/rkward/ChangeLog
trunk/rkward/rkward/rbackend/rcommand.h
trunk/rkward/rkward/rbackend/rembedinternal.cpp
trunk/rkward/rkward/rbackend/rembedinternal.h
trunk/rkward/rkward/rkconsole.cpp
Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog 2007-03-14 12:38:17 UTC (rev 1576)
+++ trunk/rkward/ChangeLog 2007-03-14 13:23:26 UTC (rev 1577)
@@ -1,3 +1,4 @@
+- make sure not to run parts of an incomplete user command. It would lead to all sorts of subtle problems
- if an incomplete command was piped through the console, the console does not become blocked for piping
- make "run current line" advance the cursor to next line after running
- warnings and errors are highlighted in command log / console (warnings only for R >= 2.5.x)
Modified: trunk/rkward/rkward/rbackend/rcommand.h
===================================================================
--- trunk/rkward/rkward/rbackend/rcommand.h 2007-03-14 12:38:17 UTC (rev 1576)
+++ trunk/rkward/rkward/rbackend/rcommand.h 2007-03-14 13:23:26 UTC (rev 1577)
@@ -200,6 +200,8 @@
void removeReceiver (RCommandReceiver *receiver);
void addTypeFlag (int flag) { _type |= flag; };
ROutputList &getOutput () { return output_list; };
+/** modify the command string. DO NOT CALL THIS after the command has been submitted! */
+ void setCommand (const QString &command) { _command = command; };
private:
friend class RThread;
friend class RInterface;
Modified: trunk/rkward/rkward/rbackend/rembedinternal.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rembedinternal.cpp 2007-03-14 12:38:17 UTC (rev 1576)
+++ trunk/rkward/rkward/rbackend/rembedinternal.cpp 2007-03-14 13:23:26 UTC (rev 1577)
@@ -645,13 +645,11 @@
return true;
}
-SEXP runCommandInternalBase (const QString &command_qstring, REmbedInternal::RKWardRError *error) {
+SEXP parseCommand (const QString &command_qstring, REmbedInternal::RKWardRError *error) {
RK_TRACE (RBACKEND);
-// some copying from RServe below
- int r_error = 0;
ParseStatus status = PARSE_NULL;
- SEXP cv, pr, exp;
+ SEXP cv, pr;
int len = -1;
QCString localc = REmbedInternal::this_pointer->current_locale_codec->fromUnicode (command_qstring, len); // needed so the string below does not go out of scope
@@ -686,34 +684,43 @@
} else { // PARSE_NULL
*error = REmbedInternal::OtherError;
}
- exp = R_NilValue;
- } else { // no error during parsing, let's try to evaluate the command
- PROTECT (pr);
- exp=R_NilValue;
+ pr = R_NilValue;
+ }
- if (TYPEOF(pr)==EXPRSXP && LENGTH(pr)>0) {
- int bi=0;
- while (bi<LENGTH(pr)) {
- SEXP pxp=VECTOR_ELT(pr, bi);
- exp=R_tryEval(pxp, R_GlobalEnv, &r_error);
- bi++;
- if (r_error) {
- break;
- }
+ return pr;
+}
+
+SEXP runCommandInternalBase (SEXP pr, REmbedInternal::RKWardRError *error) {
+ RK_TRACE (RBACKEND);
+
+ SEXP exp;
+ int r_error = 0;
+
+ PROTECT (pr);
+ exp=R_NilValue;
+
+ if (TYPEOF(pr)==EXPRSXP && LENGTH(pr)>0) {
+ int bi=0;
+ while (bi<LENGTH(pr)) {
+ SEXP pxp=VECTOR_ELT(pr, bi);
+ exp=R_tryEval(pxp, R_GlobalEnv, &r_error);
+ bi++;
+ if (r_error) {
+ break;
}
- } else {
- exp=R_tryEval(pr, R_GlobalEnv, &r_error);
}
+ } else {
+ exp=R_tryEval(pr, R_GlobalEnv, &r_error);
+ }
- if (r_error) {
- *error = REmbedInternal::OtherError;
- } else {
- *error = REmbedInternal::NoError;
- }
-
- UNPROTECT(1); /* pr */
+ if (r_error) {
+ *error = REmbedInternal::OtherError;
+ } else {
+ *error = REmbedInternal::NoError;
}
+ UNPROTECT(1); /* pr */
+
// for safety, let's protect exp for the two print calls below.
// TODO: this is not good. It causes an additional PROTECT and UPROTECT. Need to (re-)move printing
PROTECT (exp);
@@ -782,9 +789,13 @@
connectCallbacks (); // sorry, but we will not play nicely with additional frontends trying to override our callbacks. (Unless they start their own R event loop, then they should be fine)
+ *error = NoError;
if (!print_result) {
- runCommandInternalBase (command_qstring, error);
+ SEXP parsed = parseCommand (command_qstring, error);
+ if (*error == NoError) runCommandInternalBase (parsed, error);
} else { // run a user command
+ SEXP parsed = parseCommand (command_qstring, error);
+ if ((*error != NoError)) return;
#ifdef USE_R_REPLDLLDO1
/* Using R_ReplDLLdo1 () is a pain, but it seems to be the only entry point for evaluating a command as if it had been entered on a plain R console (with auto-printing if not invisible, etc.). Esp. since R_Visible is no longer exported in R 2.5.0, as it seems as of today (2007-01-17).
@@ -837,10 +848,8 @@
R_Visible = (Rboolean) 0;
SEXP exp;
- PROTECT (exp = runCommandInternalBase (command_qstring, error));
-/* char dummy[100];
- sprintf (dummy, "type: %d", TYPEOF (exp));
- Rprintf (dummy, 100); */
+ PROTECT (exp = runCommandInternalBase (parsed, error));
+
if (*error == NoError) {
SET_SYMVALUE (R_LastvalueSymbol, exp);
if (R_Visible) {
@@ -862,9 +871,11 @@
SEXP exp;
QString *list = 0;
+
+ *error = NoError;
+ SEXP parsed = parseCommand (command, error);
+ if (*error == NoError) PROTECT (exp = runCommandInternalBase (parsed, error));
- PROTECT (exp = runCommandInternalBase (command, error));
-
if (*error == NoError) {
list = SEXPToStringList (exp, count);
}
@@ -884,7 +895,9 @@
SEXP exp;
double *reals = 0;
- PROTECT (exp = runCommandInternalBase (command, error));
+ *error = NoError;
+ SEXP parsed = parseCommand (command, error);
+ if (*error == NoError) PROTECT (exp = runCommandInternalBase (parsed, error));
if (*error == NoError) {
reals = SEXPToRealArray (exp, count);
@@ -905,7 +918,9 @@
SEXP exp;
int *integers = 0;
- PROTECT (exp = runCommandInternalBase (command, error));
+ *error = NoError;
+ SEXP parsed = parseCommand (command, error);
+ if (*error == NoError) PROTECT (exp = runCommandInternalBase (parsed, error));
if (*error == NoError) {
integers = SEXPToIntArray (exp, count);
@@ -926,7 +941,9 @@
SEXP exp;
RData *data = 0;
- PROTECT (exp = runCommandInternalBase (command, error));
+ *error = NoError;
+ SEXP parsed = parseCommand (command, error);
+ if (*error == NoError) PROTECT (exp = runCommandInternalBase (parsed, error));
if (*error == NoError) {
data = SEXPToRData (exp);
Modified: trunk/rkward/rkward/rbackend/rembedinternal.h
===================================================================
--- trunk/rkward/rkward/rbackend/rembedinternal.h 2007-03-14 12:38:17 UTC (rev 1576)
+++ trunk/rkward/rkward/rbackend/rembedinternal.h 2007-03-14 13:23:26 UTC (rev 1577)
@@ -94,7 +94,8 @@
@param command command to be run
@param error this will be set to a value in RKWardError depending on success/failure of the command
@param print_result whether the R_Visible flag should be set. If true, R will behave mostly as if in a regular console session. Otherwise values
-will only be printed if called for expressedly with print ("...") or similar. */
+will only be printed if called for expressedly with print ("...") or similar.
+ at param suppress_incomplete make sure never to run an incomplete command */
void runCommandInternal (const QString &command, RKWardRError *error, bool print_result=false);
/** basically a wrapper to runCommandInternal (). Tries to convert the result of the command to an array of char* after running the command. Since
this will not ever be done for user commands, the R_Visible flag will never be set.
Modified: trunk/rkward/rkward/rkconsole.cpp
===================================================================
--- trunk/rkward/rkward/rkconsole.cpp 2007-03-14 12:38:17 UTC (rev 1576)
+++ trunk/rkward/rkward/rkconsole.cpp 2007-03-14 13:23:26 UTC (rev 1577)
@@ -775,12 +775,18 @@
RKGlobals::rInterface ()->issueCommand (command);
}
} else {
- QString text = command->command ();
+ QString command_string = command->command ();
+ QString text = command_string;
text.replace ("\n", QString ("\n") + iprefix);
doc->insertText (doc->numLines () - 1, QString (nprefix).length (), text + '\n');
command->addReceiver (this);
command->addTypeFlag (RCommand::Console);
current_command = command;
+ if (command_incomplete) {
+ RK_ASSERT (command_was_piped);
+ command_string.prepend (incomplete_command);
+ command->setCommand (command_string);
+ }
command_was_piped = true;
RKGlobals::rInterface ()->issueCommand (command);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the rkward-tracker
mailing list