[rkward-cvs] [rkward] rkward/rbackend: Don't get all confused, in an error (not strictly syntax error) makes R jump straight out of R_ParseVector to toplevel REPL.

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Thu Dec 4 16:46:03 UTC 2014


Git commit 2988466a099adb0fca39ef79588016db90cbd760 by Thomas Friedrichsmeier.
Committed on 04/12/2014 at 16:44.
Pushed by tfry into branch 'master'.

Don't get all confused, in an error (not strictly syntax error) makes R jump straight out of R_ParseVector to toplevel REPL.

M  +25   -11   rkward/rbackend/rkrbackend.cpp

http://commits.kde.org/rkward/2988466a099adb0fca39ef79588016db90cbd760

diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index 2158eb1..7e74b6a 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -1114,34 +1114,48 @@ void RKRBackend::enterEventLoop () {
 	// NOTE: Do NOT run Rf_endEmbeddedR(). It does more that we want. We rely on RCleanup, instead.
 }
 
+struct SafeParseWrap {
+	SEXP cv;
+	SEXP pr;
+	ParseStatus status;
+};
+
+void safeParseVector (void *data) {
+	SafeParseWrap *wrap = static_cast<SafeParseWrap*> (data);
+	wrap->pr = 0;
+	// TODO: Maybe we can use R_ParseGeneral instead. Then we could find the exact character, where parsing fails. Nope: not exported API
+	wrap->pr = R_ParseVector (wrap->cv, -1, &(wrap->status), R_NilValue);
+}
+
 SEXP parseCommand (const QString &command_qstring, RKRBackend::RKWardRError *error) {
 	RK_TRACE (RBACKEND);
 
-	ParseStatus status = PARSE_NULL;
-	SEXP cv, pr;
+	SafeParseWrap wrap;
+	wrap.status = PARSE_NULL;
 
 	QByteArray localc = RKRBackend::this_pointer->current_locale_codec->fromUnicode (command_qstring);		// needed so the string below does not go out of scope
 	const char *command = localc.data ();
 
-	PROTECT(cv=Rf_allocVector(STRSXP, 1));
-	SET_STRING_ELT(cv, 0, Rf_mkChar(command));
+	PROTECT(wrap.cv=Rf_allocVector(STRSXP, 1));
+	SET_STRING_ELT(wrap.cv, 0, Rf_mkChar(command));
 
-	// TODO: Maybe we can use R_ParseGeneral instead. Then we could find the exact character, where parsing fails. Nope: not exported API
-	pr=R_ParseVector(cv, -1, &status, R_NilValue);
+	// Yes, if there is an error in the parse, R does jump back to toplevel!
+	R_ToplevelExec (safeParseVector, &wrap);
+	SEXP pr = wrap.pr;
 	UNPROTECT(1);
 
 	if ((!pr) || (TYPEOF (pr) == NILSXP)) {
 		// got a null SEXP. This means parse was *not* ok, even if R_ParseVector told us otherwise
-		if (status == PARSE_OK) {
-			status = PARSE_ERROR;
+		if (wrap.status == PARSE_OK) {
+			wrap.status = PARSE_ERROR;
 			printf ("weird parse error\n");
 		}
 	}
 
-	if (status != PARSE_OK) {
-		if ((status == PARSE_INCOMPLETE) || (status == PARSE_EOF)) {
+	if (wrap.status != PARSE_OK) {
+		if ((wrap.status == PARSE_INCOMPLETE) || (wrap.status == PARSE_EOF)) {
 			*error = RKRBackend::Incomplete;
-		} else if (status == PARSE_ERROR) {
+		} else if (wrap.status == PARSE_ERROR) {
 			//extern SEXP parseError (SEXP call, int linenum);
 			//parseError (R_NilValue, 0);
 			*error = RKRBackend::SyntaxError;





More information about the rkward-tracker mailing list