diff libinterp/corefcn/pr-output.cc @ 27518:25479159213b

Don't change anything if format() fails during parsing of multiple arguments. * pr-output.cc: Add special case for format called with no arguments and set all values to defaults and return immediately. Add unwind_protect frame and protect_var all format variables. At end of function, which implies parsing has been succesful, discard unwind_protect state information since it is no longer required.
author Rik <rik@octave.org>
date Wed, 16 Oct 2019 14:35:03 -0700
parents 1ef42010c53b
children 37f9eb2c05e0
line wrap: on
line diff
--- a/libinterp/corefcn/pr-output.cc	Wed Oct 16 13:49:19 2019 -0700
+++ b/libinterp/corefcn/pr-output.cc	Wed Oct 16 14:35:03 2019 -0700
@@ -3569,230 +3569,230 @@
 static inline void
 set_format_style (int argc, const string_vector& argv)
 {
-  int idx = 1;
-  std::string format;
-
-  argc--;
-  if (argc == 0)
+  if (--argc == 0)
     {
+      // Special case of no options, reset to default values
       init_format_state ();
       set_output_prec (5);
-      format = "short";
+      format_string = "short";
       Vcompact_format = false;
       uppercase_format = false;
+      return;
     }
-  else
+
+  int idx = 1;
+  std::string format;
+
+  octave::unwind_protect frame;
+
+  frame.protect_var (bank_format);
+  frame.protect_var (bit_format);
+  frame.protect_var (free_format);
+  frame.protect_var (hex_format);
+  frame.protect_var (plus_format);
+  frame.protect_var (plus_format_chars);
+  frame.protect_var (rat_format);
+  frame.protect_var (print_e);
+  frame.protect_var (print_eng);
+  frame.protect_var (print_g);
+  frame.protect_var (format_string);
+  frame.protect_var (Vcompact_format);
+  frame.protect_var (uppercase_format);
+  int prec = output_precision ();
+  frame.add ([prec] (void) { set_output_prec (prec); });
+
+  format = format_string;   // Initialize with existing value
+  while (argc-- > 0)
     {
-      format = format_string;   // Initialize with existing value
-      while (argc-- > 0)
+      std::string arg = argv[idx++];
+      std::transform (arg.begin (), arg.end (), arg.begin (), tolower);
+
+      if (arg == "short")
         {
-          std::string arg = argv[idx++];
-          std::transform (arg.begin (), arg.end (), arg.begin (), tolower);
-
-          if (arg == "short")
+          format = arg;
+          init_format_state ();
+          if (argc > 0)
             {
-              format = arg;
-              if (argc > 0)
+              arg = argv[idx];
+              if (arg == "e")
                 {
-                  arg = argv[idx];
-                  if (arg == "e")
-                    {
-                      init_format_state ();
-                      print_e = true;
-                      format.append (arg);
-                      argc--;
-                      idx++;
-                    }
-                  else if (arg == "g")
-                    {
-                      init_format_state ();
-                      print_g = true;
-                      format.append (arg);
-                      argc--;
-                      idx++;
-                    }
-                  else if (arg == "eng")
-                    {
-                      init_format_state ();
-                      print_eng = true;
-                      format.append (arg);
-                      argc--;
-                      idx++;
-                    }
-                  else
-                    init_format_state ();
+                  print_e = true;
+                  format.append (arg);
+                  argc--; idx++;
                 }
-              else
-                init_format_state ();
-
-              set_output_prec (5);
-            }
-          else if (arg == "shorte")
-            {
-              format = arg;
-              init_format_state ();
-              print_e = true;
-              set_output_prec (5);
-            }
-          else if (arg == "shortg")
-            {
-              format = arg;
-              init_format_state ();
-              print_g = true;
-              set_output_prec (5);
-            }
-          else if (arg == "shorteng")
-            {
-              format = arg;
-              init_format_state ();
-              print_eng = true;
-              set_output_prec (5);
-            }
-          else if (arg == "long")
-            {
-              format = arg;
-              if (argc > 0)
+              else if (arg == "g")
+                {
+                  init_format_state ();
+                  print_g = true;
+                  format.append (arg);
+                  argc--; idx++;
+                }
+              else if (arg == "eng")
                 {
-                  arg = argv[idx];
-
-                  if (arg == "e")
-                    {
-                      init_format_state ();
-                      print_e = true;
-                      format.append (arg);
-                      argc--;
-                      idx++;
-                    }
-                  else if (arg == "g")
-                    {
-                      init_format_state ();
-                      print_g = true;
-                      format.append (arg);
-                      argc--;
-                      idx++;
-                    }
-                  else if (arg == "eng")
-                    {
-                      init_format_state ();
-                      print_eng = true;
-                      format.append (arg);
-                      argc--;
-                      idx++;
-                    }
-                  else
-                    init_format_state ();
+                  init_format_state ();
+                  print_eng = true;
+                  format.append (arg);
+                  argc--; idx++;
                 }
-              else
-                init_format_state ();
-
-              set_output_prec (16);
             }
-          else if (arg == "longe")
+          set_output_prec (5);
+        }
+      else if (arg == "shorte")
+        {
+          format = arg;
+          init_format_state ();
+          print_e = true;
+          set_output_prec (5);
+        }
+      else if (arg == "shortg")
+        {
+          format = arg;
+          init_format_state ();
+          print_g = true;
+          set_output_prec (5);
+        }
+      else if (arg == "shorteng")
+        {
+          format = arg;
+          init_format_state ();
+          print_eng = true;
+          set_output_prec (5);
+        }
+      else if (arg == "long")
+        {
+          format = arg;
+          init_format_state ();
+          if (argc > 0)
             {
-              format = arg;
-              init_format_state ();
-              print_e = true;
-              set_output_prec (16);
-            }
-          else if (arg == "longg")
-            {
-              format = arg;
-              init_format_state ();
-              print_g = true;
-              set_output_prec (16);
+              arg = argv[idx];
+
+              if (arg == "e")
+                {
+                  print_e = true;
+                  format.append (arg);
+                  argc--; idx++;
+                }
+              else if (arg == "g")
+                {
+                  print_g = true;
+                  format.append (arg);
+                  argc--; idx++;
+                }
+              else if (arg == "eng")
+                {
+                  print_eng = true;
+                  format.append (arg);
+                  argc--; idx++;
+                }
             }
-          else if (arg == "longeng")
-            {
-              format = arg;
-              init_format_state ();
-              print_eng = true;
-              set_output_prec (16);
-            }
-          else if (arg == "hex")
-            {
-              format = arg;
-              init_format_state ();
-              hex_format = 1;
-            }
-          else if (arg == "native-hex")
-            {
-              format = arg;
-              init_format_state ();
-              hex_format = 2;
-            }
-          else if (arg == "bit")
+          set_output_prec (16);
+        }
+      else if (arg == "longe")
+        {
+          format = arg;
+          init_format_state ();
+          print_e = true;
+          set_output_prec (16);
+        }
+      else if (arg == "longg")
+        {
+          format = arg;
+          init_format_state ();
+          print_g = true;
+          set_output_prec (16);
+        }
+      else if (arg == "longeng")
+        {
+          format = arg;
+          init_format_state ();
+          print_eng = true;
+          set_output_prec (16);
+        }
+      else if (arg == "hex")
+        {
+          format = arg;
+          init_format_state ();
+          hex_format = 1;
+        }
+      else if (arg == "native-hex")
+        {
+          format = arg;
+          init_format_state ();
+          hex_format = 2;
+        }
+      else if (arg == "bit")
+        {
+          format = arg;
+          init_format_state ();
+          bit_format = 1;
+        }
+      else if (arg == "native-bit")
+        {
+          format = arg;
+          init_format_state ();
+          bit_format = 2;
+        }
+      else if (arg == "+" || arg == "plus")
+        {
+          format = arg;
+          init_format_state ();
+          plus_format = true;
+          if (argc > 0)
             {
-              format = arg;
-              init_format_state ();
-              bit_format = 1;
-            }
-          else if (arg == "native-bit")
-            {
-              format = arg;
-              init_format_state ();
-              bit_format = 2;
-            }
-          else if (arg == "+" || arg == "plus")
-            {
-              format = arg;
-              if (argc > 0)
+              arg = argv[idx];
+
+              if (arg.length () == 3)
                 {
-                  arg = argv[idx];
-
-                  if (arg.length () == 3)
-                    {
-                      plus_format_chars = arg;
-                      format.append (arg);
-                      argc--;
-                      idx++;
-                    }
-                  else
-                    plus_format_chars = "+- ";
+                  plus_format_chars = arg;
+                  format.append (arg);
+                  argc--; idx++;
                 }
               else
                 plus_format_chars = "+- ";
-
-              init_format_state ();
-              plus_format = true;
             }
-          else if (arg == "rat")
-            {
-              format = arg;
-              init_format_state ();
-              rat_format = true;
-            }
-          else if (arg == "bank")
-            {
-              format = arg;
-              init_format_state ();
-              bank_format = true;
-            }
-          else if (arg == "free")
-            {
-              format = arg;
-              init_format_state ();
-              free_format = true;
-            }
-          else if (arg == "none")
-            {
-              format = arg;
-              init_format_state ();
-              free_format = true;
-            }
-          else if (arg == "compact")
-            Vcompact_format = true;
-          else if (arg == "loose")
-            Vcompact_format = false;
-          else if (arg == "lowercase")
-            uppercase_format = false;
-          else if (arg == "uppercase")
-            uppercase_format = true;
           else
-            error ("format: unrecognized format state '%s'", arg.c_str ());
+            plus_format_chars = "+- ";
+        }
+      else if (arg == "rat")
+        {
+          format = arg;
+          init_format_state ();
+          rat_format = true;
+        }
+      else if (arg == "bank")
+        {
+          format = arg;
+          init_format_state ();
+          bank_format = true;
         }
+      else if (arg == "free")
+        {
+          format = arg;
+          init_format_state ();
+          free_format = true;
+        }
+      else if (arg == "none")
+        {
+          format = arg;
+          init_format_state ();
+          free_format = true;
+        }
+      else if (arg == "compact")
+        Vcompact_format = true;
+      else if (arg == "loose")
+        Vcompact_format = false;
+      else if (arg == "lowercase")
+        uppercase_format = false;
+      else if (arg == "uppercase")
+        uppercase_format = true;
+      else
+        error ("format: unrecognized format state '%s'", arg.c_str ());
     }
 
   format_string = format;
+
+  // If successful, discard unwind state information
+  frame.discard ();
 }
 
 DEFUN (format, args, nargout,