changeset 1239:68c2b06beacb octave-forge

Use Feval directly rather than trying to simulate it --- this should be more robust against changes in the octave interpreter.
author pkienzle
date Wed, 28 Jan 2004 22:19:34 +0000
parents 85617a3eb1ca
children a4fd2e3c9e96
files main/miscellaneous/listen.cc
diffstat 1 files changed, 81 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/main/miscellaneous/listen.cc	Wed Jan 28 16:57:59 2004 +0000
+++ b/main/miscellaneous/listen.cc	Wed Jan 28 22:19:34 2004 +0000
@@ -1,4 +1,8 @@
 #define STATUS(x) do { if (debug) std::cout << x << std::endl << std::flush; } while (0)
+#define USE_DEFUN_INTERNAL 1
+// Temporary hack (I hope).  For some reason the interpreter
+// is not finding the send/send_error commands, so I install
+// them by hand..
 
 #include <iomanip>
 
@@ -17,12 +21,15 @@
 #include <octave/oct.h>
 #include <octave/parse.h>
 #include <octave/variables.h>
+#if 0
 #include <octave/unwind-prot.h>
+#endif
 #include <octave/oct-syscalls.h>
 #include <octave/oct-time.h>
 #include <octave/lo-mappers.h>
 
 static bool debug = false;
+static char* context = NULL;
 
 static double timestamp = 0.0;
 inline void tic(void) { timestamp = octave_time(); }
@@ -35,6 +42,7 @@
   for (std::string::iterator i=s.begin(); i != s.end(); i++) *i = tolower(*i);
 }
 
+#if 0
 octave_value
 get_builtin_value (const std::string& nm)
 {
@@ -56,7 +64,7 @@
 
   return retval;
 }
-
+#endif
 
 // XXX FIXME XXX autoconf stuff
 #if 0 && defined(_sgi)
@@ -195,13 +203,12 @@
   // XXX FIXME XXX check read/write return values
   assert(sizeof(unsigned long int) == 4);
   char command[5];
-  char def_buffer[16536];
+  char def_context[16536];
   bool ok;
-  char *buffer;
   STATUS("waiting for command");
 
-  // XXX FIXME XXX do we need to specify the buffer size?
-  //  int bufsize=sizeof(def_buffer);
+  // XXX FIXME XXX do we need to specify the context size?
+  //  int bufsize=sizeof(def_context);
   //  socklen_t ol;
   //  ol=sizeof(bufsize);
   //  setsockopt(channel,SOL_SOCKET,SO_SNDBUF,&bufsize,ol);
@@ -231,34 +238,34 @@
     len = ntohl(len);
     // STATUS("read 4 byte command length in " << toc() << "us"); 
 
-    // Read the command buffer, allocating a new one if the default
+    // Read the command context, allocating a new one if the default
     // is too small.
-    if (len > (signed)sizeof(def_buffer)-1) {
+    if (len > (signed)sizeof(def_context)-1) {
       // XXX FIXME XXX use octave allocators
       // XXX FIXME XXX unwind_protect
-      buffer = new char[len+1];
-      if (buffer == NULL) {
+      context= new char[len+1];
+      if (context== NULL) {
 	// Requested command is too large --- skip to the next command
 	// XXX FIXME XXX maybe we want to kill the connection instead?
 	channel_error(channel,"out of memory");
 	ok = true;
 	STATUS("skip big command loop");
-	while (ok && len > (signed)sizeof(def_buffer)) {
-	  ok = reads(channel, def_buffer, sizeof(def_buffer));
-	  len -= sizeof(def_buffer);
+	while (ok && len > (signed)sizeof(def_context)) {
+	  ok = reads(channel, def_context, sizeof(def_context));
+	  len -= sizeof(def_context);
 	}
 	STATUS("done skip big command loop");
 	if (!ok) break;
-	ok = reads(channel, def_buffer, sizeof(def_buffer));
+	ok = reads(channel, def_context, sizeof(def_context));
 	if (!ok) break;
 	continue;
       }
     } else {
-      buffer = def_buffer;
+      context = def_context;
     }
     // if (debug) tic();
-    ok = reads(channel, buffer, len);
-    buffer[len] = '\0';
+    ok = reads(channel, context, len);
+    context[len] = '\0';
     STATUS("read " << len << " byte command in " << toc() << "us");
 
     // Process the command
@@ -266,11 +273,11 @@
     case 'm': // send the named matrix 
       {
 	// XXX FIXME XXX this can be removed: app can do send(name,value)
-	STATUS("sending " << buffer);
+	STATUS("sending " << context);
 	unsigned long t;
 	
 	// read the matrix contents
-	octave_value def = get_octave_value(buffer);
+	octave_value def = get_octave_value(context);
 	if(!def.is_defined() || !def.is_real_matrix()) 
 	  channel_error(channel,"not a matrix");
 	Matrix m = def.matrix_value();
@@ -285,7 +292,7 @@
 	if (ok) ok = writes(channel,&t,4);            // columns
 	t = htonl(len); 
 	if (ok) ok = writes(channel, &t, 4);          // name length
-	if (ok) ok = writes(channel,buffer,len);      // name
+	if (ok) ok = writes(channel,context,len);      // name
 	
 	// write the matrix contents
 	const double *v = m.data();                   // data
@@ -306,23 +313,29 @@
 		// XXX FIXME XXX can we limit the maximum output width for a
 		// string?  The setprecision() io manipulator doesn't do it.
 		// In the meantime, a hack ...
-		char t = buffer[400]; buffer[400] = '\0';
+		char t = context[400]; context[400] = '\0';
 		STATUS("evaluating (" << len << ") " 
-		       << buffer << std::endl 
+		       << context << std::endl 
 		       << "..." << std::endl 
-		       << buffer+len-100);
-		buffer[400] = t;
+		       << context+len-100);
+		context[400] = t;
 	      }
 	    else
 	      {
-		STATUS("evaluating (" << len << ") " << buffer);
+		STATUS("evaluating (" << len << ") " << context);
 	      }
 	  }
 
 	if (debug) tic();
+#if 1
+	octave_value_list evalargs;
+	evalargs(1) = "send_error(lasterr);";
+	evalargs(0) = context;
+	feval("eval",evalargs,0);
+#else
 	int parse_status = 0;
 	error_state = 0;
-	eval_string(buffer, true, parse_status, 0);
+	eval_string(context, true, parse_status, 0);
 	STATUS("parse status = " << parse_status << ", error state = " 
 	       << error_state << ", processing time = " << toc() << "us");
 	if (parse_status != 0 || error_state)
@@ -335,17 +348,18 @@
 	    str += "when evaluating:\n";
 	    if (len > 100) 
 	      {	
-		char t=buffer[100]; 
-	        buffer[100] = '\0'; 
-	        str+=buffer; 
-	        buffer[100]=t;
+		char t=context[100]; 
+	        context[100] = '\0'; 
+	        str+=context; 
+	        context[100]=t;
 	      }
 	    else
-              str += buffer;
+              str += context;
 	    STATUS("error is " << str);
 	    channel_error(channel,str.c_str());
 	    clear_global_error_variable(NULL);
 	  }
+#endif
       }
       break;
       
@@ -358,7 +372,7 @@
       break;
     }
 
-    if (buffer != def_buffer) delete[] buffer;
+    if (context != def_context) delete[] context;
     // STATUS("done " << command);
     if (!ok) break;
     if (debug) tic();
@@ -368,11 +382,39 @@
 
 int channel = -1;
 
-#if 1
-// Temporary hack (I hope).  For some reason 
-// the DEFUN_DLD isn't being found from
-// within listen, so I install it by hand.
+#if USE_DEFUN_INTERNAL
+DEFUN_INTERNAL(send_error,args,,false,"\
+Send the given error message across the socket.  The error context\n\
+is taken to be the last command received from the socket.")
+#else
+DEFUN_DLD(send_error,args,,"\
+Send the given error message across the socket.  The error context\n\
+is taken to be the last command received from the socket.")
+#endif
+{
+  std::string str;
+  const int nargin = args.length();
+  if (nargin != 1) str="send_error not called with error";
+  else str = args(0).string_value();
 
+  // provide a context for the error (but not too much!)
+  str += "when evaluating:\n";
+  if (strlen(context) > 100) 
+    {	
+      char t=context[100]; 
+      context[100] = '\0'; 
+      str+=context; 
+      context[100]=t;
+    }
+  else
+    str += context;
+ 
+  STATUS("error is " << str);
+  channel_error(channel,str.c_str());
+  return octave_value_list();
+}
+
+#if USE_DEFUN_INTERNAL
 DEFUN_INTERNAL(send,args,,false,"\
 send(str)\n\
   Send a command on the current connection\n\
@@ -560,9 +602,11 @@
     return ret;
   }
 
+#if 0
   unwind_protect::begin_frame("Flisten");
   unwind_protect_bool (buffer_error_messages);
   buffer_error_messages = true;
+#endif
 
   sigchld_setup();
 
@@ -633,6 +677,8 @@
 
   STATUS("could not read commands; returning");
   close(sockfd);
+#if 0
   unwind_protect::run_frame("Flisten");
+#endif
   return ret;
 }