changeset 3483:1bb6e519a4a2

[project @ 2000-01-26 23:37:10 by jwe]
author jwe
date Wed, 26 Jan 2000 23:37:11 +0000
parents e461b8ed7c4d
children 8b1f46ac2b64
files scripts/ChangeLog scripts/miscellaneous/popen2.m src/ChangeLog src/oct-stream.cc src/oct-stream.h
diffstat 5 files changed, 380 insertions(+), 150 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Wed Jan 26 07:25:57 2000 +0000
+++ b/scripts/ChangeLog	Wed Jan 26 23:37:11 2000 +0000
@@ -1,3 +1,8 @@
+2000-01-26  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* miscellaneous/popen2.m: Deal with the fact that pipe now returns
+	a list of file structures, not a vector of numeric file ids.
+
 2000-01-25  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* plot/__axis_label__.m: New function.
--- a/scripts/miscellaneous/popen2.m	Wed Jan 26 07:25:57 2000 +0000
+++ b/scripts/miscellaneous/popen2.m	Wed Jan 26 23:37:11 2000 +0000
@@ -71,14 +71,14 @@
 
         if (pid == 0)
 
-          fclose (stdin_pipe (2));
-          fclose (stdout_pipe (1));
+          fclose (nth (stdin_pipe, 2));
+          fclose (nth (stdout_pipe, 1));
 
-          dup2 (stdin_pipe (1), stdin);
-          fclose (stdin_pipe (1));
+          dup2 (nth (stdin_pipe, 1), stdin);
+          fclose (nth (stdin_pipe, 1));
 
-          dup2 (stdout_pipe (2), stdout);
-          fclose (stdout_pipe (2));
+          dup2 (nth (stdout_pipe, 2), stdout);
+          fclose (nth (stdout_pipe, 2));
 
           if (exec (command, args) < 0)
             error ("popen2: unable to start process `%s'", command);
@@ -87,14 +87,14 @@
 
         elseif (pid)
 
-          fclose (stdin_pipe (1));
-          fclose (stdout_pipe (2));
+          fclose (nth (stdin_pipe, 1));
+          fclose (nth (stdout_pipe, 2));
 
-          if (fcntl (stdout_pipe (1), __F_SETFL__, __O_NONBLOCK__) < 0)
+          if (fcntl (nth (stdout_pipe, 1), __F_SETFL__, __O_NONBLOCK__) < 0)
             error ("popen2: error setting file mode");
           else
-            in = stdin_pipe (2);
-            out = stdout_pipe (1);
+            in = nth (stdin_pipe, 2);
+            out = nth (stdout_pipe, 1);
           endif
 
         elseif (pid < 0)
--- a/src/ChangeLog	Wed Jan 26 07:25:57 2000 +0000
+++ b/src/ChangeLog	Wed Jan 26 23:37:11 2000 +0000
@@ -1,3 +1,29 @@
+2000-01-26  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* oct-stream.h (scanf_format_elt::char_class): New struct elt.
+	Add arg to constructor.
+	(scanf_format_elt::special_conversion): New enum.
+	* oct-stream.cc (scanf_format_list::add_elt_to_list): New arg,
+	char_class.  Pass it to scanf_format_elt constructor.
+	(scanf_format_list::scanf_format_list): Create separate list
+	elements for whitespace and literal conversions.
+	(expand_char_class): New function.
+	(scanf_format_list::finish_conversion): Extract character class
+	(not including the delimiting brackets) and expand the list of
+	characters.  Pass the result to add_elt_to_list.
+	(scanf_format_list::all_character_conversions): Also accept '^',
+	scanf_format_elt::literal_conversion, and
+	scanf_format_elt::whitespace_conversion types too.
+	(DO_WHITESPACE_CONVERSION, BEGIN_CHAR_CLASS_CONVERSION,
+	BEGIN_C_CONVERSION, BEGIN_S_CONVERSION, DO_LITERAL_CONVERSION):
+	New macros.
+	(octave_base_stream::do_scanf, octave_base_stream::do_oscanf):
+	Use them to avoid code duplication.
+	Handle whitespace, literal text, and character class conversions.
+	(octave_base_stream::oscanf): Loop over all format list elements,
+	not just the first nconv elements.  Clear status flags on is for
+	all streams.
+
 2000-01-25  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* xdiv.cc (result_ok): Just check value of info.
--- a/src/oct-stream.cc	Wed Jan 26 07:25:57 2000 +0000
+++ b/src/oct-stream.cc	Wed Jan 26 23:37:11 2000 +0000
@@ -177,17 +177,42 @@
 
       if (s[i] == '%')
 	{
+	  // Process percent-escape conversion type.
+
 	  process_conversion (s, i, n, width, discard, type, modifier,
 			      num_elts);
 	  have_more = (buf != 0);
 	}
-      else
+      else if (isspace (s[i]))
 	{
+	  type = scanf_format_elt::whitespace_conversion;
+
 	  width = 0;
 	  discard = false;
 	  modifier = '\0';
-	  type = '\0';
-	  *buf << s[i++];
+	  *buf << " ";
+
+	  while (++i < n && isspace (s[i]))
+	    /* skip whitespace */;
+
+	  add_elt_to_list (width, discard, type, modifier, num_elts);
+
+	  have_more = false;
+	}
+      else
+	{
+	  type = scanf_format_elt::literal_conversion;
+
+	  width = 0;
+	  discard = false;
+	  modifier = '\0';
+
+	  while (i < n && ! isspace (s[i]) && s[i] != '%')
+	    *buf << s[i++];
+
+	  add_elt_to_list (width, discard, type, modifier, num_elts);
+
+	  have_more = false;
 	}
 
       if (nconv < 0)
@@ -218,7 +243,8 @@
 
 void
 scanf_format_list::add_elt_to_list (int width, bool discard, char type,
-				    char modifier, int& num_elts)
+				    char modifier, int& num_elts,
+				    const string& char_class)
 {
   if (buf)
     {
@@ -231,7 +257,8 @@
 	  if (*text)
 	    {
 	      scanf_format_elt *elt
-		= new scanf_format_elt (text, width, discard, type, modifier);
+		= new scanf_format_elt (text, width, discard, type,
+					modifier, char_class);
 
 	      if (num_elts == list.length ())
 		list.resize (2 * num_elts);
@@ -247,11 +274,45 @@
     }
 }
 
+static string
+expand_char_class (const string& s)
+{
+  string retval;
+
+  size_t len = s.length ();
+
+  size_t i = 0;
+
+  while (i < len)
+    {
+      unsigned char c = s[i++];
+
+      if (c == '-' && i > 1 && i < len
+	  && (unsigned char) s[i-2] <= (unsigned char) s[i])
+	{
+	  // Add all characters from the range except the first (we
+	  // already added it below).
+
+	  for (c = s[i-2]+1; c < s[i]; c++)
+	    retval += c;
+	}
+      else
+	{
+	  // Add the character to the class.  Only add '-' if it is
+	  // the last character in the class.
+
+	  if (c != '-' || i == len)
+	    retval += c;
+	}
+    }
+
+  return retval;
+}
+
 void
 scanf_format_list::process_conversion (const string& s, int& i, int n,
 				       int& width, bool& discard, char& type,
 				       char& modifier, int& num_elts)
-
 {
   width = 0;
   discard = false;
@@ -357,10 +418,15 @@
 {
   int retval = 0;
 
+  string char_class;
+
   if (s[i] == '%')
     *buf << s[i++];
   else
     {
+      int beg_idx = -1;
+      int end_idx = -1;
+
       type = s[i];
 
       if (s[i] == '[')
@@ -369,10 +435,20 @@
 
 	  if (i < n)
 	    {
+	      beg_idx = i;
+
 	      if (s[i] == '^')
 		{
 		  type = '^';
 		  *buf << s[i++];
+
+		  if (i < n)
+		    {
+		      beg_idx = i;
+
+		      if (s[i] == ']')
+			*buf << s[i++];
+		    }
 		}
 	      else if (s[i] == ']')
 		*buf << s[i++];
@@ -382,7 +458,10 @@
 	    *buf << s[i++];
 
 	  if (i < n && s[i] == ']')
-	    *buf << s[i++];
+	    {
+	      end_idx = i-1;
+	      *buf << s[i++];
+	    }
 
 	  if (s[i-1] != ']')
 	    retval = nconv = -1;
@@ -393,7 +472,14 @@
       nconv++;
 
       if (nconv > 0)
-	add_elt_to_list (width, discard, type, modifier, num_elts);
+	{
+	  if (beg_idx >= 0 && end_idx >= 0)
+	    char_class = expand_char_class (s.substr (beg_idx,
+						      end_idx - beg_idx +1));
+
+	  add_elt_to_list (width, discard, type, modifier, num_elts,
+			   char_class);
+	}
     }
 
   return retval;
@@ -408,11 +494,20 @@
     {
       scanf_format_elt *elt = list(i);
 
-      cerr << elt->width << "\t"
-	   << elt->discard << "\t"
-	   << elt->type << "\t"
-	   << elt->modifier << "\t"
-	   << undo_string_escapes (elt->text) << "\n";
+      cerr << "width:      " << elt->width << "\n"
+	   << "discard:    " << elt->discard << "\n"
+	   << "type:       ";
+
+      if (elt->type == scanf_format_elt::literal_conversion)
+	cerr << "literal text\n";
+      else if (elt->type == scanf_format_elt::whitespace_conversion)
+	cerr << "whitespace\n";
+      else
+	cerr << elt->type << "\n";
+
+      cerr << "modifier:   " << elt->modifier << "\n"
+	   << "char_class: `" << undo_string_escapes (elt->char_class) << "'\n"
+	   << "text:       `" << undo_string_escapes (elt->text) << "'\n\n";
     }
 }
 
@@ -429,7 +524,9 @@
 
 	  switch (elt->type)
 	    {
-	    case 'c': case 's': case '%': case '[':
+	    case 'c': case 's': case '%': case '[': case '^':
+	    case scanf_format_elt::literal_conversion:
+	    case scanf_format_elt::whitespace_conversion:
 	      break;
 
 	    default:
@@ -956,6 +1053,153 @@
 do_scanf_conv (istream&, const char*, double*, Matrix&, double*, int&,
 	       int&, int, int, bool);
 
+#define DO_WHITESPACE_CONVERSION() \
+  do \
+    { \
+      int c = EOF; \
+ \
+      while (is && (c = is.get ()) != EOF && isspace (c)) \
+	/* skip whitespace */; \
+ \
+      if (c != EOF) \
+	is.putback (c); \
+    } \
+  while (0)
+
+#define DO_LITERAL_CONVERSION() \
+  do \
+    { \
+      int c = EOF; \
+ \
+      int n = strlen (fmt); \
+      int i = 0; \
+ \
+      while (i < n && is && (c = is.get ()) != EOF) \
+	{ \
+	  if (c == fmt[i]) \
+	    { \
+	      i++; \
+	      continue; \
+	    } \
+	  else \
+	    { \
+	      is.putback (c); \
+	      break; \
+	    } \
+	} \
+ \
+      if (i != n) \
+	is.setstate (ios::failbit); \
+    } \
+  while (0)
+
+#define BEGIN_C_CONVERSION() \
+  is.unsetf (ios::skipws); \
+ \
+  int width = elt->width ? elt->width : 1; \
+ \
+  char *tmp = new char[width + 1]; \
+ \
+  int c = EOF; \
+  int n = 0; \
+ \
+  while (is && n < width && (c = is.get ()) != EOF) \
+    tmp[n++] = (char) c; \
+ \
+  tmp[n] = '\0'
+
+// For a `%s' format, skip initial whitespace and then read until the
+// next whitespace character.
+#define BEGIN_S_CONVERSION() \
+  int width = elt->width; \
+ \
+  char *tmp = 0; \
+ \
+  do \
+    { \
+      if (width) \
+	{ \
+	  tmp = new char [width+1]; \
+ \
+	  is.scan (fmt, tmp); \
+ \
+	  tmp[width] = '\0'; \
+	} \
+      else \
+	{ \
+	  ostrstream buf; \
+ \
+	  int c = EOF; \
+ \
+	  while (is && (c = is.get ()) != EOF && isspace (c)) \
+	    /* skip leading whitespace */; \
+ \
+	  if (is && c != EOF) \
+	    buf << (char) c; \
+ \
+	  while (is && (c = is.get ()) != EOF && ! isspace (c)) \
+	    buf << (char) c; \
+ \
+	  if (isspace (c)) \
+	    is.putback (c); \
+ \
+	  buf << ends; \
+ \
+	  tmp = buf.str (); \
+	} \
+    } \
+  while (0)
+
+// This format must match a nonempty sequence of characters.
+#define BEGIN_CHAR_CLASS_CONVERSION() \
+  int width = elt->width; \
+ \
+  char *tmp = 0; \
+ \
+  do \
+    { \
+      if (width) \
+	{ \
+	  tmp = new char[width+1]; \
+ \
+	  is.scan (fmt, tmp); \
+ \
+	  tmp[width] = '\0'; \
+	} \
+      else \
+	{ \
+	  ostrstream buf; \
+ \
+	  string char_class = elt->char_class; \
+ \
+	  int c = EOF; \
+ \
+	  if (elt->type == '[') \
+	    { \
+	      while (is && (c = is.get ()) != EOF \
+		     && char_class.find (c) != NPOS) \
+		buf << (char) c; \
+	    } \
+	  else \
+	    { \
+	      while (is && (c = is.get ()) != EOF \
+		     && char_class.find (c) == NPOS) \
+		buf << (char) c; \
+	    } \
+ \
+	  if (c != EOF) \
+	    is.putback (c); \
+ \
+	  buf << ends; \
+ \
+	  tmp = buf.str (); \
+ \
+	  if (strlen (tmp) == 0) \
+	    is.setstate (ios::failbit); \
+	} \
+    } \
+  while (0)
+
 #define FINISH_CHARACTER_CONVERSION() \
   do \
     { \
@@ -1120,13 +1364,21 @@
 
 	      switch (elt->type)
 		{
+		case scanf_format_elt::whitespace_conversion:
+		  DO_WHITESPACE_CONVERSION ();
+		  break;
+
+		case scanf_format_elt::literal_conversion:
+		  DO_LITERAL_CONVERSION ();
+		  break;
+
 		case '%':
 		  {
 		    int dummy;
 
 		    is.scan (fmt, &dummy);
 		  }
-		break;
+		  break;
 
 		case 'd': case 'i': case 'o': case 'u': case 'x':
 		  {
@@ -1139,7 +1391,7 @@
 					 data_index, conversion_count,
 					 nr, max_size, discard);
 			}
-		      break;
+			break;
 
 		      case 'l':
 			{
@@ -1148,7 +1400,7 @@
 					 data_index, conversion_count,
 					 nr, max_size, discard);
 			}
-		      break;
+			break;
 
 		      default:
 			{
@@ -1157,10 +1409,10 @@
 					 data_index, conversion_count,
 					 nr, max_size, discard);
 			}
-		      break;
+			break;
 		      }
 		  }
-		break;
+		  break;
 
 		case 'e': case 'f': case 'g':
 		  {
@@ -1170,76 +1422,35 @@
 				   data_index, conversion_count,
 				   nr, max_size, discard);
 		  }
-		break;
+		  break;
 
 		case 'c':
 		  {
-		    is.unsetf (ios::skipws);
-
-		    int width = elt->width;
-
-		    if (width == 0)
-		      width = 1;
-
-		    char *tmp = new char[width+1];
-
-		    int c = EOF;
-		    int n = 0;
-
-		    while (is && n < width && (c = is.get ()) != EOF)
-		      tmp[n++] = (char) c;
-
-		    tmp[n] = '\0';
+		    BEGIN_C_CONVERSION ();
 
 		    FINISH_CHARACTER_CONVERSION ();
+
+		    is.setf (flags);
 		  }
 		  break;
 
 		case 's':
 		  {
-		    int width = elt->width;
-
-		    char *tmp = 0;
-
-		    if (width)
-		      {
-			tmp = new char [width+1];
-
-			is.scan (fmt, tmp);
-
-			tmp[width] = '\0';
-		      }
-		    else
-		      {
-			// We're looking at a `%s' format.  We have to
-			// skip initial whitespace and then read until
-			// the next whitespace character.
-
-			ostrstream buf;
-
-			int c = EOF;
-
-			while (is && (c = is.get ()) != EOF && isspace (c))
-			  /* skip leading whitespace */;
-
-			if (is && c != EOF)
-			  buf << (char) c;
-			  
-			while (is && (c = is.get ()) != EOF && ! isspace (c))
-			  buf << (char) c;
-
-			buf << ends;
-
-			tmp = buf.str ();
-		      }
+		    BEGIN_S_CONVERSION ();
 
 		    FINISH_CHARACTER_CONVERSION ();
-
-		    is.setf (flags);
 		  }
-		break;
-
-		case 'p': case '[':
+		  break;
+
+		case '[': case '^':
+		  {
+		    BEGIN_CHAR_CLASS_CONVERSION ();
+
+		    FINISH_CHARACTER_CONVERSION ();
+		  }
+		  break;
+
+		case 'p':
 		  error ("fscanf: unsupported format specifier");
 		  break;
 
@@ -1436,6 +1647,14 @@
 
 	  switch (elt->type)
 	    {
+	    case scanf_format_elt::whitespace_conversion:
+	      DO_WHITESPACE_CONVERSION ();
+	      break;
+
+	    case scanf_format_elt::literal_conversion:
+	      DO_LITERAL_CONVERSION ();
+	      break;
+
 	    case '%':
 	      {
 		int dummy;
@@ -1475,69 +1694,26 @@
 
 	    case 'c':
 	      {
-		is.unsetf (ios::skipws);
-
-		int width = elt->width ? elt->width : 1;
-
-		char *tmp = new char[width + 1];
-
-		if (is.scan (fmt, tmp))
-		  {
-		    if (! discard)
-		      {
-			tmp[width] = '\0';
-			retval = tmp;
-		      }
-		  }
-		else
+		BEGIN_C_CONVERSION ();
+
+		if (! discard)
+		  retval = tmp;
+
+		delete [] tmp;
+
+		if (! is)
 		  quit = true;
 
 		is.setf (flags);
-
-		delete [] tmp;
 	      }
 	      break;
 
 	    case 's':
 	      {
-		int width = elt->width;
-
-		char *tmp = 0;
-
-		if (width)
-		  {
-		    tmp = new char [width+1];
-
-		    is.scan (fmt, tmp);
-
-		    tmp[width] = '\0';
-		  }
-		else
-		  {
-		    // We're looking at a `%s' format.  We have to
-		    // skip initial whitespace and then read until
-		    // the next whitespace character.
-
-		    ostrstream buf;
-
-		    int c = EOF;
-
-		    while (is && (c = is.get ()) != EOF && isspace (c))
-		      /* skip leading whitespace */;
-
-		    if (is && c != EOF)
-		      buf << (char) c;
-			  
-		    while (is && (c = is.get ()) != EOF && ! isspace (c))
-		      buf << (char) c;
-
-		    buf << ends;
-
-		    tmp = buf.str ();
-
-		    if (! discard)
-		      retval = tmp;
-		  }
+		BEGIN_S_CONVERSION ();
+
+		if (! discard)
+		  retval = tmp;
 
 		delete [] tmp;
 
@@ -1546,7 +1722,21 @@
 	      }
 	      break;
 
-	    case 'p': case '[':
+	    case '[': case '^':
+	      {
+		BEGIN_CHAR_CLASS_CONVERSION ();
+
+		if (! discard)
+		  retval = tmp;
+
+		delete [] tmp;
+
+		if (! is)
+		  quit = true;
+	      }
+	      break;
+
+	    case 'p':
 	      error ("fscanf: unsupported format specifier");
 	      break;
 
@@ -1559,13 +1749,11 @@
       if (ok () && is.fail ())
 	{
 	  error ("fscanf: read error");
-      
+
 	  // XXX FIXME XXX -- is this the right thing to do?
 
 	  if (interactive && name () == "stdin")
 	    {
-	      is.clear ();
-
 	      // Skip to end of line.
 
 	      bool err;
@@ -1630,6 +1818,8 @@
 
 	default:
 	  {
+	    is.clear ();
+
 	    int len = fmt_list.length ();
 
 	    retval.resize (nconv, Matrix ());
@@ -1640,7 +1830,7 @@
 
 	    bool quit = false;
 
-	    for (int i = 0; i < nconv; i++)
+	    for (int i = 0; i < len; i++)
 	      {
 		octave_value tmp;
 
--- a/src/oct-stream.h	Wed Jan 26 07:25:57 2000 +0000
+++ b/src/oct-stream.h	Wed Jan 26 23:37:11 2000 +0000
@@ -41,9 +41,17 @@
 struct
 scanf_format_elt
 {
+  enum special_conversion
+    {
+      whitespace_conversion = 1,
+      literal_conversion = 2
+    };
+
   scanf_format_elt (const char *txt = 0, int w = 0, bool d = false,
-		    char typ = '\0', char mod = '\0')
-    : text (txt), width (w), discard (d), type (typ), modifier (mod) { }
+		    char typ = '\0', char mod = '\0',
+		    const string& ch_class = string ())
+    : text (txt), width (w), discard (d), type (typ), modifier (mod),
+      char_class (ch_class) { }
 
   ~scanf_format_elt (void) { delete text; }
 
@@ -52,6 +60,7 @@
   bool discard;
   char type;
   char modifier;
+  string char_class;
 };
 
 class
@@ -115,7 +124,7 @@
   ostrstream *buf;
 
   void add_elt_to_list (int width, bool discard, char type, char modifier,
-			int& num_elts);
+			int& num_elts, const string& char_class = string ());
 
   void process_conversion (const string& s, int& i, int n, int& width,
 			   bool& discard, char& type, char& modifier,