GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-stream.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2017 John W. Eaton
4 Copyright (C) 2015-2016 Lachlan Andrew, Monash University
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <cassert>
29 #include <cctype>
30 #include <cstring>
31 
32 #include <deque>
33 #include <fstream>
34 #include <iomanip>
35 #include <iostream>
36 #include <sstream>
37 #include <string>
38 
39 #include "Array.h"
40 #include "Cell.h"
41 #include "byte-swap.h"
42 #include "lo-ieee.h"
43 #include "lo-mappers.h"
44 #include "lo-utils.h"
45 #include "oct-locbuf.h"
46 #include "quit.h"
47 #include "singleton-cleanup.h"
48 #include "str-vec.h"
49 
50 #include "error.h"
51 #include "errwarn.h"
52 #include "input.h"
53 #include "interpreter.h"
54 #include "octave.h"
55 #include "oct-stdstrm.h"
56 #include "oct-stream.h"
57 #include "ov.h"
58 #include "ovl.h"
59 #include "utils.h"
60 
61 // Programming Note: There are two very different error functions used
62 // in the stream code. When invoked with "error (...)" the member
63 // function from octave_stream or octave_base_stream is called. This
64 // function sets the error state on the stream AND returns control to
65 // the caller. The caller must then return a value at the end of the
66 // function. When invoked with "::error (...)" the exception-based
67 // error function from error.h is used. This function will throw an
68 // exception and not return control to the caller. BE CAREFUL and
69 // invoke the correct error function!
70 
71 // Possible values for conv_err:
72 //
73 // 1 : not a real scalar
74 // 2 : value is NaN
75 // 3 : value is not an integer
76 
77 static int
78 convert_to_valid_int (const octave_value& tc, int& conv_err)
79 {
80  conv_err = 0;
81 
82  int retval = 0;
83 
84  double dval = 0.0;
85 
86  try
87  {
88  dval = tc.double_value ();
89  }
90  catch (const octave::execution_exception&)
91  {
93 
94  conv_err = 1;
95  }
96 
97  if (! conv_err)
98  {
99  if (! lo_ieee_isnan (dval))
100  {
101  int ival = octave::math::nint (dval);
102 
103  if (ival == dval)
104  retval = ival;
105  else
106  conv_err = 3;
107  }
108  else
109  conv_err = 2;
110  }
111 
112  return retval;
113 }
114 
115 static octave_idx_type
116 get_size (double d, const std::string& who)
117 {
118  octave_idx_type retval = -1;
119 
120  if (lo_ieee_isnan (d))
121  ::error ("%s: NaN is invalid as size specification", who.c_str ());
122 
123  if (octave::math::isinf (d))
124  retval = -1;
125  else
126  {
127  if (d < 0.0)
128  ::error ("%s: negative value invalid as size specification",
129  who.c_str ());
130 
132  ::error ("%s: dimension too large for Octave's index type",
133  who.c_str ());
134 
135  retval = octave::math::nint_big (d);
136  }
137 
138  return retval;
139 }
140 
141 static void
143  bool& one_elt_size_spec, const std::string& who)
144 {
145  nr = -1;
146  nc = -1;
147 
148  one_elt_size_spec = false;
149 
150  double dnr = -1.0;
151  double dnc = -1.0;
152 
153  octave_idx_type sz_len = size.numel ();
154 
155  if (sz_len == 1)
156  {
157  one_elt_size_spec = true;
158 
159  dnr = size(0);
160 
161  dnc = (dnr == 0.0) ? 0.0 : 1.0;
162  }
163  else if (sz_len == 2)
164  {
165  dnr = size(0);
166 
167  if (octave::math::isinf (dnr))
168  ::error ("%s: invalid size specification", who.c_str ());
169 
170  dnc = size(1);
171  }
172  else
173  ::error ("%s: invalid size specification", who.c_str ());
174 
175  nr = get_size (dnr, who);
176 
177  if (dnc >= 0.0)
178  nc = get_size (dnc, who);
179 }
180 
181 class
183 {
184 public:
185 
187  {
188  whitespace_conversion = 1,
189  literal_conversion = 2,
190  null = 3
191  };
192 
193  scanf_format_elt (const char *txt = 0, int w = 0, bool d = false,
194  char typ = '\0', char mod = '\0',
195  const std::string& ch_class = "")
196  : text (strsave (txt)), width (w), discard (d), type (typ),
197  modifier (mod), char_class (ch_class)
198  { }
199 
201  : text (strsave (e.text)), width (e.width), discard (e.discard),
202  type (e.type), modifier (e.modifier), char_class (e.char_class)
203  { }
204 
205  scanf_format_elt& operator = (const scanf_format_elt& e)
206  {
207  if (this != &e)
208  {
209  text = strsave (e.text);
210  width = e.width;
211  discard = e.discard;
212  type = e.type;
213  modifier = e.modifier;
214  char_class = e.char_class;
215  }
216 
217  return *this;
218  }
219 
220  ~scanf_format_elt (void) { delete [] text; }
221 
222  // The C-style format string.
223  const char *text;
224 
225  // The maximum field width.
226  int width;
227 
228  // TRUE if we are not storing the result of this conversion.
229  bool discard;
230 
231  // Type of conversion -- 'd', 'i', 'o', 'u', 'x', 'e', 'f', 'g',
232  // 'c', 's', 'p', '%', or '['.
233  char type;
234 
235  // A length modifier -- 'h', 'l', or 'L'.
236  char modifier;
237 
238  // The class of characters in a '[' format.
240 };
241 
242 class
244 {
245 public:
246 
247  scanf_format_list (const std::string& fmt = "");
248 
249  ~scanf_format_list (void);
250 
251  octave_idx_type num_conversions (void) { return nconv; }
252 
253  // The length can be different than the number of conversions.
254  // For example, "x %d y %d z" has 2 conversions but the length of
255  // the list is 3 because of the characters that appear after the
256  // last conversion.
257 
258  size_t length (void) const { return fmt_elts.size (); }
259 
260  const scanf_format_elt *first (void)
261  {
262  curr_idx = 0;
263  return current ();
264  }
265 
266  const scanf_format_elt *current (void) const
267  {
268  return length () > 0 ? fmt_elts[curr_idx] : 0;
269  }
270 
271  const scanf_format_elt *next (bool cycle = true)
272  {
273  static scanf_format_elt dummy
274  (0, 0, false, scanf_format_elt::null, '\0', "");
275 
276  curr_idx++;
277 
278  if (curr_idx >= length ())
279  {
280  if (cycle)
281  curr_idx = 0;
282  else
283  return &dummy;
284  }
285 
286  return current ();
287  }
288 
289  void printme (void) const;
290 
291  bool ok (void) const { return (nconv >= 0); }
292 
293  operator bool () const { return ok (); }
294 
295  bool all_character_conversions (void);
296 
297  bool all_numeric_conversions (void);
298 
299 private:
300 
301  // Number of conversions specified by this format string, or -1 if
302  // invalid conversions have been found.
304 
305  // Index to current element;
306  size_t curr_idx;
307 
308  // List of format elements.
309  std::deque<scanf_format_elt*> fmt_elts;
310 
311  // Temporary buffer.
312  std::ostringstream buf;
313 
314  void add_elt_to_list (int width, bool discard, char type, char modifier,
315  const std::string& char_class = "");
316 
317  void process_conversion (const std::string& s, size_t& i, size_t n,
318  int& width, bool& discard, char& type,
319  char& modifier);
320 
321  int finish_conversion (const std::string& s, size_t& i, size_t n,
322  int& width, bool discard, char& type,
323  char modifier);
324  // No copying!
325 
327 
328  scanf_format_list& operator = (const scanf_format_list&);
329 };
330 
332  : nconv (0), curr_idx (0), fmt_elts (), buf ()
333 {
334  size_t n = s.length ();
335 
336  size_t i = 0;
337 
338  int width = 0;
339  bool discard = false;
340  char modifier = '\0';
341  char type = '\0';
342 
343  bool have_more = true;
344 
345  while (i < n)
346  {
347  have_more = true;
348 
349  if (s[i] == '%')
350  {
351  // Process percent-escape conversion type.
352 
353  process_conversion (s, i, n, width, discard, type, modifier);
354 
355  have_more = (buf.tellp () != 0);
356  }
357  else if (isspace (s[i]))
358  {
360 
361  width = 0;
362  discard = false;
363  modifier = '\0';
364  buf << " ";
365 
366  while (++i < n && isspace (s[i]))
367  ; // skip whitespace
368 
369  add_elt_to_list (width, discard, type, modifier);
370 
371  have_more = false;
372  }
373  else
374  {
376 
377  width = 0;
378  discard = false;
379  modifier = '\0';
380 
381  while (i < n && ! isspace (s[i]) && s[i] != '%')
382  buf << s[i++];
383 
384  add_elt_to_list (width, discard, type, modifier);
385 
386  have_more = false;
387  }
388 
389  if (nconv < 0)
390  {
391  have_more = false;
392  break;
393  }
394  }
395 
396  if (have_more)
397  add_elt_to_list (width, discard, type, modifier);
398 
399  buf.clear ();
400  buf.str ("");
401 }
402 
404 {
405  size_t n = fmt_elts.size ();
406 
407  for (size_t i = 0; i < n; i++)
408  {
409  scanf_format_elt *elt = fmt_elts[i];
410  delete elt;
411  }
412 }
413 
414 void
415 scanf_format_list::add_elt_to_list (int width, bool discard, char type,
416  char modifier,
417  const std::string& char_class)
418 {
419  std::string text = buf.str ();
420 
421  if (! text.empty ())
422  {
423  scanf_format_elt *elt
424  = new scanf_format_elt (text.c_str (), width, discard, type,
425  modifier, char_class);
426 
427  fmt_elts.push_back (elt);
428  }
429 
430  buf.clear ();
431  buf.str ("");
432 }
433 
434 static std::string
436 {
438 
439  size_t len = s.length ();
440 
441  size_t i = 0;
442 
443  while (i < len)
444  {
445  unsigned char c = s[i++];
446 
447  if (c == '-' && i > 1 && i < len
448  && ( static_cast<unsigned char> (s[i-2])
449  <= static_cast<unsigned char> (s[i])))
450  {
451  // Add all characters from the range except the first (we
452  // already added it below).
453 
454  for (c = s[i-2]+1; c < s[i]; c++)
455  retval += c;
456  }
457  else
458  {
459  // Add the character to the class. Only add '-' if it is
460  // the last character in the class.
461 
462  if (c != '-' || i == len)
463  retval += c;
464  }
465  }
466 
467  return retval;
468 }
469 
470 void
472  size_t n, int& width, bool& discard,
473  char& type, char& modifier)
474 {
475  width = 0;
476  discard = false;
477  modifier = '\0';
478  type = '\0';
479 
480  buf << s[i++];
481 
482  bool have_width = false;
483 
484  while (i < n)
485  {
486  switch (s[i])
487  {
488  case '*':
489  if (discard)
490  nconv = -1;
491  else
492  {
493  discard = true;
494  buf << s[i++];
495  }
496  break;
497 
498  case '0': case '1': case '2': case '3': case '4':
499  case '5': case '6': case '7': case '8': case '9':
500  if (have_width)
501  nconv = -1;
502  else
503  {
504  char c = s[i++];
505  width = 10 * width + c - '0';
506  have_width = true;
507  buf << c;
508  while (i < n && isdigit (s[i]))
509  {
510  c = s[i++];
511  width = 10 * width + c - '0';
512  buf << c;
513  }
514  }
515  break;
516 
517  case 'h': case 'l': case 'L':
518  if (modifier != '\0')
519  nconv = -1;
520  else
521  modifier = s[i++];
522  break;
523 
524  case 'd': case 'i': case 'o': case 'u': case 'x':
525  if (modifier == 'L')
526  {
527  nconv = -1;
528  break;
529  }
530  goto fini;
531 
532  case 'e': case 'f': case 'g':
533  if (modifier == 'h')
534  {
535  nconv = -1;
536  break;
537  }
538 
539  // No float or long double conversions, thanks.
540  buf << 'l';
541 
542  goto fini;
543 
544  case 'c': case 's': case 'p': case '%': case '[':
545  if (modifier != '\0')
546  {
547  nconv = -1;
548  break;
549  }
550  goto fini;
551 
552  fini:
553  {
554  if (finish_conversion (s, i, n, width, discard,
555  type, modifier) == 0)
556  return;
557  }
558  break;
559 
560  default:
561  nconv = -1;
562  break;
563  }
564 
565  if (nconv < 0)
566  break;
567  }
568 
569  nconv = -1;
570 }
571 
572 int
574  size_t n, int& width, bool discard,
575  char& type, char modifier)
576 {
577  int retval = 0;
578 
579  std::string char_class;
580 
581  size_t beg_idx = std::string::npos;
582  size_t end_idx = std::string::npos;
583 
584  if (s[i] == '%')
585  {
586  type = '%';
587  buf << s[i++];
588  }
589  else
590  {
591  type = s[i];
592 
593  if (s[i] == '[')
594  {
595  buf << s[i++];
596 
597  if (i < n)
598  {
599  beg_idx = i;
600 
601  if (s[i] == '^')
602  {
603  type = '^';
604  buf << s[i++];
605 
606  if (i < n)
607  {
608  beg_idx = i;
609 
610  if (s[i] == ']')
611  buf << s[i++];
612  }
613  }
614  else if (s[i] == ']')
615  buf << s[i++];
616  }
617 
618  while (i < n && s[i] != ']')
619  buf << s[i++];
620 
621  if (i < n && s[i] == ']')
622  {
623  end_idx = i-1;
624  buf << s[i++];
625  }
626 
627  if (s[i-1] != ']')
628  retval = nconv = -1;
629  }
630  else
631  buf << s[i++];
632 
633  nconv++;
634  }
635 
636  if (nconv >= 0)
637  {
638  if (beg_idx != std::string::npos && end_idx != std::string::npos)
639  char_class = expand_char_class (s.substr (beg_idx,
640  end_idx - beg_idx + 1));
641 
642  add_elt_to_list (width, discard, type, modifier, char_class);
643  }
644 
645  return retval;
646 }
647 
648 void
650 {
651  size_t n = fmt_elts.size ();
652 
653  for (size_t i = 0; i < n; i++)
654  {
655  scanf_format_elt *elt = fmt_elts[i];
656 
657  std::cerr
658  << "width: " << elt->width << "\n"
659  << "discard: " << elt->discard << "\n"
660  << "type: ";
661 
663  std::cerr << "literal text\n";
665  std::cerr << "whitespace\n";
666  else
667  std::cerr << elt->type << "\n";
668 
669  std::cerr
670  << "modifier: " << elt->modifier << "\n"
671  << "char_class: '" << undo_string_escapes (elt->char_class) << "'\n"
672  << "text: '" << undo_string_escapes (elt->text) << "'\n\n";
673  }
674 }
675 
676 bool
678 {
679  size_t n = fmt_elts.size ();
680 
681  if (n > 0)
682  {
683  for (size_t i = 0; i < n; i++)
684  {
685  scanf_format_elt *elt = fmt_elts[i];
686 
687  switch (elt->type)
688  {
689  case 'c': case 's': case '%': case '[': case '^':
692  break;
693 
694  default:
695  return false;
696  break;
697  }
698  }
699 
700  return true;
701  }
702  else
703  return false;
704 }
705 
706 bool
708 {
709  size_t n = fmt_elts.size ();
710 
711  if (n > 0)
712  {
713  for (size_t i = 0; i < n; i++)
714  {
715  scanf_format_elt *elt = fmt_elts[i];
716 
717  switch (elt->type)
718  {
719  case 'd': case 'i': case 'o': case 'u': case 'x':
720  case 'e': case 'f': case 'g':
721  break;
722 
723  default:
724  return false;
725  break;
726  }
727  }
728 
729  return true;
730  }
731  else
732  return false;
733 }
734 
735 class
737 {
738 public:
739 
740  printf_format_elt (const char *txt = 0, int n = 0, int w = -1,
741  int p = -1, const std::string& f = "",
742  char typ = '\0', char mod = '\0')
743  : text (strsave (txt)), args (n), fw (w), prec (p), flags (f),
744  type (typ), modifier (mod)
745  { }
746 
748  : text (strsave (e.text)), args (e.args), fw (e.fw), prec (e.prec),
749  flags (e.flags), type (e.type), modifier (e.modifier)
750  { }
751 
752  printf_format_elt& operator = (const printf_format_elt& e)
753  {
754  if (this != &e)
755  {
756  text = strsave (e.text);
757  args = e.args;
758  fw = e.fw;
759  prec = e.prec;
760  flags = e.flags;
761  type = e.type;
762  modifier = e.modifier;
763  }
764 
765  return *this;
766  }
767 
768  ~printf_format_elt (void) { delete [] text; }
769 
770  // The C-style format string.
771  const char *text;
772 
773  // How many args do we expect to consume?
774  int args;
775 
776  // Field width.
777  int fw;
778 
779  // Precision.
780  int prec;
781 
782  // Flags -- '-', '+', ' ', '0', or '#'.
784 
785  // Type of conversion -- 'd', 'i', 'o', 'x', 'X', 'u', 'c', 's',
786  // 'f', 'e', 'E', 'g', 'G', 'p', or '%'
787  char type;
788 
789  // A length modifier -- 'h', 'l', or 'L'.
790  char modifier;
791 };
792 
793 class
795 {
796 public:
797 
798  printf_format_list (const std::string& fmt = "");
799 
800  ~printf_format_list (void);
801 
802  octave_idx_type num_conversions (void) { return nconv; }
803 
804  const printf_format_elt *first (void)
805  {
806  curr_idx = 0;
807  return current ();
808  }
809 
810  const printf_format_elt *current (void) const
811  {
812  return length () > 0 ? fmt_elts[curr_idx] : 0;
813  }
814 
815  size_t length (void) const { return fmt_elts.size (); }
816 
817  const printf_format_elt *next (bool cycle = true)
818  {
819  curr_idx++;
820 
821  if (curr_idx >= length ())
822  {
823  if (cycle)
824  curr_idx = 0;
825  else
826  return 0;
827  }
828 
829  return current ();
830  }
831 
832  bool last_elt_p (void) { return (curr_idx + 1 == length ()); }
833 
834  void printme (void) const;
835 
836  bool ok (void) const { return (nconv >= 0); }
837 
838  operator bool () const { return ok (); }
839 
840 private:
841 
842  // Number of conversions specified by this format string, or -1 if
843  // invalid conversions have been found.
845 
846  // Index to current element;
847  size_t curr_idx;
848 
849  // List of format elements.
850  std::deque<printf_format_elt*> fmt_elts;
851 
852  // Temporary buffer.
853  std::ostringstream buf;
854 
855  void add_elt_to_list (int args, const std::string& flags, int fw,
856  int prec, char type, char modifier);
857 
858  void process_conversion (const std::string& s, size_t& i, size_t n,
859  int& args, std::string& flags, int& fw,
860  int& prec, char& modifier, char& type);
861 
862  void finish_conversion (const std::string& s, size_t& i, int args,
863  const std::string& flags, int fw, int prec,
864  char modifier, char& type);
865 
866  // No copying!
867 
869 
870  printf_format_list& operator = (const printf_format_list&);
871 };
872 
874  : nconv (0), curr_idx (0), fmt_elts (), buf ()
875 {
876  size_t n = s.length ();
877 
878  size_t i = 0;
879 
880  int args = 0;
881  std::string flags;
882  int fw = -1;
883  int prec = -1;
884  char modifier = '\0';
885  char type = '\0';
886 
887  bool have_more = true;
888  bool empty_buf = true;
889 
890  if (n == 0)
891  {
892  printf_format_elt *elt
893  = new printf_format_elt ("", args, fw, prec, flags, type, modifier);
894 
895  fmt_elts.push_back (elt);
896  }
897  else
898  {
899  while (i < n)
900  {
901  have_more = true;
902 
903  empty_buf = (buf.tellp () == 0);
904 
905  switch (s[i])
906  {
907  case '%':
908  {
909  if (empty_buf)
910  {
911  process_conversion (s, i, n, args, flags, fw, prec,
912  type, modifier);
913 
914  // If there is nothing in the buffer, then
915  // add_elt_to_list must have just been called, so we
916  // are already done with the current element and we
917  // don't need to call add_elt_to_list if this is our
918  // last trip through the loop.
919 
920  have_more = (buf.tellp () != 0);
921  }
922  else
923  add_elt_to_list (args, flags, fw, prec, type, modifier);
924  }
925  break;
926 
927  default:
928  {
929  args = 0;
930  flags = "";
931  fw = -1;
932  prec = -1;
933  modifier = '\0';
934  type = '\0';
935  buf << s[i++];
936  empty_buf = false;
937  }
938  break;
939  }
940 
941  if (nconv < 0)
942  {
943  have_more = false;
944  break;
945  }
946  }
947 
948  if (have_more)
949  add_elt_to_list (args, flags, fw, prec, type, modifier);
950 
951  buf.clear ();
952  buf.str ("");
953  }
954 }
955 
957 {
958  size_t n = fmt_elts.size ();
959 
960  for (size_t i = 0; i < n; i++)
961  {
962  printf_format_elt *elt = fmt_elts[i];
963  delete elt;
964  }
965 }
966 
967 void
969  int fw, int prec, char type,
970  char modifier)
971 {
972  std::string text = buf.str ();
973 
974  if (! text.empty ())
975  {
976  printf_format_elt *elt
977  = new printf_format_elt (text.c_str (), args, fw, prec, flags,
978  type, modifier);
979 
980  fmt_elts.push_back (elt);
981  }
982 
983  buf.clear ();
984  buf.str ("");
985 }
986 
987 void
989  size_t n, int& args,
990  std::string& flags, int& fw,
991  int& prec, char& modifier,
992  char& type)
993 {
994  args = 0;
995  flags = "";
996  fw = -1;
997  prec = -1;
998  modifier = '\0';
999  type = '\0';
1000 
1001  buf << s[i++];
1002 
1003  bool nxt = false;
1004 
1005  while (i < n)
1006  {
1007  switch (s[i])
1008  {
1009  case '-': case '+': case ' ': case '0': case '#':
1010  flags += s[i];
1011  buf << s[i++];
1012  break;
1013 
1014  default:
1015  nxt = true;
1016  break;
1017  }
1018 
1019  if (nxt)
1020  break;
1021  }
1022 
1023  if (i < n)
1024  {
1025  if (s[i] == '*')
1026  {
1027  fw = -2;
1028  args++;
1029  buf << s[i++];
1030  }
1031  else
1032  {
1033  if (isdigit (s[i]))
1034  {
1035  int nn = 0;
1036  std::string tmp = s.substr (i);
1037  sscanf (tmp.c_str (), "%d%n", &fw, &nn);
1038  }
1039 
1040  while (i < n && isdigit (s[i]))
1041  buf << s[i++];
1042  }
1043  }
1044 
1045  if (i < n && s[i] == '.')
1046  {
1047  // nothing before the . means 0.
1048  if (fw == -1)
1049  fw = 0;
1050 
1051  // . followed by nothing is 0.
1052  prec = 0;
1053 
1054  buf << s[i++];
1055 
1056  if (i < n)
1057  {
1058  if (s[i] == '*')
1059  {
1060  prec = -2;
1061  args++;
1062  buf << s[i++];
1063  }
1064  else
1065  {
1066  if (isdigit (s[i]))
1067  {
1068  int nn = 0;
1069  std::string tmp = s.substr (i);
1070  sscanf (tmp.c_str (), "%d%n", &prec, &nn);
1071  }
1072 
1073  while (i < n && isdigit (s[i]))
1074  buf << s[i++];
1075  }
1076  }
1077  }
1078 
1079  if (i < n)
1080  {
1081  // Accept and record modifier, but don't place it in the format
1082  // item text. All integer conversions are handled as 64-bit
1083  // integers.
1084 
1085  switch (s[i])
1086  {
1087  case 'h': case 'l': case 'L':
1088  modifier = s[i++];
1089  break;
1090 
1091  default:
1092  break;
1093  }
1094  }
1095 
1096  if (i < n)
1097  finish_conversion (s, i, args, flags, fw, prec, modifier, type);
1098  else
1099  nconv = -1;
1100 }
1101 
1102 void
1104  int args, const std::string& flags,
1105  int fw, int prec, char modifier,
1106  char& type)
1107 {
1108  switch (s[i])
1109  {
1110  case 'd': case 'i': case 'o': case 'x': case 'X':
1111  case 'u': case 'c':
1112  if (modifier == 'L')
1113  {
1114  nconv = -1;
1115  break;
1116  }
1117  goto fini;
1118 
1119  case 'f': case 'e': case 'E': case 'g': case 'G':
1120  if (modifier == 'h' || modifier == 'l')
1121  {
1122  nconv = -1;
1123  break;
1124  }
1125  goto fini;
1126 
1127  case 's': case 'p': case '%':
1128  if (modifier != '\0')
1129  {
1130  nconv = -1;
1131  break;
1132  }
1133  goto fini;
1134 
1135  fini:
1136 
1137  type = s[i];
1138 
1139  buf << s[i++];
1140 
1141  if (type != '%' || args != 0)
1142  nconv++;
1143 
1144  if (type != '%')
1145  args++;
1146 
1147  add_elt_to_list (args, flags, fw, prec, type, modifier);
1148 
1149  break;
1150 
1151  default:
1152  nconv = -1;
1153  break;
1154  }
1155 }
1156 
1157 void
1159 {
1160  size_t n = fmt_elts.size ();
1161 
1162  for (size_t i = 0; i < n; i++)
1163  {
1164  printf_format_elt *elt = fmt_elts[i];
1165 
1166  std::cerr
1167  << "args: " << elt->args << "\n"
1168  << "flags: '" << elt->flags << "'\n"
1169  << "width: " << elt->fw << "\n"
1170  << "prec: " << elt->prec << "\n"
1171  << "type: '" << elt->type << "'\n"
1172  << "modifier: '" << elt->modifier << "'\n"
1173  << "text: '" << undo_string_escapes (elt->text) << "'\n\n";
1174  }
1175 }
1176 
1177 // Calculate x^n. Used for ...e+nn so that, for example, 1e2 is
1178 // exactly 100 and 5e-1 is 1/2
1179 
1180 static double
1181 pown (double x, unsigned int n)
1182 {
1183  double retval = 1;
1184 
1185  for (unsigned int d = n; d; d >>= 1)
1186  {
1187  if (d & 1)
1188  retval *= x;
1189  x *= x;
1190  }
1191 
1192  return retval;
1193 }
1194 
1195 static Cell
1197 {
1198  Cell retval (dim_vector (1, 2));
1199 
1200  retval(0) = Cell (octave_value ("inf"));
1201  retval(1) = Cell (octave_value ("nan"));
1202 
1203  return retval;
1204 }
1205 
1206 namespace octave
1207 {
1208  // Delimited stream, optimized to read strings of characters separated
1209  // by single-character delimiters.
1210  //
1211  // The reason behind this class is that octstream doesn't provide
1212  // seek/tell, but the opportunity has been taken to optimise for the
1213  // textscan workload.
1214  //
1215  // The function reads chunks into a 4kiB buffer, and marks where the
1216  // last delimiter occurs. Reads up to this delimiter can be fast.
1217  // After that last delimiter, the remaining text is moved to the front
1218  // of the buffer and the buffer is refilled. This also allows cheap
1219  // seek and tell operations within a "fast read" block.
1220 
1221  class
1223  {
1224  public:
1225 
1226  delimited_stream (std::istream& is, const std::string& delimiters,
1227  int longest_lookahead, octave_idx_type bsize = 4096);
1228 
1229  delimited_stream (std::istream& is, const delimited_stream& ds);
1230 
1231  ~delimited_stream (void);
1232 
1233  // Called when optimized sequence of get is finished. Ensures that
1234  // there is a remaining delimiter in buf, or loads more data in.
1235  void field_done (void)
1236  {
1237  if (idx >= last)
1238  refresh_buf ();
1239  }
1240 
1241  // Load new data into buffer, and set eob, last, idx.
1242  // Return EOF at end of file, 0 otherwise.
1243  int refresh_buf (void);
1244 
1245  // Get a character, relying on caller to call field_done if
1246  // a delimiter has been reached.
1247  int get (void)
1248  {
1249  if (delimited)
1250  return eof () ? std::istream::traits_type::eof () : *idx++;
1251  else
1252  return get_undelim ();
1253  }
1254 
1255  // Get a character, checking for underrun of the buffer.
1256  int get_undelim (void);
1257 
1258  // Read character that will be got by the next get.
1259  int peek (void) { return eof () ? std::istream::traits_type::eof () : *idx; }
1260 
1261  // Read character that will be got by the next get.
1262  int peek_undelim (void);
1263 
1264  // Undo a 'get' or 'get_undelim'. It is the caller's responsibility
1265  // to avoid overflow by calling putbacks only for a character got by
1266  // get() or get_undelim(), with no intervening
1267  // get, get_delim, field_done, refresh_buf, getline, read or seekg.
1268  void putback (char /*ch*/ = 0) { if (! eof ()) --idx; }
1269 
1270  int getline (std::string& dest, char delim);
1271 
1272  // int skipline (char delim);
1273 
1274  char *read (char *buffer, int size, char* &new_start);
1275 
1276  // Return a position suitable to "seekg", valid only within this
1277  // block between calls to field_done.
1278  char *tellg (void) { return idx; }
1279 
1280  void seekg (char *old_idx) { idx = old_idx; }
1281 
1282  bool eof (void)
1283  {
1284  return (eob == buf && i_stream.eof ()) || (flags & std::ios_base::eofbit);
1285  }
1286 
1287  operator const void* (void) { return (! eof () && ! flags) ? this : 0; }
1288 
1289  bool fail (void) { return flags & std::ios_base::failbit; }
1290 
1291  std::ios_base::iostate rdstate (void) { return flags; }
1292 
1293  void setstate (std::ios_base::iostate m) { flags = flags | m; }
1294 
1295  void clear (std::ios_base::iostate m
1296  = (std::ios_base::eofbit & ~std::ios_base::eofbit))
1297  {
1298  flags = flags & m;
1299  }
1300 
1301  // Report if any characters have been consumed.
1302  // (get, read, etc. not cancelled by putback or seekg)
1303 
1304  void progress_benchmark (void) { progress_marker = idx; }
1305 
1306  bool no_progress (void) { return progress_marker == idx; }
1307 
1308  private:
1309 
1310  // Number of characters to read from the file at once.
1311  int bufsize;
1312 
1313  // Stream to read from.
1314  std::istream& i_stream;
1315 
1316  // Temporary storage for a "chunk" of data.
1317  char *buf;
1318 
1319  // Current read pointer.
1320  char *idx;
1321 
1322  // Location of last delimiter in the buffer at buf (undefined if
1323  // delimited is false).
1324  char *last;
1325 
1326  // Position after last character in buffer.
1327  char *eob;
1328 
1329  // True if there is delimiter in the bufer after idx.
1331 
1332  // Longest lookahead required.
1333  int longest;
1334 
1335  // Sequence of single-character delimiters.
1337 
1338  // Position of start of buf in original stream.
1339  std::streampos buf_in_file;
1340 
1341  // Marker to see if a read consumes any characters.
1343 
1344  std::ios_base::iostate flags;
1345 
1346  // No copying!
1347 
1349 
1350  delimited_stream& operator = (const delimited_stream&);
1351  };
1352 
1353  // Create a delimited stream, reading from is, with delimiters delims,
1354  // and allowing reading of up to tellg + longest_lookeahead. When is
1355  // is at EOF, lookahead may be padded by ASCII nuls.
1356 
1358  const std::string& delimiters,
1359  int longest_lookahead,
1360  octave_idx_type bsize)
1361  : bufsize (bsize), i_stream (is), longest (longest_lookahead),
1362  delims (delimiters),
1363  flags (std::ios::failbit & ~std::ios::failbit) // can't cast 0
1364  {
1365  buf = new char[bufsize];
1366  eob = buf + bufsize;
1367  idx = eob; // refresh_buf shouldn't try to copy old data
1368  progress_marker = idx;
1369  refresh_buf (); // load the first batch of data
1370  }
1371 
1372  // Used to create a stream from a strstream from data read from a dstr.
1373  // FIXME: Find a more efficient approach. Perhaps derived dstr
1375  const delimited_stream& ds)
1376  : bufsize (ds.bufsize), i_stream (is), longest (ds.longest),
1377  delims (ds.delims),
1378  flags (std::ios::failbit & ~std::ios::failbit) // can't cast 0
1379  {
1380  buf = new char[bufsize];
1381  eob = buf + bufsize;
1382  idx = eob; // refresh_buf shouldn't try to copy old data
1383  progress_marker = idx;
1384  refresh_buf (); // load the first batch of data
1385  }
1386 
1388  {
1389  // Seek to the correct position in i_stream.
1390  if (! eof ())
1391  {
1392  i_stream.clear ();
1393  i_stream.seekg (buf_in_file);
1394  i_stream.read (buf, idx - buf);
1395  }
1396 
1397  delete [] buf;
1398  }
1399 
1400  // Read a character from the buffer, refilling the buffer from the file
1401  // if necessary.
1402 
1403  int
1405  {
1406  int retval;
1407  if (eof ())
1408  {
1409  setstate (std::ios_base::failbit);
1410  return std::istream::traits_type::eof ();
1411  }
1412 
1413  if (idx < eob)
1414  retval = *idx++;
1415  else
1416  {
1417  refresh_buf ();
1418 
1419  if (eof ())
1420  {
1421  setstate (std::ios_base::eofbit);
1422  retval = std::istream::traits_type::eof ();
1423  }
1424  else
1425  retval = *idx++;
1426  }
1427 
1428  if (idx >= last)
1429  delimited = false;
1430 
1431  return retval;
1432  }
1433 
1434  // Return the next character to be read without incrementing the
1435  // pointer, refilling the buffer from the file if necessary.
1436 
1437  int
1439  {
1440  int retval = get_undelim ();
1441  putback ();
1442 
1443  return retval;
1444  }
1445 
1446  // Copy remaining unprocessed data to the start of the buffer and load
1447  // new data to fill it. Return EOF if the file is at EOF before
1448  // reading any data and all of the data that has been read has been
1449  // processed.
1450 
1451  int
1453  {
1454  if (eof ())
1455  return std::istream::traits_type::eof ();
1456 
1457  int retval;
1458 
1459  if (eob < idx)
1460  idx = eob;
1461 
1462  size_t old_remaining = eob - idx;
1463 
1464  octave_quit (); // allow ctrl-C
1465 
1466  if (old_remaining > 0)
1467  {
1468  buf_in_file += (idx - buf);
1469  memmove (buf, idx, old_remaining);
1470  }
1471 
1472  progress_marker -= idx - buf; // where original idx would have been
1473  idx = buf;
1474 
1475  int gcount; // chars read
1476  if (! i_stream.eof ())
1477  {
1478  buf_in_file = i_stream.tellg (); // record for destructor
1479  i_stream.read (buf + old_remaining, bufsize - old_remaining);
1480  gcount = i_stream.gcount ();
1481  }
1482  else
1483  gcount = 0;
1484 
1485  eob = buf + old_remaining + gcount;
1486  last = eob;
1487  if (gcount == 0)
1488  {
1489  delimited = false;
1490 
1491  if (eob != buf) // no more data in file, but still some to go
1492  retval = 0;
1493  else
1494  // file and buffer are both done.
1495  retval = std::istream::traits_type::eof ();
1496  }
1497  else
1498  {
1499  delimited = true;
1500 
1501  for (last = eob - longest; last - buf >= 0; last--)
1502  {
1503  if (delims.find (*last) != std::string::npos)
1504  break;
1505  }
1506 
1507  if (last < buf)
1508  delimited = false;
1509 
1510  retval = 0;
1511  }
1512 
1513  // Ensure fast peek doesn't give valid char
1514  if (retval == std::istream::traits_type::eof ())
1515  *idx = '\0'; // FIXME: check that no TreatAsEmpty etc starts w. \0?
1516 
1517  return retval;
1518  }
1519 
1520  // Return a pointer to a block of data of size size, assuming that a
1521  // sufficiently large buffer is available in buffer, if required.
1522  // If called when delimited == true, and size is no greater than
1523  // longest_lookahead then this will not call refresh_buf, so seekg
1524  // still works. Otherwise, seekg may be invalidated.
1525 
1526  char *
1527  delimited_stream::read (char *buffer, int size, char* &prior_tell)
1528  {
1529  char *retval;
1530 
1531  if (eob - idx > size)
1532  {
1533  retval = idx;
1534  idx += size;
1535  if (idx > last)
1536  delimited = false;
1537  }
1538  else
1539  {
1540  // If there was a tellg pointing to an earlier point than the current
1541  // read position, try to keep it in the active buffer.
1542  // In the current code, prior_tell==idx for each call,
1543  // so this is not necessary, just a precaution.
1544 
1545  if (eob - prior_tell + size < bufsize)
1546  {
1547  octave_idx_type gap = idx - prior_tell;
1548  idx = prior_tell;
1549  refresh_buf ();
1550  idx += gap;
1551  }
1552  else // can't keep the tellg in range. May skip some data.
1553  {
1554  refresh_buf ();
1555  }
1556 
1557  prior_tell = buf;
1558 
1559  if (eob - idx > size)
1560  {
1561  retval = idx;
1562  idx += size;
1563  if (idx > last)
1564  delimited = false;
1565  }
1566  else
1567  {
1568  if (size <= bufsize) // small read, but reached EOF
1569  {
1570  retval = idx;
1571  memset (eob, 0, size + (idx - buf));
1572  idx += size;
1573  }
1574  else // Reading more than the whole buf; return it in buffer
1575  {
1576  retval = buffer;
1577  // FIXME: read bufsize at a time
1578  int i;
1579  for (i = 0; i < size && ! eof (); i++)
1580  *buffer++ = get_undelim ();
1581  if (eof ())
1582  memset (buffer, 0, size - i);
1583  }
1584  }
1585  }
1586 
1587  return retval;
1588  }
1589 
1590  // Return in OUT an entire line, terminated by delim. On input, OUT
1591  // must have length at least 1.
1592 
1593  int
1595  {
1596  int len = out.length (), used = 0;
1597  int ch;
1598  while ((ch = get_undelim ()) != delim
1599  && ch != std::istream::traits_type::eof ())
1600  {
1601  out[used++] = ch;
1602  if (used == len)
1603  {
1604  len <<= 1;
1605  out.resize (len);
1606  }
1607  }
1608  out.resize (used);
1609  field_done ();
1610 
1611  return ch;
1612  }
1613 
1614  // A single conversion specifier, such as %f or %c.
1615 
1616  class
1618  {
1619  public:
1620 
1622  {
1623  whitespace_conversion = 1,
1624  literal_conversion = 2
1625  };
1626 
1627  textscan_format_elt (const std::string& txt, int w = 0, int p = -1,
1628  int bw = 0, bool dis = false, char typ = '\0',
1629  const std::string& ch_class = std::string ())
1630  : text (txt), width (w), prec (p), bitwidth (bw),
1631  char_class (ch_class), type (typ), discard (dis),
1632  numeric (typ == 'd' || typ == 'u' || type == 'f' || type == 'n')
1633  { }
1634 
1636  : text (e.text), width (e.width), prec (e.prec),
1637  bitwidth (e.bitwidth), char_class (e.char_class), type (e.type),
1638  discard (e.discard), numeric (e.numeric)
1639  { }
1640 
1642  {
1643  if (this != &e)
1644  {
1645  text = e.text;
1646  width = e.width;
1647  prec = e.prec;
1648  bitwidth = e.bitwidth;
1649  discard = e.discard;
1650  type = e.type;
1651  numeric = e.numeric;
1652  char_class = e.char_class;
1653  }
1654 
1655  return *this;
1656  }
1657 
1658  // The C-style format string.
1660 
1661  // The maximum field width.
1662  unsigned int width;
1663 
1664  // The maximum number of digits to read after the decimal in a
1665  // floating point conversion.
1666  int prec;
1667 
1668  // The size of the result. For integers, bitwidth may be 8, 16, 34,
1669  // or 64. For floating point values, bitwidth may be 32 or 64.
1671 
1672  // The class of characters in a `[' or `^' format.
1674 
1675  // Type of conversion
1676  // -- `d', `u', `f', `n', `s', `q', `c', `%', `C', `D', `[' or `^'.
1677  char type;
1678 
1679  // TRUE if we are not storing the result of this conversion.
1680  bool discard;
1681 
1682  // TRUE if the type is 'd', 'u', 'f', 'n'
1683  bool numeric;
1684  };
1685 
1686  // The (parsed) sequence of format specifiers.
1687 
1688  class textscan;
1689 
1690  class
1692  {
1693  public:
1694 
1695  textscan_format_list (const std::string& fmt = std::string (),
1696  const std::string& who = "textscan");
1697 
1698  ~textscan_format_list (void);
1699 
1700  octave_idx_type num_conversions (void) const { return nconv; }
1701 
1702  // The length can be different than the number of conversions.
1703  // For example, "x %d y %d z" has 2 conversions but the length of
1704  // the list is 3 because of the characters that appear after the
1705  // last conversion.
1706 
1707  size_t numel (void) const { return fmt_elts.size (); }
1708 
1710  {
1711  curr_idx = 0;
1712  return current ();
1713  }
1714 
1715  const textscan_format_elt *current (void) const
1716  {
1717  return numel () > 0 ? fmt_elts[curr_idx] : 0;
1718  }
1719 
1720  const textscan_format_elt *next (bool cycle = true)
1721  {
1722  curr_idx++;
1723 
1724  if (curr_idx >= numel ())
1725  {
1726  if (cycle)
1727  curr_idx = 0;
1728  else
1729  return 0;
1730  }
1731 
1732  return current ();
1733  }
1734 
1735  void printme (void) const;
1736 
1737  bool ok (void) const { return (nconv >= 0); }
1738 
1739  operator const void* (void) const { return ok () ? this : 0; }
1740 
1741  // What function name should be shown when reporting errors.
1743 
1744  // True if number of %f to be set from data file.
1746 
1747  // At least one conversion specifier is s,q,c, or [...].
1749 
1750  int read_first_row (delimited_stream& is, textscan& ts);
1751 
1752  std::list<octave_value> out_buf (void) const { return (output_container); }
1753 
1754  private:
1755 
1756  // Number of conversions specified by this format string, or -1 if
1757  // invalid conversions have been found.
1759 
1760  // Index to current element;
1761  size_t curr_idx;
1762 
1763  // List of format elements.
1764  std::deque<textscan_format_elt*> fmt_elts;
1765 
1766  // list holding column arrays of types specified by conversions
1767  std::list<octave_value> output_container;
1768 
1769  // Temporary buffer.
1770  std::ostringstream buf;
1771 
1772  void add_elt_to_list (unsigned int width, int prec, int bitwidth,
1773  octave_value val_type, bool discard,
1774  char type,
1775  const std::string& char_class = std::string ());
1776 
1777  void process_conversion (const std::string& s, size_t& i, size_t n);
1778 
1779  std::string parse_char_class (const std::string& pattern) const;
1780 
1781  int finish_conversion (const std::string& s, size_t& i, size_t n,
1782  unsigned int& width, int& prec, int& bitwidth,
1783  octave_value& val_type,
1784  bool discard, char& type);
1785  // No copying!
1786 
1788 
1789  textscan_format_list& operator = (const textscan_format_list&);
1790  };
1791 
1792  // Main class to implement textscan. Read data and parse it
1793  // according to a format.
1794  //
1795  // The calling sequence is
1796  //
1797  // textscan scanner ();
1798  // scanner.scan (...);
1799 
1800  class
1802  textscan
1803  {
1804  public:
1805 
1806  textscan (const std::string& who_arg = "textscan");
1807 
1808  ~textscan (void) { }
1809 
1810  octave_value scan (std::istream& isp, const std::string& fmt,
1811  octave_idx_type ntimes,
1812  const octave_value_list& options,
1813  octave_idx_type& read_count);
1814 
1815  private:
1816 
1817  friend class textscan_format_list;
1818 
1819  // What function name should be shown when reporting errors.
1821 
1823 
1824  // Three cases for delim_table and delim_list
1825  // 1. delim_table empty, delim_list empty: whitespace delimiters
1826  // 2. delim_table = look-up table of delim chars, delim_list empty.
1827  // 3. delim_table non-empty, delim_list = Cell array of delim strings
1828 
1830 
1831  // delim_table[i] == '\0' if i is not a delimiter.
1833 
1834  // String of delimiter characters.
1836 
1838 
1839  // How far ahead to look to detect an open comment.
1841 
1842  // First character of open comment.
1844 
1846 
1848 
1849  // 'inf' and 'nan' for formatted_double.
1851 
1852  // Array of strings of delimiters.
1854 
1855  // Longest delimiter.
1857 
1862 
1863  // Longest string to treat as "N/A".
1865 
1867 
1868  short eol1;
1869  short eol2;
1871 
1876 
1878 
1879  octave_value do_scan (std::istream& isp, textscan_format_list& fmt_list,
1880  octave_idx_type ntimes);
1881 
1882  void parse_options (const octave_value_list& args,
1883  textscan_format_list& fmt_list);
1884 
1885  int read_format_once (delimited_stream& isp, textscan_format_list& fmt_list,
1886  std::list<octave_value>& retval,
1887  Array<octave_idx_type> row, int& done_after);
1888 
1889  void scan_one (delimited_stream& is, const textscan_format_elt& fmt,
1891 
1892  // Methods to process a particular conversion specifier.
1893  double read_double (delimited_stream& is,
1894  const textscan_format_elt& fmt) const;
1895 
1896  void scan_complex (delimited_stream& is, const textscan_format_elt& fmt,
1897  Complex& val) const;
1898 
1899  int scan_bracket (delimited_stream& is, const std::string& pattern,
1900  std::string& val) const;
1901 
1902  int scan_caret (delimited_stream& is, const std::string& pattern,
1903  std::string& val) const;
1904 
1905  void scan_string (delimited_stream& is, const textscan_format_elt& fmt,
1906  std::string& val) const;
1907 
1908  void scan_cstring (delimited_stream& is, const textscan_format_elt& fmt,
1909  std::string& val) const;
1910 
1911  void scan_qstring (delimited_stream& is, const textscan_format_elt& fmt,
1912  std::string& val);
1913 
1914  // Helper methods.
1915  std::string read_until (delimited_stream& is, const Cell& delimiters,
1916  const std::string& ends) const;
1917 
1918  int lookahead (delimited_stream& is, const Cell& targets, int max_len,
1919  bool case_sensitive = true) const;
1920 
1921  bool match_literal (delimited_stream& isp, const textscan_format_elt& elem);
1922 
1923  int skip_whitespace (delimited_stream& is, bool EOLstop = false);
1924 
1925  int skip_delim (delimited_stream& is);
1926 
1927  bool is_delim (unsigned char ch) const
1928  {
1929  return ((delim_table.empty () && (isspace (ch) || ch == eol1 || ch == eol2))
1930  || delim_table[ch] != '\0');
1931  }
1932 
1933  bool isspace (unsigned int ch) const { return whitespace_table[ch & 0xff]; }
1934 
1935  // True if the only delimiter is whitespace.
1936  bool whitespace_delim (void) const { return delim_table.empty (); }
1937 
1938  // No copying!
1939 
1940  textscan (const textscan&);
1941 
1942  textscan& operator = (const textscan&);
1943  };
1944 
1946  const std::string& who_arg)
1947  : who (who_arg), set_from_first (false), has_string (false),
1948  nconv (0), curr_idx (0), fmt_elts (), buf ()
1949  {
1950  size_t n = s.length ();
1951 
1952  size_t i = 0;
1953 
1954  unsigned int width = -1; // Unspecified width = max (except %c)
1955  int prec = -1;
1956  int bitwidth = 0;
1957  bool discard = false;
1958  char type = '\0';
1959 
1960  bool have_more = true;
1961 
1962  if (s.empty ())
1963  {
1964  buf.clear ();
1965  buf.str ("");
1966 
1967  buf << "%f";
1968 
1969  bitwidth = 64;
1970  type = 'f';
1971  add_elt_to_list (width, prec, bitwidth, octave_value (NDArray ()),
1972  discard, type);
1973  have_more = false;
1974  set_from_first = true;
1975  nconv = 1;
1976  }
1977  else
1978  {
1979  set_from_first = false;
1980 
1981  while (i < n)
1982  {
1983  have_more = true;
1984 
1985  if (s[i] == '%' && (i+1 == n || s[i+1] != '%'))
1986  {
1987  // Process percent-escape conversion type.
1988 
1989  process_conversion (s, i, n);
1990 
1991  // If there is nothing in the buffer, then add_elt_to_list
1992  // must have just been called, so we are already done with
1993  // the current element and we don't need to call
1994  // add_elt_to_list if this is our last trip through the
1995  // loop.
1996 
1997  have_more = (buf.tellp () != 0);
1998  }
1999  else if (isspace (s[i]))
2000  {
2001  while (++i < n && isspace (s[i]))
2002  /* skip whitespace */;
2003 
2004  have_more = false;
2005  }
2006  else
2007  {
2009 
2010  width = 0;
2011  prec = -1;
2012  bitwidth = 0;
2013  discard = true;
2014 
2015  while (i < n && ! isspace (s[i])
2016  && (s[i] != '%' || (i+1 < n && s[i+1] == '%')))
2017  {
2018  if (s[i] == '%') // if double %, skip one
2019  i++;
2020  buf << s[i++];
2021  width++;
2022  }
2023 
2024  add_elt_to_list (width, prec, bitwidth, octave_value (),
2025  discard, type);
2026 
2027  have_more = false;
2028  }
2029 
2030  if (nconv < 0)
2031  {
2032  have_more = false;
2033  break;
2034  }
2035  }
2036  }
2037 
2038  if (have_more)
2039  add_elt_to_list (width, prec, bitwidth, octave_value (), discard, type);
2040 
2041  buf.clear ();
2042  buf.str ("");
2043  }
2044 
2046  {
2047  size_t n = numel ();
2048 
2049  for (size_t i = 0; i < n; i++)
2050  {
2051  textscan_format_elt *elt = fmt_elts[i];
2052  delete elt;
2053  }
2054  }
2055 
2056  void
2057  textscan_format_list::add_elt_to_list (unsigned int width, int prec,
2058  int bitwidth, octave_value val_type,
2059  bool discard, char type,
2060  const std::string& char_class)
2061  {
2062  std::string text = buf.str ();
2063 
2064  if (! text.empty ())
2065  {
2066  textscan_format_elt *elt
2067  = new textscan_format_elt (text, width, prec, bitwidth, discard, type,
2068  char_class);
2069 
2070  if (! discard)
2071  output_container.push_back (val_type);
2072 
2073  fmt_elts.push_back (elt);
2074  }
2075 
2076  buf.clear ();
2077  buf.str ("");
2078  }
2079 
2080  void
2082  size_t n)
2083  {
2084  unsigned width = 0;
2085  int prec = -1;
2086  int bitwidth = 0;
2087  bool discard = false;
2088  octave_value val_type;
2089  char type = '\0';
2090 
2091  buf << s[i++];
2092 
2093  bool have_width = false;
2094 
2095  while (i < n)
2096  {
2097  switch (s[i])
2098  {
2099  case '*':
2100  if (discard)
2101  nconv = -1;
2102  else
2103  {
2104  discard = true;
2105  buf << s[i++];
2106  }
2107  break;
2108 
2109  case '0': case '1': case '2': case '3': case '4':
2110  case '5': case '6': case '7': case '8': case '9':
2111  if (have_width)
2112  nconv = -1;
2113  else
2114  {
2115  char c = s[i++];
2116  width = width * 10 + c - '0';
2117  have_width = true;
2118  buf << c;
2119  while (i < n && isdigit (s[i]))
2120  {
2121  c = s[i++];
2122  width = width * 10 + c - '0';
2123  buf << c;
2124  }
2125 
2126  if (i < n && s[i] == '.')
2127  {
2128  buf << s[i++];
2129  prec = 0;
2130  while (i < n && isdigit (s[i]))
2131  {
2132  c = s[i++];
2133  prec = prec * 10 + c - '0';
2134  buf << c;
2135  }
2136  }
2137  }
2138  break;
2139 
2140  case 'd': case 'u':
2141  {
2142  bool done = true;
2143  buf << (type = s[i++]);
2144  if (i < n)
2145  {
2146  if (s[i] == '8')
2147  {
2148  bitwidth = 8;
2149  if (type == 'd')
2150  val_type = octave_value (int8NDArray ());
2151  else
2152  val_type = octave_value (uint8NDArray ());
2153  buf << s[i++];
2154  }
2155  else if (s[i] == '1' && i+1 < n && s[i+1] == '6')
2156  {
2157  bitwidth = 16;
2158  if (type == 'd')
2159  val_type = octave_value (int16NDArray ());
2160  else
2161  val_type = octave_value (uint16NDArray ());
2162  buf << s[i++];
2163  buf << s[i++];
2164  }
2165  else if (s[i] == '3' && i+1 < n && s[i+1] == '2')
2166  {
2167  done = false; // use default size below
2168  buf << s[i++];
2169  buf << s[i++];
2170  }
2171  else if (s[i] == '6' && i+1 < n && s[i+1] == '4')
2172  {
2173  bitwidth = 64;
2174  if (type == 'd')
2175  val_type = octave_value (int64NDArray ());
2176  else
2177  val_type = octave_value (uint64NDArray ());
2178  buf << s[i++];
2179  buf << s[i++];
2180  }
2181  else
2182  done = false;
2183  }
2184  else
2185  done = false;
2186 
2187  if (! done)
2188  {
2189  bitwidth = 32;
2190  if (type == 'd')
2191  val_type = octave_value (int32NDArray ());
2192  else
2193  val_type = octave_value (uint32NDArray ());
2194  }
2195  goto fini;
2196  }
2197 
2198  case 'f':
2199  buf << (type = s[i++]);
2200  bitwidth = 64;
2201  if (i < n)
2202  {
2203  if (s[i] == '3' && i+1 < n && s[i+1] == '2')
2204  {
2205  bitwidth = 32;
2206  val_type = octave_value (FloatNDArray ());
2207  buf << s[i++];
2208  buf << s[i++];
2209  }
2210  else if (s[i] == '6' && i+1 < n && s[i+1] == '4')
2211  {
2212  val_type = octave_value (NDArray ());
2213  buf << s[i++];
2214  buf << s[i++];
2215  }
2216  else
2217  val_type = octave_value (NDArray ());
2218  }
2219  else
2220  val_type = octave_value (NDArray ());
2221  goto fini;
2222 
2223  case 'n':
2224  buf << (type = s[i++]);
2225  bitwidth = 64;
2226  val_type = octave_value (NDArray ());
2227  goto fini;
2228 
2229  case 's': case 'q': case '[': case 'c':
2230  if (! discard)
2231  val_type = octave_value (Cell ());
2232  buf << (type = s[i++]);
2233  has_string = true;
2234  goto fini;
2235 
2236  fini:
2237  {
2238  if (! have_width)
2239  {
2240  if (type == 'c') // %c defaults to one character
2241  width = 1;
2242  else
2243  width = static_cast<unsigned int> (-1); // others: unlimited
2244  }
2245 
2246  if (finish_conversion (s, i, n, width, prec, bitwidth, val_type,
2247  discard, type) == 0)
2248  return;
2249  }
2250  break;
2251 
2252  default:
2253  error ("%s: '%%%c' is not a valid format specifier",
2254  who.c_str (), s[i]);
2255  }
2256 
2257  if (nconv < 0)
2258  break;
2259  }
2260 
2261  nconv = -1;
2262  }
2263 
2264  // Parse [...] and [^...]
2265  //
2266  // Matlab does not expand expressions like A-Z, but they are useful, and
2267  // so we parse them "carefully". We treat '-' as a usual character
2268  // unless both start and end characters are from the same class (upper
2269  // case, lower case, numeric), or this is not the first '-' in the
2270  // pattern.
2271  //
2272  // Keep both a running list of characters and a mask of which chars have
2273  // occurred. The first is efficient for patterns with few characters.
2274  // The latter is efficient for [^...] patterns.
2275 
2276  std::string
2278  {
2279  int len = pattern.length ();
2280  if (len == 0)
2281  return "";
2282 
2283  std::string retval (256, '\0');
2284  std::string mask (256, '\0'); // number of times chr has been seen
2285 
2286  int in = 0, out = 0;
2287  unsigned char ch, prev = 0;
2288  bool flip = false;
2289 
2290  ch = pattern[in];
2291  if (ch == '^')
2292  {
2293  in++;
2294  flip = true;
2295  }
2296  mask[pattern[in]] = '\1';
2297  retval[out++] = pattern[in++]; // even copy ']' if it is first
2298 
2299  bool prev_was_range = false; // disallow "a-m-z" as a pattern
2300  bool prev_prev_was_range = false;
2301  for (; in < len; in++)
2302  {
2303  bool was_range = false;
2304  ch = pattern[in];
2305  if (ch == ']')
2306  break;
2307 
2308  if (prev == '-' && in > 1 && isalnum (ch) && ! prev_prev_was_range)
2309  {
2310  unsigned char start_of_range = pattern[in-2];
2311  if (start_of_range < ch
2312  && ((isupper (ch) && isupper (start_of_range))
2313  || (islower (ch) && islower (start_of_range))
2314  || (isdigit (ch) && isdigit (start_of_range))
2315  || mask['-'] > 1)) // not the first '-'
2316  {
2317  was_range = true;
2318  out--;
2319  mask['-']--;
2320  for (int i = start_of_range; i <= ch; i++)
2321  {
2322  if (mask[i] == '\0')
2323  {
2324  mask[i] = '\1';
2325  retval[out++] = i;
2326  }
2327  }
2328  }
2329  }
2330  if (! was_range)
2331  {
2332  if (mask[ch]++ == 0)
2333  retval[out++] = ch;
2334  else if (ch != '-')
2335  warning_with_id ("octave:textscan-pattern",
2336  "%s: [...] contains two '%c's",
2337  who.c_str (), ch);
2338 
2339  if (prev == '-' && mask['-'] >= 2)
2341  ("octave:textscan-pattern",
2342  "%s: [...] contains two '-'s outside range expressions",
2343  who.c_str ());
2344  }
2345  prev = ch;
2346  prev_prev_was_range = prev_was_range;
2347  prev_was_range = was_range;
2348  }
2349 
2350  if (flip) // [^...]
2351  {
2352  out = 0;
2353  for (int i = 0; i < 256; i++)
2354  if (! mask[i])
2355  retval[out++] = i;
2356  }
2357 
2358  retval.resize (out);
2359 
2360  return retval;
2361  }
2362 
2363  int
2365  size_t n, unsigned int& width,
2366  int& prec, int& bitwidth,
2367  octave_value& val_type, bool discard,
2368  char& type)
2369  {
2370  int retval = 0;
2371 
2372  std::string char_class;
2373 
2374  size_t beg_idx = std::string::npos;
2375  size_t end_idx = std::string::npos;
2376 
2377  if (type != '%')
2378  {
2379  nconv++;
2380  if (type == '[')
2381  {
2382  if (i < n)
2383  {
2384  beg_idx = i;
2385 
2386  if (s[i] == '^')
2387  {
2388  type = '^';
2389  buf << s[i++];
2390 
2391  if (i < n)
2392  {
2393  beg_idx = i;
2394 
2395  if (s[i] == ']')
2396  buf << s[i++];
2397  }
2398  }
2399  else if (s[i] == ']')
2400  buf << s[i++];
2401  }
2402 
2403  while (i < n && s[i] != ']')
2404  buf << s[i++];
2405 
2406  if (i < n && s[i] == ']')
2407  {
2408  end_idx = i-1;
2409  buf << s[i++];
2410  }
2411 
2412  if (s[i-1] != ']')
2413  retval = nconv = -1;
2414  }
2415  }
2416 
2417  if (nconv >= 0)
2418  {
2419  if (beg_idx != std::string::npos && end_idx != std::string::npos)
2420  char_class = parse_char_class (s.substr (beg_idx,
2421  end_idx - beg_idx + 1));
2422 
2423  add_elt_to_list (width, prec, bitwidth, val_type, discard, type,
2424  char_class);
2425  }
2426 
2427  return retval;
2428  }
2429 
2430  void
2432  {
2433  size_t n = numel ();
2434 
2435  for (size_t i = 0; i < n; i++)
2436  {
2437  textscan_format_elt *elt = fmt_elts[i];
2438 
2439  std::cerr
2440  << "width: " << elt->width << "\n"
2441  << "digits " << elt->prec << "\n"
2442  << "bitwidth: " << elt->bitwidth << "\n"
2443  << "discard: " << elt->discard << "\n"
2444  << "type: ";
2445 
2447  std::cerr << "literal text\n";
2449  std::cerr << "whitespace\n";
2450  else
2451  std::cerr << elt->type << "\n";
2452 
2453  std::cerr
2454  << "char_class: `" << undo_string_escapes (elt->char_class) << "'\n"
2455  << "text: `" << undo_string_escapes (elt->text) << "'\n\n";
2456  }
2457  }
2458 
2459  // If FORMAT is explicitly "", it is assumed to be "%f" repeated enough
2460  // times to read the first row of the file. Set it now.
2461 
2462  int
2464  {
2465  // Read first line and strip end-of-line, which may be two characters
2466  std::string first_line (20, ' ');
2467 
2468  is.getline (first_line, static_cast<char> (ts.eol2));
2469 
2470  if (! first_line.empty ()
2471  && first_line[first_line.length () - 1] == ts.eol1)
2472  first_line.resize (first_line.length () - 1);
2473 
2474  std::istringstream strstr (first_line);
2475  delimited_stream ds (strstr, is);
2476 
2477  dim_vector dv (1,1); // initial size of each output_container
2478  Complex val;
2479  octave_value val_type;
2480  nconv = 0;
2481  int max_empty = 1000; // failsafe, if ds fails but not with eof
2482  int retval = 0;
2483 
2484  // read line, creating output_container as we go
2485  while (! ds.eof ())
2486  {
2487  bool already_skipped_delim = false;
2488  ts.skip_whitespace (ds);
2489  ds.progress_benchmark ();
2490  bool progress = false;
2491  ts.scan_complex (ds, *fmt_elts[0], val);
2492  if (ds.fail ())
2493  {
2494  ds.clear (ds.rdstate () & ~std::ios::failbit);
2495 
2496  if (ds.eof ())
2497  break;
2498 
2499  // Unless this was a missing value (i.e., followed by a delimiter),
2500  // return with an error status.
2501  ts.skip_delim (ds);
2502  if (ds.no_progress ())
2503  {
2504  retval = 4;
2505  break;
2506  }
2507  already_skipped_delim = true;
2508 
2509  val = ts.empty_value.scalar_value ();
2510 
2511  if (! --max_empty)
2512  break;
2513  }
2514 
2515  if (val.imag () == 0)
2516  val_type = octave_value (NDArray (dv, val.real ()));
2517  else
2518  val_type = octave_value (ComplexNDArray (dv, val));
2519 
2520  output_container.push_back (val_type);
2521 
2522  if (! already_skipped_delim)
2523  ts.skip_delim (ds);
2524 
2525  if (! progress && ds.no_progress ())
2526  break;
2527 
2528  nconv++;
2529  }
2530 
2531  output_container.pop_front (); // discard empty element from constructor
2532 
2533  // Create fmt_list now that the size is known
2534  for (octave_idx_type i = 1; i < nconv; i++)
2535  fmt_elts.push_back (new textscan_format_elt (*fmt_elts[0]));
2536 
2537  return retval; // May have returned 4 above.
2538  }
2539 
2541  : who (who_arg), buf (), whitespace_table (), delim_table (),
2542  delims (), comment_style (), comment_len (0), comment_char (-2),
2543  buffer_size (0), date_locale (), inf_nan (init_inf_nan ()),
2544  empty_value (octave::numeric_limits<double>::NaN ()), exp_chars ("edED"),
2545  header_lines (0), treat_as_empty (), treat_as_empty_len (0),
2546  whitespace (" \b\t"), eol1 ('\r'), eol2 ('\n'),
2547  return_on_error (1), collect_output (false),
2548  multiple_delims_as_one (false), default_exp (true),
2549  numeric_delim (false), lines (0)
2550  { }
2551 
2552  octave_value
2553  textscan::scan (std::istream& isp, const std::string& fmt,
2554  octave_idx_type ntimes, const octave_value_list& options,
2555  octave_idx_type& count)
2556  {
2557  textscan_format_list fmt_list (fmt);
2558 
2559  parse_options (options, fmt_list);
2560 
2561  octave_value result = do_scan (isp, fmt_list, ntimes);
2562 
2563  // FIXME: this is probably not the best way to get count. The
2564  // position could easily be larger than octave_idx_type when using
2565  // 32-bit indexing.
2566 
2567  std::ios::iostate state = isp.rdstate ();
2568  isp.clear ();
2569  count = static_cast<octave_idx_type> (isp.tellg ());
2570  isp.setstate (state);
2571 
2572  return result;
2573  }
2574 
2575  octave_value
2576  textscan::do_scan (std::istream& isp, textscan_format_list& fmt_list,
2577  octave_idx_type ntimes)
2578  {
2580 
2581  if (fmt_list.num_conversions () == -1)
2582  error ("%s: invalid format specified", who.c_str ());
2583 
2584  if (fmt_list.num_conversions () == 0)
2585  error ("%s: no valid format conversion specifiers", who.c_str ());
2586 
2587  // skip the first header_lines
2588  std::string dummy;
2589  for (int i = 0; i < header_lines && isp; i++)
2590  getline (isp, dummy, static_cast<char> (eol2));
2591 
2592  // Create our own buffered stream, for fast get/putback/tell/seek.
2593 
2594  // First, see how far ahead it should let us look.
2595  int max_lookahead = std::max (std::max (comment_len, treat_as_empty_len),
2596  std::max (delim_len, 3)); // 3 for NaN and Inf
2597 
2598  // Next, choose a buffer size to avoid reading too much, or too often.
2599  octave_idx_type buf_size = 4096;
2600  if (buffer_size)
2601  buf_size = buffer_size;
2602  else if (ntimes > 0)
2603  {
2604  // Avoid overflow of 80*ntimes...
2605  buf_size = std::min (buf_size, std::max (ntimes, 80 * ntimes));
2606  buf_size = std::max (buf_size, ntimes);
2607  }
2608  // Finally, create the stream.
2609  delimited_stream is (isp,
2610  (delim_table.empty () ? whitespace + "\r\n" : delims),
2611  max_lookahead, buf_size);
2612 
2613  // Grow retval dynamically. "size" is half the initial size
2614  // (FIXME: Should we start smaller if ntimes is large?)
2615  octave_idx_type size = ((ntimes < 8 && ntimes >= 0) ? ntimes : 1);
2616  Array<octave_idx_type> row_idx (dim_vector (1,2));
2617  row_idx(1) = 0;
2618 
2619  int err = 0;
2620  octave_idx_type row = 0;
2621 
2622  if (multiple_delims_as_one) // bug #44750?
2623  skip_delim (is);
2624 
2625  int done_after; // Number of columns read when EOF seen.
2626 
2627  // If FORMAT explicitly "", read first line and see how many "%f" match
2628  if (fmt_list.set_from_first)
2629  {
2630  err = fmt_list.read_first_row (is, *this);
2631  lines = 1;
2632 
2633  done_after = fmt_list.numel () + 1;
2634  if (! err)
2635  row = 1; // the above puts the first line into fmt_list.out_buf ()
2636  }
2637  else
2638  done_after = fmt_list.out_buf ().size () + 1;
2639 
2640  std::list<octave_value> out = fmt_list.out_buf ();
2641 
2642  // We will later merge adjacent columns of the same type.
2643  // Check now which columns to merge.
2644  // Reals may become complex, and so we can't trust types
2645  // after reading in data.
2646  // If the format was "", that conversion may already have happened,
2647  // so force all to be merged (as all are %f).
2648  bool merge_with_prev[fmt_list.numel ()];
2649  int conv = 0;
2650  if (collect_output)
2651  {
2652  int prev_type = -1;
2653  for (std::list<octave_value>::iterator col = out.begin ();
2654  col != out.end (); col++)
2655  {
2656  if (col->type_id () == prev_type
2657  || (fmt_list.set_from_first && prev_type != -1))
2658  merge_with_prev [conv++] = true;
2659  else
2660  merge_with_prev [conv++] = false;
2661 
2662  prev_type = col->type_id ();
2663  }
2664  }
2665 
2666  // This should be caught by earlier code, but this avoids a possible
2667  // infinite loop below.
2668  if (fmt_list.num_conversions () == 0)
2669  error ("%s: No conversions specified", who.c_str ());
2670 
2671  // Read the data. This is the main loop.
2672  if (! err)
2673  {
2674  for (/* row set ~30 lines above */; row < ntimes || ntimes == -1; row++)
2675  {
2676  if (row == 0 || row >= size)
2677  {
2678  size += size+1;
2679  for (std::list<octave_value>::iterator col = out.begin ();
2680  col != out.end (); col++)
2681  *col = (*col).resize (dim_vector (size, 1), 0);
2682  }
2683 
2684  row_idx(0) = row;
2685  err = read_format_once (is, fmt_list, out, row_idx, done_after);
2686 
2687  if ((err & ~1) > 0 || ! is || (lines >= ntimes && ntimes > -1))
2688  break;
2689  }
2690  }
2691 
2692  if ((err & 4) && ! return_on_error)
2693  error ("%s: Read error in field %d of row %d", who.c_str (),
2694  done_after + 1, row + 1);
2695 
2696  // If file does not end in EOL, do not pad columns with NaN.
2697  bool uneven_columns = false;
2698  if (err & 4)
2699  uneven_columns = true;
2700  else if (isp.eof ())
2701  {
2702  isp.clear ();
2703  isp.seekg (-1, std::ios_base::end);
2704  int last_char = isp.get ();
2705  isp.setstate (isp.eofbit);
2706  uneven_columns = (last_char != eol1 && last_char != eol2);
2707  }
2708 
2709  // convert return value to Cell array
2711 
2712  // (err & 1) means "error, and no columns read this row
2713  // FIXME: This may redundant now that done_after=0 says the same
2714  if (err & 1)
2715  done_after = out.size () + 1;
2716 
2717  int valid_rows = (row == ntimes) ? ntimes
2718  : (((err & 1) && (err & 8)) ? row : row+1);
2719  dim_vector dv (valid_rows, 1);
2720 
2721  ra_idx(0) = 0;
2722  int i = 0;
2723  if (! collect_output)
2724  {
2725  retval = Cell (dim_vector (1, out.size ()));
2726  for (std::list<octave_value>::iterator col = out.begin ();
2727  col != out.end (); col++, i++)
2728  {
2729  // trim last columns if that was requested
2730  if (i == done_after && uneven_columns)
2731  dv = dim_vector (std::max (valid_rows - 1, 0), 1);
2732 
2733  ra_idx(1) = i;
2734  retval = do_cat_op (retval, octave_value (Cell (col->resize (dv,0))),
2735  ra_idx);
2736  }
2737  }
2738  else // group adjacent cells of the same type into a single cell
2739  {
2740  octave_value cur; // current cell, accumulating columns
2741  octave_idx_type group_size = 0; // columns in this cell
2742  int prev_type = -1;
2743 
2744  conv = 0;
2745  retval = Cell ();
2746  for (std::list<octave_value>::iterator col = out.begin ();
2747  col != out.end (); col++)
2748  {
2749  if (! merge_with_prev [conv++]) // including first time
2750  {
2751  if (prev_type != -1)
2752  {
2753  ra_idx(1) = i++;
2754  retval = do_cat_op (retval, octave_value (Cell (cur)),
2755  ra_idx);
2756  }
2757  cur = octave_value (col->resize (dv,0));
2758  group_size = 1;
2759  prev_type = col->type_id ();
2760  }
2761  else
2762  {
2763  ra_idx(1) = group_size++;
2764  cur = do_cat_op (cur, octave_value (col->resize (dv,0)),
2765  ra_idx);
2766  }
2767  }
2768  ra_idx(1) = i;
2769  retval = do_cat_op (retval, octave_value (Cell (cur)), ra_idx);
2770  }
2771 
2772  return retval;
2773  }
2774 
2775  // Read a double considering the "precision" field of FMT and the
2776  // EXP_CHARS option of OPTIONS.
2777 
2778  double
2780  const textscan_format_elt& fmt) const
2781  {
2782  int sign = 1;
2783  unsigned int width_left = fmt.width;
2784  double retval = 0;
2785  bool valid = false; // syntactically correct double?
2786 
2787  int ch = is.peek ();
2788 
2789  if (ch == '+')
2790  {
2791  is.get ();
2792  ch = is.peek ();
2793  if (width_left)
2794  width_left--;
2795  }
2796  else if (ch == '-')
2797  {
2798  sign = -1;
2799  is.get ();
2800  ch = is.peek ();
2801  if (width_left)
2802  width_left--;
2803  }
2804 
2805  // Read integer part
2806  if (ch != '.')
2807  {
2808  if (ch >= '0' && ch <= '9') // valid if at least one digit
2809  valid = true;
2810  while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')
2811  retval = retval * 10 + (ch - '0');
2812  width_left++;
2813  }
2814 
2815  // Read fractional part, up to specified precision
2816  if (ch == '.' && width_left)
2817  {
2818  double multiplier = 1;
2819  int precision = fmt.prec;
2820  int i;
2821 
2822  if (width_left)
2823  width_left--; // Consider width of '.'
2824 
2825  if (precision == -1)
2826  precision = 1<<30; // FIXME: Should be MAXINT
2827 
2828  if (! valid) // if there was nothing before '.'...
2829  is.get (); // ...ch was a "peek", not "get".
2830 
2831  for (i = 0; i < precision; i++)
2832  {
2833  if (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')
2834  retval += (ch - '0') * (multiplier *= 0.1);
2835  else
2836  {
2837  width_left++;
2838  break;
2839  }
2840  }
2841 
2842  // round up if we truncated and the next digit is >= 5
2843  if ((i == precision || ! width_left) && (ch = is.get ()) >= '5'
2844  && ch <= '9')
2845  retval += multiplier;
2846 
2847  if (i > 0)
2848  valid = true; // valid if at least one digit after '.'
2849 
2850  // skip remainder after '.', to field width, to look for exponent
2851  if (i == precision)
2852  while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')
2853  ; // discard
2854 
2855  width_left++;
2856  }
2857 
2858  // look for exponent part in, e.g., 6.023E+23
2859  bool used_exp = false;
2860  if (valid && width_left > 1 && exp_chars.find (ch) != std::string::npos)
2861  {
2862  int ch1 = is.peek ();
2863  if (ch1 == '-' || ch1 == '+' || (ch1 >= '0' && ch1 <= '9'))
2864  {
2865  // if 1.0e+$ or some such, this will set failbit, as we want
2866  width_left--; // count "E"
2867  int exp = 0;
2868  int exp_sign = 1;
2869  if (ch1 == '+')
2870  {
2871  if (width_left)
2872  width_left--;
2873  is.get ();
2874  }
2875  else if (ch1 == '-')
2876  {
2877  exp_sign = -1;
2878  is.get ();
2879  if (width_left)
2880  width_left--;
2881  }
2882  valid = false;
2883  while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')
2884  {
2885  exp = exp*10 + ch - '0';
2886  valid = true;
2887  }
2888  width_left++;
2889  if (ch != std::istream::traits_type::eof () && width_left)
2890  is.putback (ch);
2891 
2892  double multiplier = pown (10, exp);
2893  if (exp_sign > 0)
2894  retval *= multiplier;
2895  else
2896  retval /= multiplier;
2897 
2898  used_exp = true;
2899  }
2900  }
2901  is.clear ();
2902  if (! used_exp && ch != std::istream::traits_type::eof () && width_left)
2903  is.putback (ch);
2904 
2905  // Check for +/- inf and NaN
2906  if (! valid && width_left >= 3)
2907  {
2908  int i = lookahead (is, inf_nan, 3, false); // false -> case insensitive
2909  if (i == 0)
2910  {
2912  valid = true;
2913  }
2914  else if (i == 1)
2915  {
2917  valid = true;
2918  }
2919  }
2920 
2921  // Check for +/- inf and NaN
2922  if (! valid && width_left >= 3)
2923  {
2924  int i = lookahead (is, inf_nan, 3, false); // false -> case insensitive
2925  if (i == 0)
2926  {
2928  valid = true;
2929  }
2930  else if (i == 1)
2931  {
2933  valid = true;
2934  }
2935  }
2936 
2937  if (! valid)
2938  is.setstate (std::ios::failbit);
2939  else
2940  is.setstate (is.rdstate () & ~std::ios::failbit);
2941 
2942  return retval * sign;
2943  }
2944 
2945  // Read a single number: real, complex, inf, NaN, possibly with limited
2946  // precision. Calls to this should be preceded by skip_whitespace.
2947  // Calling that inside scan_complex would violate its const declaration.
2948 
2949  void
2951  Complex& val) const
2952  {
2953  double im = 0;
2954  double re = 0;
2955  bool as_empty = false; // did we fail but match a "treat_as_empty" string?
2956  bool inf = false;
2957 
2958  int ch = is.peek ();
2959  if (ch == '+' || ch == '-') // check for [+-][ij] with no coefficients
2960  {
2961  ch = is.get ();
2962  int ch2 = is.peek ();
2963  if (ch2 == 'i' || ch2 == 'j')
2964  {
2965  double value = 1;
2966  is.get ();
2967  // Check not -inf
2968  if (is.peek () == 'n')
2969  {
2970  char *pos = is.tellg ();
2971  std::ios::iostate state = is.rdstate ();
2972 
2973  is.get ();
2974  ch2 = is.get ();
2975  if (ch2 == 'f')
2976  {
2977  inf = true;
2978  re = (ch == '+') ? octave::numeric_limits<double>::Inf ()
2980  value = 0;
2981  }
2982  else
2983  {
2984  is.clear (state);
2985  is.seekg (pos); // reset to position before look-ahead
2986  }
2987  }
2988 
2989  im = (ch == '+') ? value : -value;
2990  }
2991  else
2992  is.putback (ch);
2993  }
2994 
2995  if (! im && ! inf) // if not [+-][ij] or [+-]inf, read real normally
2996  {
2997  char *pos = is.tellg ();
2998  std::ios::iostate state = is.rdstate ();
2999  //re = octave_read_value<double> (is);
3000  re = read_double (is, fmt);
3001 
3002  // check for "treat as empty" string
3003  if (treat_as_empty.numel ()
3004  && (is.fail () || octave::math::is_NaN_or_NA (Complex (re))
3006  {
3007 
3008  for (int i = 0; i < treat_as_empty.numel (); i++)
3009  {
3010  if (ch == treat_as_empty (i).string_value ()[0])
3011  {
3012  as_empty = true; // first char matches, so read the lot
3013  break;
3014  }
3015  }
3016  if (as_empty) // if first char matched...
3017  {
3018  as_empty = false; // ...look for the whole string
3019 
3020  is.clear (state); // treat_as_empty "-" causes partial read
3021  is.seekg (pos); // reset to position before failed read
3022 
3023  // treat_as_empty strings may be different sizes.
3024  // Read ahead longest, put it all back, then re-read the string
3025  // that matches.
3026  std::string look_buf (treat_as_empty_len, '\0');
3027  char *look = is.read (&look_buf[0], look_buf.size (), pos);
3028 
3029  is.clear (state);
3030  is.seekg (pos); // reset to position before look-ahead
3031  // FIXME: is.read could invalidate pos
3032 
3033  for (int i = 0; i < treat_as_empty.numel (); i++)
3034  {
3035  std::string s = treat_as_empty (i).string_value ();
3036  if (! strncmp (s.c_str (), look, s.size ()))
3037  {
3038  as_empty = true;
3039  // read just the right amount
3040  is.read (&look_buf[0], s.size (), pos);
3041  break;
3042  }
3043  }
3044  }
3045  }
3046 
3047  if (! is.eof () && ! as_empty)
3048  {
3049  state = is.rdstate (); // before tellg, since that fails at EOF
3050  pos = is.tellg ();
3051  ch = is.peek (); // ch == EOF if read failed; no need to chk fail
3052  if (ch == 'i' || ch == 'j') // pure imaginary
3053  {
3054  is.get ();
3055  im = re;
3056  re = 0;
3057  }
3058  else if (ch == '+' || ch == '-') // see if it is real+imag[ij]
3059  {
3060  // save stream state in case we have to restore it
3061  pos = is.tellg ();
3062  state = is.rdstate ();
3063 
3064  //im = octave_read_value<double> (is);
3065  im = read_double (is, fmt);
3066  if (is.fail ())
3067  im = 1;
3068 
3069  if (is.peek () == 'i' || is.peek () == 'j')
3070  is.get ();
3071  else
3072  {
3073  im = 0; // no valid imaginary part. Restore state
3074  is.clear (state); // eof shouldn't cause fail.
3075  is.seekg (pos);
3076  }
3077  }
3078  else if (is.eof ()) // we've read enough to be a "valid" read
3079  is.clear (state); // failed peek shouldn't cause fail
3080  }
3081  }
3082  if (as_empty)
3083  val = empty_value.scalar_value ();
3084  else
3085  val = Complex (re, im);
3086  }
3087 
3088  // Return in VAL the run of characters from IS NOT contained in PATTERN.
3089 
3090  int
3092  std::string& val) const
3093  {
3094  int c1 = std::istream::traits_type::eof ();
3095  std::ostringstream obuf; // Is this optimized for growing?
3096 
3097  while (is && ((c1 = (is && ! is.eof ())
3098  ? is.get_undelim ()
3099  : std::istream::traits_type::eof ())
3100  != std::istream::traits_type::eof ())
3101  && pattern.find (c1) == std::string::npos)
3102  obuf << static_cast<char> (c1);
3103 
3104  val = obuf.str ();
3105 
3106  if (c1 != std::istream::traits_type::eof ())
3107  is.putback (c1);
3108 
3109  return c1;
3110  }
3111 
3112  // Read until one of the strings in DELIMITERS is found. For
3113  // efficiency, ENDS is a list of the last character of each delimiter.
3114 
3115  std::string
3116  textscan::read_until (delimited_stream& is, const Cell& delimiters,
3117  const std::string& ends) const
3118  {
3119  std::string retval ("");
3120  bool done = false;
3121  do
3122  {
3123  // find sequence ending with an ending char
3124  std::string next;
3125  scan_caret (is, ends.c_str (), next);
3126  retval = retval + next; // FIXME: could use repeated doubling of size
3127 
3128  int last = (! is.eof ()
3129  ? is.get_undelim () : std::istream::traits_type::eof ());
3130 
3131  if (last != std::istream::traits_type::eof ())
3132  {
3133  retval = retval + static_cast<char> (last);
3134  for (int i = 0; i < delimiters.numel (); i++)
3135  {
3136  std::string delim = delimiters(i).string_value ();
3137  size_t start = (retval.length () > delim.length ()
3138  ? retval.length () - delim.length ()
3139  : 0);
3140  std::string may_match = retval.substr (start);
3141  if (may_match == delim)
3142  {
3143  done = true;
3144  retval = retval.substr (0, start);
3145  break;
3146  }
3147  }
3148  }
3149  }
3150  while (! done && is && ! is.eof ());
3151 
3152  return retval;
3153  }
3154 
3155  // Read stream until either fmt.width chars have been read, or
3156  // options.delimiter has been found. Does *not* rely on fmt being 's'.
3157  // Used by formats like %6f to limit to 6.
3158 
3159  void
3161  std::string& val) const
3162  {
3163  if (delim_list.is_empty ())
3164  {
3165  unsigned int i = 0;
3166  unsigned int width = fmt.width;
3167 
3168  for (i = 0; i < width; i++)
3169  {
3170  if (i+1 > val.length ())
3171  val = val + val + ' '; // grow even if empty
3172  int ch = is.get ();
3173  if (is_delim (ch) || ch == std::istream::traits_type::eof ())
3174  {
3175  is.putback (ch);
3176  break;
3177  }
3178  else
3179  val[i] = ch;
3180  }
3181  val = val.substr (0, i); // trim pre-allocation
3182  }
3183  else // Cell array of multi-character delimiters
3184  {
3185  std::string ends ("");
3186  for (int i = 0; i < delim_list.numel (); i++)
3187  {
3188  std::string tmp = delim_list(i).string_value ();
3189  ends += tmp.substr (tmp.length () - 1);
3190  }
3191  val = textscan::read_until (is, delim_list, ends);
3192  }
3193  }
3194 
3195  // Return in VAL the run of characters from IS contained in PATTERN.
3196 
3197  int
3199  std::string& val) const
3200  {
3201  int c1 = std::istream::traits_type::eof ();
3202  std::ostringstream obuf; // Is this optimized for growing?
3203 
3204  while (is && pattern.find (c1 = is.get_undelim ()) != std::string::npos)
3205  obuf << static_cast<char> (c1);
3206 
3207  val = obuf.str ();
3208  if (c1 != std::istream::traits_type::eof ())
3209  is.putback (c1);
3210  return c1;
3211  }
3212 
3213  // Return in VAL a string, either delimited by whitespace/delimiters, or
3214  // enclosed in a pair of double quotes ("..."). Enclosing quotes are
3215  // removed. A consecutive pair "" is inserted into VAL as a single ".
3216 
3217  void
3219  std::string& val)
3220  {
3221  skip_whitespace (is);
3222 
3223  if (is.peek () != '\"')
3224  scan_string (is, fmt, val);
3225  else
3226  {
3227  is.get ();
3228  scan_caret (is, "\"", val); // read everything until "
3229  is.get (); // swallow "
3230 
3231  while (is && is.peek () == '\"') // if double ", insert one in stream,
3232  { // and keep looking for single "
3233  is.get ();
3234  std::string val1;
3235  scan_caret (is, "\"", val1);
3236  val = val + "\"" + val1;
3237  is.get_undelim ();
3238  }
3239  }
3240  }
3241 
3242  // Read from IS into VAL a string of the next fmt.width characters,
3243  // including any whitespace or delimiters.
3244 
3245  void
3247  std::string& val) const
3248  {
3249  val.resize (fmt.width);
3250 
3251  for (unsigned int i = 0; is && i < fmt.width; i++)
3252  {
3253  int ch = is.get_undelim ();
3254  if (ch != std::istream::traits_type::eof ())
3255  val[i] = ch;
3256  else
3257  {
3258  val.resize (i);
3259  break;
3260  }
3261  }
3262  }
3263 
3264  // Read a single '%...' conversion and place it in position ROW of OV.
3265 
3266  void
3269  {
3270  skip_whitespace (is);
3271 
3272  is.clear ();
3273 
3274  octave_value val;
3275  if (fmt.numeric)
3276  {
3277  if (fmt.type == 'f' || fmt.type == 'n')
3278  {
3279  Complex v;
3280  skip_whitespace (is);
3281  scan_complex (is, fmt, v);
3282 
3283  if (! fmt.discard && ! is.fail ())
3284  {
3285  if (fmt.bitwidth == 64)
3286  {
3287  if (ov.is_real_type () && v.imag () == 0)
3288  ov.internal_rep ()->fast_elem_insert (row(0), v.real ());
3289  else
3290  {
3291  if (ov.is_real_type ()) // cat does type conversion
3292  ov = do_cat_op (ov, octave_value (v), row);
3293  else
3294  ov.internal_rep ()->fast_elem_insert (row(0), v);
3295  }
3296  }
3297  else
3298  {
3299  if (ov.is_real_type () && v.imag () == 0)
3300  ov.internal_rep ()->fast_elem_insert (row(0),
3301  float (v.real ()));
3302  else
3303  {
3304  if (ov.is_real_type ()) // cat does type conversion
3305  ov = do_cat_op (ov, octave_value (v), row);
3306  else
3307  ov.internal_rep ()->fast_elem_insert (row(0),
3308  FloatComplex (v));
3309  }
3310  }
3311  }
3312  }
3313  else
3314  {
3315  double v; // Matlab docs say 1e30 etc should be valid for %d and
3316  // 1000 as a %d8 should be 127, so read as double.
3317  // Some loss of precision for d64 and u64.
3318  skip_whitespace (is);
3319  v = read_double (is, fmt);
3320  if (! fmt.discard && ! is.fail ())
3321  switch (fmt.bitwidth)
3322  {
3323  case 64:
3324  switch (fmt.type)
3325  {
3326  case 'd':
3327  {
3328  octave_int64 vv = v;
3329  ov.internal_rep ()->fast_elem_insert (row(0), vv);
3330  }
3331  break;
3332 
3333  case 'u':
3334  {
3335  octave_uint64 vv = v;
3336  ov.internal_rep ()->fast_elem_insert (row(0), vv);
3337  }
3338  break;
3339  }
3340  break;
3341 
3342  case 32:
3343  switch (fmt.type)
3344  {
3345  case 'd':
3346  {
3347  octave_int32 vv = v;
3348  ov.internal_rep ()->fast_elem_insert (row(0), vv);
3349  }
3350  break;
3351 
3352  case 'u':
3353  {
3354  octave_uint32 vv = v;
3355  ov.internal_rep ()->fast_elem_insert (row(0), vv);
3356  }
3357  break;
3358  }
3359  break;
3360 
3361  case 16:
3362  if (fmt.type == 'd')
3363  {
3364  octave_int16 vv = v;
3365  ov.internal_rep ()->fast_elem_insert (row(0), vv);
3366  }
3367  else
3368  {
3369  octave_uint16 vv = v;
3370  ov.internal_rep ()->fast_elem_insert (row(0), vv);
3371  }
3372  break;
3373 
3374  case 8:
3375  if (fmt.type == 'd')
3376  {
3377  octave_int8 vv = v;
3378  ov.internal_rep ()->fast_elem_insert (row(0), vv);
3379  }
3380  else
3381  {
3382  octave_uint8 vv = v;
3383  ov.internal_rep ()->fast_elem_insert (row(0), vv);
3384  }
3385  break;
3386  }
3387  }
3388 
3389  if (is.fail () & ! fmt.discard)
3390  ov = do_cat_op (ov, empty_value, row);
3391  }
3392  else
3393  {
3394  std::string vv (" "); // initial buffer. Grows as needed
3395  switch (fmt.type)
3396  {
3397  case 's':
3398  scan_string (is, fmt, vv);
3399  break;
3400 
3401  case 'q':
3402  scan_qstring (is, fmt, vv);
3403  break;
3404 
3405  case 'c':
3406  scan_cstring (is, fmt, vv);
3407  break;
3408 
3409  case '[':
3410  scan_bracket (is, fmt.char_class.c_str (), vv);
3411  break;
3412 
3413  case '^':
3414  scan_caret (is, fmt.char_class.c_str (), vv);
3415  break;
3416  }
3417 
3418  if (! fmt.discard)
3419  ov.internal_rep ()->fast_elem_insert (row (0),
3420  Cell (octave_value (vv)));
3421 
3422  // FIXME: why does failbit get set at EOF, instead of eofbit?
3423  if (! vv.empty ())
3424  is.clear (is.rdstate () & ~std::ios_base::failbit);
3425  }
3426 
3427  is.field_done ();
3428  }
3429 
3430  // Read data corresponding to the entire format string once, placing the
3431  // values in row ROW of retval.
3432 
3433  int
3435  textscan_format_list& fmt_list,
3436  std::list<octave_value>& retval,
3437  Array<octave_idx_type> row, int& done_after)
3438  {
3439  const textscan_format_elt *elem = fmt_list.first ();
3440  std::list<octave_value>::iterator out = retval.begin ();
3441  bool no_conversions = true;
3442  bool done = false;
3443  bool conversion_failed = false; // Record for ReturnOnError
3444  bool nothing_worked = true;
3445 
3446  octave_quit ();
3447 
3448  for (size_t i = 0; i < fmt_list.numel (); i++)
3449  {
3450  bool this_conversion_failed = false;
3451 
3452  // Clear fail of previous numeric conversions.
3453  is.clear ();
3454 
3455  switch (elem->type)
3456  {
3457  case 'C':
3458  case 'D':
3459  warning ("%s: conversion %c not yet implemented",
3460  who.c_str (), elem->type);
3461  break;
3462 
3463  case 'u':
3464  case 'd':
3465  case 'f':
3466  case 'n':
3467  case 's':
3468  case '[':
3469  case '^':
3470  case 'q':
3471  case 'c':
3472  scan_one (is, *elem, *out, row);
3473  break;
3474 
3476  match_literal (is, *elem);
3477  break;
3478 
3479  default:
3480  error ("Unknown format element '%c'", elem->type);
3481  }
3482 
3483  if (! is.fail ())
3484  {
3485  if (! elem->discard)
3486  no_conversions = false;
3487  }
3488  else
3489  {
3490  is.clear (is.rdstate () & ~std::ios::failbit);
3491 
3492  if (!is.eof () && ~is_delim (is.peek ()))
3493  this_conversion_failed = true;
3494  }
3495 
3496  if (! elem->discard)
3497  out++;
3498 
3499  elem = fmt_list.next ();
3500  char *pos = is.tellg ();
3501 
3502  // FIXME: these conversions "ignore delimiters". Should they include
3503  // delimiters at the start of the conversion, or can those be skipped?
3505  // && elem->type != '[' && elem->type != '^' && elem->type != 'c'
3506  )
3507  skip_delim (is);
3508 
3509  if (is.eof ())
3510  {
3511  if (! done)
3512  done_after = i+1;
3513 
3514  // note EOF, but process others to get empty_val.
3515  done = true;
3516  }
3517 
3518  if (this_conversion_failed)
3519  {
3520  if (is.tellg () == pos && ! conversion_failed)
3521  {
3522  // done_after = first failure
3523  done_after = i; // note fail, but parse others to get empty_val
3524  conversion_failed = true;
3525  }
3526  else
3527  this_conversion_failed = false;
3528  }
3529  else if (! done && !conversion_failed)
3530  nothing_worked = false;
3531  }
3532 
3533  if (done)
3534  is.setstate (std::ios::eofbit);
3535 
3536  return no_conversions
3537  + (is.eof () ? 2 : 0)
3538  + (conversion_failed ? 4 : 0)
3539  + (nothing_worked ? 8 : 0);
3540 
3541  }
3542 
3543  void
3545  textscan_format_list& fmt_list)
3546  {
3547  int last = args.length ();
3548  int n = last;
3549 
3550  if (n & 1)
3551  error ("%s: %d parameters given, but only %d values",
3552  who.c_str (), n-n/2, n/2);
3553 
3554  delim_len = 1;
3555  bool have_delims = false;
3556  for (int i = 0; i < last; i += 2)
3557  {
3558  std::string param = args(i).xstring_value ("%s: Invalid parameter type <%s> for parameter %d",
3559  who.c_str (),
3560  args(i).type_name ().c_str (),
3561  i/2 + 1);
3562  std::transform (param.begin (), param.end (), param.begin (), ::tolower);
3563 
3564  if (param == "delimiter")
3565  {
3566  bool invalid = true;
3567  if (args(i+1).is_string ())
3568  {
3569  invalid = false;
3570  have_delims = true;
3571  delims = args(i+1).string_value ();
3572  if (args(i+1).is_sq_string ())
3574  }
3575  else if (args(i+1).is_cell ())
3576  {
3577  invalid = false;
3578  delim_list = args(i+1).cell_value ();
3579  delim_table = " "; // non-empty, to flag non-default delim
3580 
3581  // Check that all elements are strings, and find max length
3582  for (int j = 0; j < delim_list.numel (); j++)
3583  {
3584  if (! delim_list(j).is_string ())
3585  invalid = true;
3586  else
3587  {
3588  if (delim_list(j).is_sq_string ())
3590  .string_value ());
3591  octave_idx_type len = delim_list(j).string_value ()
3592  .length ();
3593  delim_len = std::max (static_cast<int> (len), delim_len);
3594  }
3595  }
3596  }
3597  if (invalid)
3598  error ("%s: Delimiters must be either a string or cell array of strings",
3599  who.c_str ());
3600  }
3601  else if (param == "commentstyle")
3602  {
3603  if (args(i+1).is_string ())
3604  {
3605  // check here for names like "C++", "C", "shell", ...?
3606  comment_style = Cell (args(i+1));
3607  }
3608  else if (args(i+1).is_cell ())
3609  {
3610  comment_style = args(i+1).cell_value ();
3611  int len = comment_style.numel ();
3612  if ((len >= 1 && ! comment_style (0).is_string ())
3613  || (len >= 2 && ! comment_style (1).is_string ())
3614  || (len >= 3))
3615  error ("%s: CommentStyle must be either a string or cell array of one or two strings",
3616  who.c_str ());
3617  }
3618  else
3619  error ("%s: CommentStyle must be either a string or cell array of one or two strings",
3620  who.c_str ());
3621 
3622  // How far ahead do we need to look to detect an open comment
3623  // and which character do we look for?
3624  if (comment_style.numel () >= 1)
3625  {
3626  comment_len = comment_style (0).string_value ().size ();
3627  comment_char = comment_style (0).string_value ()[0];
3628  }
3629  }
3630  else if (param == "treatasempty")
3631  {
3632  bool invalid = false;
3633  if (args(i+1).is_string ())
3634  {
3635  treat_as_empty = Cell (args(i+1));
3636  treat_as_empty_len = args(i+1).string_value ().size ();
3637  }
3638  else if (args(i+1).is_cell ())
3639  {
3640  treat_as_empty = args(i+1).cell_value ();
3641  for (int j = 0; j < treat_as_empty.numel (); j++)
3642  if (! treat_as_empty (j).is_string ())
3643  invalid = true;
3644  else
3645  {
3646  int k = treat_as_empty (j).string_value ().size ();
3647  if (k > treat_as_empty_len)
3649  }
3650  }
3651  if (invalid)
3652  error ("%s: TreatAsEmpty must be either a string or cell array of one or two strings",
3653  who.c_str ());
3654 
3655  // FIXME: Ensure none is a prefix of a later one. Sort by length?
3656  }
3657  else if (param == "collectoutput")
3658  {
3659  collect_output = args(i+1).xbool_value ("%s: CollectOutput must be logical or numeric", who.c_str ());
3660  }
3661  else if (param == "emptyvalue")
3662  {
3663  empty_value = args(i+1).xscalar_value ("%s: EmptyValue must be numeric", who.c_str ());
3664  }
3665  else if (param == "headerlines")
3666  {
3667  header_lines = args(i+1).xscalar_value ("%s: HeaderLines must be numeric", who.c_str ());
3668  }
3669  else if (param == "bufsize")
3670  {
3671  buffer_size = args(i+1).xscalar_value ("%s: BufSize must be numeric", who.c_str ());
3672  }
3673  else if (param == "multipledelimsasone")
3674  {
3675  multiple_delims_as_one = args(i+1).xbool_value ("%s: MultipleDelimsAsOne must be logical or numeric", who.c_str ());
3676  }
3677  else if (param == "returnonerror")
3678  {
3679  return_on_error = args(i+1).xbool_value ("%s: ReturnOnError must be logical or numeric", who.c_str ());
3680  }
3681  else if (param == "whitespace")
3682  {
3683  whitespace = args(i+1).xstring_value ("%s: Whitespace must be a character string", who.c_str ());
3684  }
3685  else if (param == "expchars")
3686  {
3687  exp_chars = args(i+1).xstring_value ("%s: ExpChars must be a character string", who.c_str ());
3688  default_exp = false;
3689  }
3690  else if (param == "endofline")
3691  {
3692  bool valid = true;
3693  std::string s = args(i+1).xstring_value ("%s: EndOfLine must be at most one character or '\\r\\n'", who.c_str ());
3694  if (args(i+1).is_sq_string ())
3695  s = do_string_escapes (s);
3696  int l = s.length ();
3697  if (l == 0)
3698  eol1 = eol2 = -2;
3699  else if (l == 1)
3700  eol1 = eol2 = s.c_str ()[0];
3701  else if (l == 2)
3702  {
3703  eol1 = s.c_str ()[0];
3704  eol2 = s.c_str ()[1];
3705  if (eol1 != '\r' || eol2 != '\n') // Why limit it?
3706  valid = false;
3707  }
3708  else
3709  valid = false;
3710 
3711  if (! valid)
3712  error ("%s: EndOfLine must be at most one character or '\\r\\n'",
3713  who.c_str ());
3714  }
3715  else
3716  error ("%s: unrecognized option '%s'", who.c_str (), param.c_str ());
3717  }
3718 
3719  whitespace_table = std::string (256, '\0');
3720  for (unsigned int i = 0; i < whitespace.length (); i++)
3721  whitespace_table[whitespace[i]] = '1';
3722 
3723  // For Matlab compatibility, add 0x20 to whitespace, unless
3724  // whitespace is explicitly ignored.
3725  if (! (whitespace.empty () && fmt_list.has_string))
3726  whitespace_table[' '] = '1';
3727 
3728  // Create look-up table of delimiters, based on 'delimiter'
3729  delim_table = std::string (256, '\0');
3730  if (eol1 >= 0 && eol1 < 256)
3731  delim_table[eol1] = '1'; // EOL is always a delimiter
3732  if (eol2 >= 0 && eol2 < 256)
3733  delim_table[eol2] = '1'; // EOL is always a delimiter
3734  if (! have_delims)
3735  for (unsigned int i = 0; i < 256; i++)
3736  {
3737  if (isspace (i))
3738  delim_table[i] = '1';
3739  }
3740  else
3741  for (unsigned int i = 0; i < delims.length (); i++)
3742  delim_table[delims[i]] = '1';
3743  }
3744 
3745  // Skip comments, and characters specified by the "Whitespace" option.
3746  // If EOLstop == true, don't skip end of line.
3747 
3748  int
3750  {
3751  int c1 = std::istream::traits_type::eof ();
3752  bool found_comment = false;
3753 
3754  do
3755  {
3756  found_comment = false;
3757  int prev = -1;
3758  while (is && (c1 = is.get_undelim ()) != std::istream::traits_type::eof ()
3759  && ( ( (c1 == eol1 || c1 == eol2) && ++lines && ! EOLstop)
3760  || isspace (c1)))
3761  {
3762  if (prev == eol1 && eol1 != eol2 && c1 == eol2)
3763  lines--;
3764  prev = c1;
3765  }
3766 
3767  if (c1 == comment_char) // see if we match an open comment
3768  {
3769  // save stream state in case we have to restore it
3770  char *pos = is.tellg ();
3771  std::ios::iostate state = is.rdstate ();
3772 
3773  std::string tmp (comment_len, '\0');
3774  char *look = is.read (&tmp[0], comment_len-1, pos); // already read first char
3775  if (is && ! strncmp (comment_style(0).string_value ().substr (1)
3776  .c_str (), look, comment_len-1))
3777  {
3778  found_comment = true;
3779 
3780  std::string dummy;
3781  if (comment_style.numel () == 1) // skip to end of line
3782  {
3783  std::string eol (3, '\0');
3784  eol[0] = eol1;
3785  eol[1] = eol2;
3786 
3787  scan_caret (is, eol, dummy);
3788  c1 = is.get_undelim ();
3789  if (c1 == eol1 && eol1 != eol2 && is.peek_undelim () == eol2)
3790  is.get_undelim ();
3791  lines++;
3792  }
3793  else // matching pair
3794  {
3795  std::string end_c = comment_style(1).string_value ();
3796  // last char of end-comment sequence
3797  std::string last = end_c.substr (end_c.size () - 1);
3798  std::string may_match ("");
3799  do
3800  {
3801  // find sequence ending with last char
3802  scan_caret (is, last, dummy);
3803  is.get_undelim (); // (read LAST itself)
3804 
3805  may_match = may_match + dummy + last;
3806  if (may_match.length () > end_c.length ())
3807  {
3808  size_t start = may_match.length () - end_c.length ();
3809  may_match = may_match.substr (start);
3810  }
3811  }
3812  while (may_match != end_c && is && ! is.eof ());
3813  }
3814  }
3815  else // wasn't really a comment; restore state
3816  {
3817  is.clear (state);
3818  is.seekg (pos);
3819  }
3820  }
3821  }
3822  while (found_comment);
3823 
3824  if (c1 != std::istream::traits_type::eof ())
3825  is.putback (c1);
3826  return c1;
3827  }
3828 
3829  // See if the next few characters match one of the strings in target.
3830  // For efficiency, MAX_LEN is the cached longest length of any target.
3831  // Return -1 if none is found, or the index of the match.
3832 
3833  int
3834  textscan::lookahead (delimited_stream& is, const Cell& targets, int max_len,
3835  bool case_sensitive) const
3836  {
3837  // target strings may be different sizes.
3838  // Read ahead longest, put it all back, then re-read the string
3839  // that matches.
3840 
3841  char *pos = is.tellg ();
3842 
3843  std::string tmp (max_len, '\0');
3844  char *look = is.read (&tmp[0], tmp.size (), pos);
3845 
3846  is.clear ();
3847  is.seekg (pos); // reset to position before look-ahead
3848  // FIXME: pos may be corrupted by is.read
3849 
3850  int i;
3851  int (*compare)(const char *, const char *, size_t);
3852  compare = case_sensitive ? strncmp : strncasecmp;
3853 
3854  for (i = 0; i < targets.numel (); i++)
3855  {
3856  std::string s = targets (i).string_value ();
3857  if (! (*compare) (s.c_str (), look, s.size ()))
3858  {
3859  is.read (&tmp[0], s.size (), pos); // read just the right amount
3860  break;
3861  }
3862  }
3863 
3864  if (i == targets.numel ())
3865  i = -1;
3866 
3867  return i;
3868  }
3869 
3870  // Skip delimiters -- multiple if MultipleDelimsAsOne specified.
3871  int
3873  {
3874  int c1 = skip_whitespace (is, true); // 'true': stop once EOL is read
3875  if (delim_list.numel () == 0) // single character delimiter
3876  {
3877  if (is_delim (c1) || c1 == eol1 || c1 == eol2)
3878  {
3879  is.get ();
3880  if (c1 == eol1 && is.peek_undelim () == eol2)
3881  is.get_undelim (); // if \r\n, skip the \n too.
3882 
3884  {
3885  int prev = -1;
3886  // skip multiple delims.
3887  // Increment lines for each end-of-line seen; for \r\n, decrement
3888  while (is && ((c1 = is.get_undelim ())
3889  != std::istream::traits_type::eof ())
3890  && (((c1 == eol1 || c1 == eol2) && ++lines)
3891  || isspace (c1) || is_delim (c1)))
3892  {
3893  if (prev == eol1 && eol1 != eol2 && c1 == eol2)
3894  lines--;
3895  prev = c1;
3896  }
3897  if (c1 != std::istream::traits_type::eof ())
3898  is.putback (c1);
3899  }
3900  }
3901  }
3902  else // multi-character delimiter
3903  {
3904  int first_match;
3905 
3906  if (c1 == eol1 || c1 == eol2
3907  || (-1 != (first_match = lookahead (is, delim_list, delim_len))))
3908  {
3909  if (c1 == eol1)
3910  {
3911  is.get_undelim ();
3912  if (is.peek_undelim () == eol2)
3913  is.get_undelim ();
3914  }
3915  else if (c1 == eol2)
3916  {
3917  is.get_undelim ();
3918  }
3919 
3921  {
3922  int prev = -1;
3923  // skip multiple delims.
3924  // Increment lines for each end-of-line seen; for \r\n, decrement
3925  while (is && ((c1 = skip_whitespace (is, true))
3926  != std::istream::traits_type::eof ())
3927  && (((c1 == eol1 || c1 == eol2) && ++lines)
3928  || -1 != lookahead (is, delim_list, delim_len)))
3929  {
3930  if (prev == eol1 && eol1 != eol2 && c1 == eol2)
3931  lines--;
3932  prev = c1;
3933  }
3934  }
3935  }
3936  }
3937 
3938  return c1;
3939  }
3940 
3941  // Read in as much of the input as coincides with the literal in the
3942  // format string. Return "true" if the entire literal is matched, else
3943  // false (and set failbit).
3944 
3945  bool
3947  {
3948  // "false" -> treat EOL as normal space
3949  // since a delimiter at the start of a line is a mismatch, not empty field
3950  skip_whitespace (is, false);
3951 
3952  for (unsigned int i = 0; i < fmt.width; i++)
3953  {
3954  int ch = is.get_undelim ();
3955  if (ch != fmt.text[i])
3956  {
3957  if (ch != std::istream::traits_type::eof ())
3958  is.putback (ch);
3959  is.setstate (std::ios::failbit);
3960  return false;
3961  }
3962  }
3963  return true;
3964  }
3965 }
3966 
3967 void
3969 {
3970  fail = true;
3971  errmsg = msg;
3972 }
3973 
3974 void
3976 {
3977  fail = true;
3978  errmsg = who + ": " + msg;
3979 }
3980 
3981 void
3983 {
3984  fail = false;
3985  errmsg = "";
3986 }
3987 
3988 void
3990 {
3991  std::istream *is = input_stream ();
3992  std::ostream *os = output_stream ();
3993 
3994  if (is)
3995  is->clear ();
3996 
3997  if (os)
3998  os->clear ();
3999 }
4000 
4001 // Functions that are defined for all input streams (input streams
4002 // are those that define is).
4003 
4006  bool strip_newline, const std::string& who)
4007 {
4008  if (octave::application::interactive () && file_number () == 0)
4009  ::error ("%s: unable to read from stdin while running interactively",
4010  who.c_str ());
4011 
4013 
4014  err = false;
4015 
4016  std::istream *isp = input_stream ();
4017 
4018  if (! isp)
4019  {
4020  err = true;
4021  invalid_operation (who, "reading");
4022  }
4023  else
4024  {
4025  std::istream& is = *isp;
4026 
4027  std::ostringstream buf;
4028 
4029  int c = 0;
4030  int char_count = 0;
4031 
4032  if (max_len != 0)
4033  {
4034  while (is && (c = is.get ()) != std::istream::traits_type::eof ())
4035  {
4036  char_count++;
4037 
4038  // Handle CRLF, CR, or LF as line ending.
4039  if (c == '\r')
4040  {
4041  if (! strip_newline)
4042  buf << static_cast<char> (c);
4043 
4044  c = is.get ();
4045 
4046  if (c != std::istream::traits_type::eof ())
4047  {
4048  if (c == '\n')
4049  {
4050  char_count++;
4051 
4052  if (! strip_newline)
4053  buf << static_cast<char> (c);
4054  }
4055  else
4056  is.putback (c);
4057  }
4058 
4059  break;
4060  }
4061  else if (c == '\n')
4062  {
4063  if (! strip_newline)
4064  buf << static_cast<char> (c);
4065 
4066  break;
4067  }
4068  else
4069  buf << static_cast<char> (c);
4070 
4071  if (max_len > 0 && char_count == max_len)
4072  break;
4073  }
4074  }
4075 
4076  if (! is.eof () && char_count > 0)
4077  {
4078  // GAGME. Matlab seems to check for EOF even if the last character
4079  // in a file is a newline character. This is NOT what the
4080  // corresponding C-library functions do.
4081  int disgusting_compatibility_hack = is.get ();
4082  if (! is.eof ())
4083  is.putback (disgusting_compatibility_hack);
4084  }
4085 
4086  if (is.good () || (is.eof () && char_count > 0))
4087  retval = buf.str ();
4088  else
4089  {
4090  err = true;
4091 
4092  if (is.eof () && char_count == 0)
4093  error (who, "at end of file");
4094  else
4095  error (who, "read error");
4096  }
4097  }
4098 
4099  return retval;
4100 }
4101 
4104  const std::string& who)
4105 {
4106  return do_gets (max_len, err, true, who);
4107 }
4108 
4111  const std::string& who)
4112 {
4113  return do_gets (max_len, err, false, who);
4114 }
4115 
4116 off_t
4117 octave_base_stream::skipl (off_t num, bool& err, const std::string& who)
4118 {
4119  if (octave::application::interactive () && file_number () == 0)
4120  ::error ("%s: unable to read from stdin while running interactively",
4121  who.c_str ());
4122 
4123  off_t cnt = -1;
4124 
4125  err = false;
4126 
4127  std::istream *isp = input_stream ();
4128 
4129  if (! isp)
4130  {
4131  err = true;
4132  invalid_operation (who, "reading");
4133  }
4134  else
4135  {
4136  std::istream& is = *isp;
4137 
4138  int c = 0;
4139  int lastc = -1;
4140  cnt = 0;
4141 
4142  while (is && (c = is.get ()) != std::istream::traits_type::eof ())
4143  {
4144  // Handle CRLF, CR, or LF as line ending.
4145  if (c == '\r' || (c == '\n' && lastc != '\r'))
4146  {
4147  if (++cnt == num)
4148  break;
4149  }
4150 
4151  lastc = c;
4152  }
4153 
4154  // Maybe eat the following \n if \r was just met.
4155  if (c == '\r' && is.peek () == '\n')
4156  is.get ();
4157 
4158  if (is.bad ())
4159  {
4160  err = true;
4161  error (who, "read error");
4162  }
4163 
4164  if (err)
4165  cnt = -1;
4166  }
4167 
4168  return cnt;
4169 }
4170 
4171 template <typename T>
4172 std::istream&
4173 octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, T* valptr)
4174 {
4175  T value = T ();
4176 
4177  switch (fmt.type)
4178  {
4179  case 'o':
4180  is >> std::oct >> value >> std::dec;
4181  break;
4182 
4183  case 'x':
4184  is >> std::hex >> value >> std::dec;
4185  break;
4186 
4187  case 'i':
4188  {
4189  int c1 = std::istream::traits_type::eof ();
4190 
4191  while (is && (c1 = is.get ()) != std::istream::traits_type::eof ()
4192  && isspace (c1))
4193  ; // skip whitespace
4194 
4195  if (c1 != std::istream::traits_type::eof ())
4196  {
4197  if (c1 == '0')
4198  {
4199  int c2 = is.peek ();
4200 
4201  if (c2 == 'x' || c2 == 'X')
4202  {
4203  is.ignore ();
4204  if (std::isxdigit (is.peek ()))
4205  is >> std::hex >> value >> std::dec;
4206  else
4207  value = 0;
4208  }
4209  else
4210  {
4211  if (c2 == '0' || c2 == '1' || c2 == '2'
4212  || c2 == '3' || c2 == '4' || c2 == '5'
4213  || c2 == '6' || c2 == '7')
4214  is >> std::oct >> value >> std::dec;
4215  else if (c2 == '8' || c2 == '9')
4216  {
4217  // FIXME: Would like to set error state on octave
4218  // stream. See bug #46493. But only std::istream is
4219  // input to fcn.
4220  // error ("internal failure to match octal format");
4221  value = 0;
4222  }
4223  else
4224  value = 0;
4225  }
4226  }
4227  else
4228  {
4229  is.putback (c1);
4230 
4231  is >> value;
4232  }
4233  }
4234  }
4235  break;
4236 
4237  default:
4238  is >> value;
4239  break;
4240  }
4241 
4242  // If conversion produces an integer that overflows, failbit is set but
4243  // value is non-zero. We want to treat this case as success, so clear
4244  // failbit from the stream state to keep going.
4245  // FIXME: Maybe set error state on octave stream as above? Matlab does
4246  // *not* indicate an error message on overflow.
4247  if ((is.rdstate () & std::ios::failbit) && value != T ())
4248  is.clear (is.rdstate () & ~std::ios::failbit);
4249 
4250  // Only copy the converted value if the stream is in a state where we
4251  // want to continue reading.
4252  if (! (is.rdstate () & std::ios::failbit))
4253  *valptr = value;
4254 
4255  return is;
4256 }
4257 
4258 template <typename T>
4259 std::istream&
4260 octave_scan (std::istream& is, const scanf_format_elt& fmt, T* valptr)
4261 {
4262  if (fmt.width)
4263  {
4264  // Limit input to fmt.width characters by reading into a
4265  // temporary stringstream buffer.
4266  std::string tmp;
4267 
4268  is.width (fmt.width);
4269  is >> tmp;
4270 
4271  std::istringstream ss (tmp);
4272 
4273  octave_scan_1 (ss, fmt, valptr);
4274  }
4275  else
4276  octave_scan_1 (is, fmt, valptr);
4277 
4278  return is;
4279 }
4280 
4281 // Note that this specialization is only used for reading characters, not
4282 // character strings. See BEGIN_S_CONVERSION for details.
4283 
4284 template <>
4285 std::istream&
4286 octave_scan<> (std::istream& is, const scanf_format_elt& /* fmt */,
4287  char* valptr)
4288 {
4289  return is >> valptr;
4290 }
4291 
4292 template <>
4293 std::istream&
4294 octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double* valptr)
4295 {
4296  double& ref = *valptr;
4297 
4298  switch (fmt.type)
4299  {
4300  case 'e':
4301  case 'f':
4302  case 'g':
4303  {
4304  int c1 = std::istream::traits_type::eof ();
4305 
4306  while (is && (c1 = is.get ()) != std::istream::traits_type::eof ()
4307  && isspace (c1))
4308  ; // skip whitespace
4309 
4310  if (c1 != std::istream::traits_type::eof ())
4311  {
4312  is.putback (c1);
4313 
4314  ref = octave_read_value<double> (is);
4315  }
4316  }
4317  break;
4318 
4319  default:
4320  panic_impossible ();
4321  break;
4322  }
4323 
4324  return is;
4325 }
4326 
4327 template <typename T>
4328 void
4329 do_scanf_conv (std::istream& is, const scanf_format_elt& fmt,
4330  T valptr, Matrix& mval, double *data, octave_idx_type& idx,
4331  octave_idx_type& conversion_count, octave_idx_type nr,
4332  octave_idx_type max_size, bool discard)
4333 {
4334  octave_scan (is, fmt, valptr);
4335 
4336  if (! is)
4337  return;
4338 
4339  if (idx == max_size && ! discard)
4340  {
4341  max_size *= 2;
4342 
4343  if (nr > 0)
4344  mval.resize (nr, max_size / nr, 0.0);
4345  else
4346  mval.resize (max_size, 1, 0.0);
4347 
4348  data = mval.fortran_vec ();
4349  }
4350 
4351  if (! discard)
4352  {
4353  conversion_count++;
4354  data[idx++] = *(valptr);
4355  }
4356 }
4357 
4358 template void
4359 do_scanf_conv (std::istream&, const scanf_format_elt&, double*,
4360  Matrix&, double*, octave_idx_type&, octave_idx_type&,
4362 
4363 #define DO_WHITESPACE_CONVERSION() \
4364  do \
4365  { \
4366  int c = std::istream::traits_type::eof (); \
4367  \
4368  while (is && (c = is.get ()) != std::istream::traits_type::eof () \
4369  && isspace (c)) \
4370  { /* skip whitespace */ } \
4371  \
4372  if (c != std::istream::traits_type::eof ()) \
4373  is.putback (c); \
4374  } \
4375  while (0)
4376 
4377 #define DO_LITERAL_CONVERSION() \
4378  do \
4379  { \
4380  int c = std::istream::traits_type::eof (); \
4381  \
4382  int n = strlen (fmt); \
4383  int i = 0; \
4384  \
4385  while (i < n && is && (c = is.get ()) != std::istream::traits_type::eof ()) \
4386  { \
4387  if (c == static_cast<unsigned char> (fmt[i])) \
4388  { \
4389  i++; \
4390  continue; \
4391  } \
4392  else \
4393  { \
4394  is.putback (c); \
4395  break; \
4396  } \
4397  } \
4398  \
4399  if (i != n) \
4400  is.setstate (std::ios::failbit); \
4401  } \
4402  while (0)
4403 
4404 #define DO_PCT_CONVERSION() \
4405  do \
4406  { \
4407  int c = is.get (); \
4408  \
4409  if (c != std::istream::traits_type::eof ()) \
4410  { \
4411  if (c != '%') \
4412  { \
4413  is.putback (c); \
4414  is.setstate (std::ios::failbit); \
4415  } \
4416  } \
4417  else \
4418  is.setstate (std::ios::failbit); \
4419  } \
4420  while (0)
4421 
4422 #define BEGIN_C_CONVERSION() \
4423  is.unsetf (std::ios::skipws); \
4424  \
4425  int width = elt->width ? elt->width : 1; \
4426  \
4427  std::string tmp (width, '\0'); \
4428  \
4429  int c = std::istream::traits_type::eof (); \
4430  int n = 0; \
4431  \
4432  while (is && n < width \
4433  && (c = is.get ()) != std::istream::traits_type::eof ()) \
4434  tmp[n++] = static_cast<char> (c); \
4435  \
4436  if (n > 0 && c == std::istream::traits_type::eof ()) \
4437  is.clear (); \
4438  \
4439  tmp.resize (n)
4440 
4441 // For a '%s' format, skip initial whitespace and then read until the
4442 // next whitespace character or until WIDTH characters have been read.
4443 #define BEGIN_S_CONVERSION() \
4444  int width = elt->width; \
4445  \
4446  std::string tmp; \
4447  \
4448  do \
4449  { \
4450  if (width) \
4451  { \
4452  tmp = std::string (width, '\0'); \
4453  \
4454  int c = std::istream::traits_type::eof (); \
4455  \
4456  int n = 0; \
4457  \
4458  while (is && (c = is.get ()) != std::istream::traits_type::eof ()) \
4459  { \
4460  if (! isspace (c)) \
4461  { \
4462  tmp[n++] = static_cast<char> (c); \
4463  break; \
4464  } \
4465  } \
4466  \
4467  while (is && n < width \
4468  && (c = is.get ()) != std::istream::traits_type::eof ()) \
4469  { \
4470  if (isspace (c)) \
4471  { \
4472  is.putback (c); \
4473  break; \
4474  } \
4475  else \
4476  tmp[n++] = static_cast<char> (c); \
4477  } \
4478  \
4479  if (n > 0 && c == std::istream::traits_type::eof ()) \
4480  is.clear (); \
4481  \
4482  tmp.resize (n); \
4483  } \
4484  else \
4485  { \
4486  is >> std::ws >> tmp; \
4487  } \
4488  } \
4489  while (0)
4490 
4491 // This format must match a nonempty sequence of characters.
4492 #define BEGIN_CHAR_CLASS_CONVERSION() \
4493  int width = elt->width; \
4494  \
4495  std::string tmp; \
4496  \
4497  do \
4498  { \
4499  if (! width) \
4500  width = std::numeric_limits<int>::max (); \
4501  \
4502  std::ostringstream buf; \
4503  \
4504  std::string char_class = elt->char_class; \
4505  \
4506  int c = std::istream::traits_type::eof (); \
4507  \
4508  if (elt->type == '[') \
4509  { \
4510  int chars_read = 0; \
4511  while (is && chars_read++ < width \
4512  && (c = is.get ()) != std::istream::traits_type::eof () \
4513  && char_class.find (c) != std::string::npos) \
4514  buf << static_cast<char> (c); \
4515  } \
4516  else \
4517  { \
4518  int chars_read = 0; \
4519  while (is && chars_read++ < width \
4520  && (c = is.get ()) != std::istream::traits_type::eof () \
4521  && char_class.find (c) == std::string::npos) \
4522  buf << static_cast<char> (c); \
4523  } \
4524  \
4525  if (width == std::numeric_limits<int>::max () \
4526  && c != std::istream::traits_type::eof ()) \
4527  is.putback (c); \
4528  \
4529  tmp = buf.str (); \
4530  \
4531  if (tmp.empty ()) \
4532  is.setstate (std::ios::failbit); \
4533  else if (c == std::istream::traits_type::eof ()) \
4534  is.clear (); \
4535  \
4536  } \
4537  while (0)
4538 
4539 #define FINISH_CHARACTER_CONVERSION() \
4540  do \
4541  { \
4542  width = tmp.length (); \
4543  \
4544  if (is) \
4545  { \
4546  int i = 0; \
4547  \
4548  if (! discard) \
4549  { \
4550  conversion_count++; \
4551  \
4552  while (i < width) \
4553  { \
4554  if (data_index == max_size) \
4555  { \
4556  max_size *= 2; \
4557  \
4558  if (all_char_conv) \
4559  { \
4560  if (one_elt_size_spec) \
4561  mval.resize (1, max_size, 0.0); \
4562  else if (nr > 0) \
4563  mval.resize (nr, max_size / nr, 0.0); \
4564  else \
4565  panic_impossible (); \
4566  } \
4567  else if (nr > 0) \
4568  mval.resize (nr, max_size / nr, 0.0); \
4569  else \
4570  mval.resize (max_size, 1, 0.0); \
4571  \
4572  data = mval.fortran_vec (); \
4573  } \
4574  \
4575  data[data_index++] = tmp[i++]; \
4576  } \
4577  } \
4578  } \
4579  } \
4580  while (0)
4581 
4585  bool one_elt_size_spec,
4586  octave_idx_type& conversion_count,
4587  const std::string& who)
4588 {
4589  if (octave::application::interactive () && file_number () == 0)
4590  ::error ("%s: unable to read from stdin while running interactively",
4591  who.c_str ());
4592 
4593  octave_value retval = Matrix ();
4594 
4595  conversion_count = 0;
4596 
4597  octave_idx_type nconv = fmt_list.num_conversions ();
4598 
4599  octave_idx_type data_index = 0;
4600 
4601  if (nr == 0 || nc == 0)
4602  {
4603  if (one_elt_size_spec)
4604  nc = 0;
4605 
4606  return Matrix (nr, nc, 0.0);
4607  }
4608 
4609  std::istream *isp = input_stream ();
4610 
4611  bool all_char_conv = fmt_list.all_character_conversions ();
4612 
4613  Matrix mval;
4614  double *data = 0;
4615  octave_idx_type max_size = 0;
4616  octave_idx_type max_conv = 0;
4617 
4618  octave_idx_type final_nr = 0;
4619  octave_idx_type final_nc = 0;
4620 
4621  if (all_char_conv)
4622  {
4623  // Any of these could be resized later (if we have %s conversions,
4624  // we may read more than one element for each conversion).
4625  if (one_elt_size_spec)
4626  {
4627  max_size = 512;
4628  mval.resize (1, max_size, 0.0);
4629 
4630  if (nr > 0)
4631  max_conv = nr;
4632  }
4633  else if (nr > 0)
4634  {
4635  if (nc > 0)
4636  {
4637  mval.resize (nr, nc, 0.0);
4638  max_size = max_conv = nr * nc;
4639  }
4640  else
4641  {
4642  mval.resize (nr, 32, 0.0);
4643  max_size = nr * 32;
4644  }
4645  }
4646  else
4647  panic_impossible ();
4648  }
4649  else if (nr > 0)
4650  {
4651  if (nc > 0)
4652  {
4653  // Will not resize later.
4654  mval.resize (nr, nc, 0.0);
4655  max_size = nr * nc;
4656  max_conv = max_size;
4657  }
4658  else
4659  {
4660  // Maybe resize later.
4661  mval.resize (nr, 32, 0.0);
4662  max_size = nr * 32;
4663  }
4664  }
4665  else
4666  {
4667  // Maybe resize later.
4668  mval.resize (32, 1, 0.0);
4669  max_size = 32;
4670  }
4671 
4672  data = mval.fortran_vec ();
4673 
4674  if (isp)
4675  {
4676  std::istream& is = *isp;
4677 
4678  const scanf_format_elt *elt = fmt_list.first ();
4679 
4680  std::ios::fmtflags flags = is.flags ();
4681 
4682  octave_idx_type trips = 0;
4683 
4684  octave_idx_type num_fmt_elts = fmt_list.length ();
4685 
4686  for (;;)
4687  {
4688  octave_quit ();
4689 
4690  if (elt)
4691  {
4692  if (elt->type == scanf_format_elt::null
4695  || elt->type == '%')
4696  && max_conv > 0 && conversion_count == max_conv))
4697  {
4698  // We are done, either because we have reached the end of the
4699  // format string and are not cycling through the format again
4700  // or because we've converted all the values that have been
4701  // requested and the next format element is a conversion.
4702  // Determine final array size and exit.
4703  if (all_char_conv && one_elt_size_spec)
4704  {
4705  final_nr = 1;
4706  final_nc = data_index;
4707  }
4708  else
4709  {
4710  final_nr = nr;
4711  final_nc = (data_index - 1) / nr + 1;
4712  }
4713 
4714  break;
4715  }
4716  else if (data_index == max_size)
4717  {
4718  max_size *= 2;
4719 
4720  if (all_char_conv)
4721  {
4722  if (one_elt_size_spec)
4723  mval.resize (1, max_size, 0.0);
4724  else if (nr > 0)
4725  mval.resize (nr, max_size / nr, 0.0);
4726  else
4727  panic_impossible ();
4728  }
4729  else if (nr > 0)
4730  mval.resize (nr, max_size / nr, 0.0);
4731  else
4732  mval.resize (max_size, 1, 0.0);
4733 
4734  data = mval.fortran_vec ();
4735  }
4736 
4737  const char *fmt = elt->text;
4738 
4739  bool discard = elt->discard;
4740 
4741  switch (elt->type)
4742  {
4745  break;
4746 
4749  break;
4750 
4751  case '%':
4752  DO_PCT_CONVERSION ();
4753  break;
4754 
4755  case 'd': case 'i':
4756  {
4757  switch (elt->modifier)
4758  {
4759  case 'h':
4760  {
4761  int16_t tmp;
4762  do_scanf_conv (is, *elt, &tmp, mval, data,
4763  data_index, conversion_count,
4764  nr, max_size, discard);
4765  }
4766  break;
4767 
4768  case 'l':
4769  {
4770  int64_t tmp;
4771  do_scanf_conv (is, *elt, &tmp, mval, data,
4772  data_index, conversion_count,
4773  nr, max_size, discard);
4774  }
4775  break;
4776 
4777  default:
4778  {
4779  int32_t tmp;
4780  do_scanf_conv (is, *elt, &tmp, mval, data,
4781  data_index, conversion_count,
4782  nr, max_size, discard);
4783  }
4784  break;
4785  }
4786  }
4787  break;
4788 
4789  case 'o': case 'u': case 'x':
4790  {
4791  switch (elt->modifier)
4792  {
4793  case 'h':
4794  {
4795  uint16_t tmp;
4796  do_scanf_conv (is, *elt, &tmp, mval, data,
4797  data_index, conversion_count,
4798  nr, max_size, discard);
4799  }
4800  break;
4801 
4802  case 'l':
4803  {
4804  uint64_t tmp;
4805  do_scanf_conv (is, *elt, &tmp, mval, data,
4806  data_index, conversion_count,
4807  nr, max_size, discard);
4808  }
4809  break;
4810 
4811  default:
4812  {
4813  uint32_t tmp;
4814  do_scanf_conv (is, *elt, &tmp, mval, data,
4815  data_index, conversion_count,
4816  nr, max_size, discard);
4817  }
4818  break;
4819  }
4820  }
4821  break;
4822 
4823  case 'e': case 'f': case 'g':
4824  {
4825  double tmp;
4826 
4827  do_scanf_conv (is, *elt, &tmp, mval, data,
4828  data_index, conversion_count,
4829  nr, max_size, discard);
4830  }
4831  break;
4832 
4833  case 'c':
4834  {
4835  BEGIN_C_CONVERSION ();
4836 
4838 
4839  is.setf (flags);
4840  }
4841  break;
4842 
4843  case 's':
4844  {
4845  BEGIN_S_CONVERSION ();
4846 
4848  }
4849  break;
4850 
4851  case '[': case '^':
4852  {
4854 
4856  }
4857  break;
4858 
4859  case 'p':
4860  error ("%s: unsupported format specifier", who.c_str ());
4861  break;
4862 
4863  default:
4864  error ("%s: internal format error", who.c_str ());
4865  break;
4866  }
4867 
4868  if (! ok ())
4869  {
4870  break;
4871  }
4872  else if (! is)
4873  {
4874  if (all_char_conv)
4875  {
4876  if (one_elt_size_spec)
4877  {
4878  final_nr = 1;
4879  final_nc = data_index;
4880  }
4881  else if (data_index > nr)
4882  {
4883  final_nr = nr;
4884  final_nc = (data_index - 1) / nr + 1;
4885  }
4886  else
4887  {
4888  final_nr = data_index;
4889  final_nc = 1;
4890  }
4891  }
4892  else if (nr > 0)
4893  {
4894  if (data_index > nr)
4895  {
4896  final_nr = nr;
4897  final_nc = (data_index - 1) / nr + 1;
4898  }
4899  else
4900  {
4901  final_nr = data_index;
4902  final_nc = 1;
4903  }
4904  }
4905  else
4906  {
4907  final_nr = data_index;
4908  final_nc = 1;
4909  }
4910 
4911  // If it looks like we have a matching failure, then
4912  // reset the failbit in the stream state.
4913  if (is.rdstate () & std::ios::failbit)
4914  is.clear (is.rdstate () & (~std::ios::failbit));
4915 
4916  // FIXME: is this the right thing to do?
4917  if (octave::application::interactive ()
4918  && ! octave::application::forced_interactive ()
4919  && name () == "stdin")
4920  {
4921  is.clear ();
4922 
4923  // Skip to end of line.
4924  bool err;
4925  do_gets (-1, err, false, who);
4926  }
4927 
4928  break;
4929  }
4930  }
4931  else
4932  {
4933  error ("%s: internal format error", who.c_str ());
4934  break;
4935  }
4936 
4937  if (nconv == 0 && ++trips == num_fmt_elts)
4938  {
4939  if (all_char_conv && one_elt_size_spec)
4940  {
4941  final_nr = 1;
4942  final_nc = data_index;
4943  }
4944  else
4945  {
4946  final_nr = nr;
4947  final_nc = (data_index - 1) / nr + 1;
4948  }
4949 
4950  break;
4951  }
4952  else
4953  {
4954  // Cycle through the format list more than once if we have some
4955  // conversions to make and we haven't reached the limit on the
4956  // number of values to convert (possibly because there is no
4957  // specified limit).
4958  elt = fmt_list.next (nconv > 0
4959  && (max_conv == 0
4960  || conversion_count < max_conv));
4961  }
4962  }
4963  }
4964 
4965  if (ok ())
4966  {
4967  mval.resize (final_nr, final_nc, 0.0);
4968 
4969  retval = mval;
4970 
4971  if (all_char_conv)
4972  retval = retval.convert_to_str (false, true);
4973  }
4974 
4975  return retval;
4976 }
4977 
4980  octave_idx_type& conversion_count,
4981  const std::string& who)
4982 {
4983  octave_value retval = Matrix ();
4984 
4985  conversion_count = 0;
4986 
4987  std::istream *isp = input_stream ();
4988 
4989  if (! isp)
4990  invalid_operation (who, "reading");
4991  else
4992  {
4993  scanf_format_list fmt_list (fmt);
4994 
4995  if (fmt_list.num_conversions () == -1)
4996  ::error ("%s: invalid format specified", who.c_str ());
4997 
4998  octave_idx_type nr = -1;
4999  octave_idx_type nc = -1;
5000 
5001  bool one_elt_size_spec;
5002 
5003  get_size (size, nr, nc, one_elt_size_spec, who);
5004 
5005  retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec,
5006  conversion_count, who);
5007  }
5008 
5009  return retval;
5010 }
5011 
5012 bool
5013 octave_base_stream::do_oscanf (const scanf_format_elt *elt,
5014  octave_value& retval, const std::string& who)
5015 {
5016  std::istream *isp = input_stream ();
5017 
5018  if (! isp)
5019  return false;
5020 
5021  bool quit = false;
5022 
5023  std::istream& is = *isp;
5024 
5025  std::ios::fmtflags flags = is.flags ();
5026 
5027  if (elt)
5028  {
5029  const char *fmt = elt->text;
5030 
5031  bool discard = elt->discard;
5032 
5033  switch (elt->type)
5034  {
5037  break;
5038 
5041  break;
5042 
5043  case '%':
5044  {
5045  DO_PCT_CONVERSION ();
5046 
5047  if (! is)
5048  quit = true;
5049  }
5050  break;
5051 
5052  case 'd': case 'i':
5053  {
5054  int tmp;
5055 
5056  if (octave_scan (is, *elt, &tmp))
5057  {
5058  if (! discard)
5059  retval = tmp;
5060  }
5061  else
5062  quit = true;
5063  }
5064  break;
5065 
5066  case 'o': case 'u': case 'x':
5067  {
5068  long int tmp;
5069 
5070  if (octave_scan (is, *elt, &tmp))
5071  {
5072  if (! discard)
5073  retval = tmp;
5074  }
5075  else
5076  quit = true;
5077  }
5078  break;
5079 
5080  case 'e': case 'f': case 'g':
5081  {
5082  double tmp;
5083 
5084  if (octave_scan (is, *elt, &tmp))
5085  {
5086  if (! discard)
5087  retval = tmp;
5088  }
5089  else
5090  quit = true;
5091  }
5092  break;
5093 
5094  case 'c':
5095  {
5096  BEGIN_C_CONVERSION ();
5097 
5098  if (! discard)
5099  retval = tmp;
5100 
5101  if (! is)
5102  quit = true;
5103 
5104  is.setf (flags);
5105  }
5106  break;
5107 
5108  case 's':
5109  {
5110  BEGIN_S_CONVERSION ();
5111 
5112  if (! discard)
5113  retval = tmp;
5114 
5115  if (! is)
5116  quit = true;
5117  }
5118  break;
5119 
5120  case '[':
5121  case '^':
5122  {
5124 
5125  if (! discard)
5126  retval = tmp;
5127 
5128  if (! is)
5129  quit = true;
5130  }
5131  break;
5132 
5133  case 'p':
5134  error ("%s: unsupported format specifier", who.c_str ());
5135  break;
5136 
5137  default:
5138  error ("%s: internal format error", who.c_str ());
5139  break;
5140  }
5141  }
5142 
5143  if (ok () && is.fail ())
5144  {
5145  error ("%s: read error", who.c_str ());
5146 
5147  // FIXME: is this the right thing to do?
5148 
5149  if (octave::application::interactive ()
5150  && ! octave::application::forced_interactive ()
5151  && name () == "stdin")
5152  {
5153  // Skip to end of line.
5154  bool err;
5155  do_gets (-1, err, false, who);
5156  }
5157  }
5158 
5159  return quit;
5160 }
5161 
5164 {
5166 
5167  std::istream *isp = input_stream ();
5168 
5169  if (! isp)
5170  invalid_operation (who, "reading");
5171  else
5172  {
5173  std::istream& is = *isp;
5174 
5175  scanf_format_list fmt_list (fmt);
5176 
5177  octave_idx_type nconv = fmt_list.num_conversions ();
5178 
5179  if (nconv == -1)
5180  ::error ("%s: invalid format specified", who.c_str ());
5181 
5182  is.clear ();
5183 
5184  octave_idx_type len = fmt_list.length ();
5185 
5186  retval.resize (nconv+2, Matrix ());
5187 
5188  const scanf_format_elt *elt = fmt_list.first ();
5189 
5190  int num_values = 0;
5191 
5192  bool quit = false;
5193 
5194  for (octave_idx_type i = 0; i < len; i++)
5195  {
5196  octave_value tmp;
5197 
5198  quit = do_oscanf (elt, tmp, who);
5199 
5200  if (quit)
5201  break;
5202  else
5203  {
5204  if (tmp.is_defined ())
5205  retval(num_values++) = tmp;
5206 
5207  if (! ok ())
5208  break;
5209 
5210  elt = fmt_list.next (nconv > 0);
5211  }
5212  }
5213 
5214  retval(nconv) = num_values;
5215 
5216  int err_num;
5217  retval(nconv+1) = error (false, err_num);
5218 
5219  if (! quit)
5220  {
5221  // Pick up any trailing stuff.
5222  if (ok () && len > nconv)
5223  {
5224  octave_value tmp;
5225 
5226  elt = fmt_list.next ();
5227 
5228  do_oscanf (elt, tmp, who);
5229  }
5230  }
5231  }
5232 
5233  return retval;
5234 }
5235 
5238  octave_idx_type ntimes,
5239  const octave_value_list& options,
5240  const std::string& who,
5241  octave_idx_type& read_count)
5242 {
5243  if (octave::application::interactive () && file_number () == 0)
5244  ::error ("%s: unable to read from stdin while running interactively",
5245  who.c_str ());
5246 
5247  octave_value retval = Cell (dim_vector (1, 1), Matrix (0, 1));
5248 
5249  std::istream *isp = input_stream ();
5250 
5251  if (! isp)
5252  invalid_operation (who, "reading");
5253  else
5254  {
5255  octave::textscan scanner (who);
5256 
5257  retval = scanner.scan (*isp, fmt, ntimes, options, read_count);
5258  }
5259 
5260  return retval;
5261 }
5262 
5263 // Functions that are defined for all output streams
5264 // (output streams are those that define os).
5265 
5266 int
5268 {
5269  int retval = -1;
5270 
5271  std::ostream *os = output_stream ();
5272 
5273  if (! os)
5274  invalid_operation ("fflush", "writing");
5275  else
5276  {
5277  os->flush ();
5278 
5279  if (os->good ())
5280  retval = 0;
5281  }
5282 
5283  return retval;
5284 }
5285 
5286 class
5288 {
5289 public:
5290 
5291  enum state { ok, conversion_error };
5292 
5294  : values (args), val_idx (0), elt_idx (0),
5295  n_vals (values.length ()), n_elts (0), have_data (false),
5296  curr_state (ok)
5297  {
5298  for (octave_idx_type i = 0; i < values.length (); i++)
5299  {
5300  octave_value val = values(i);
5301 
5302  if (val.is_map () || val.is_cell () || val.is_object ())
5303  err_wrong_type_arg (who, val);
5304  }
5305  }
5306 
5308 
5309  // Get the current value as a double and advance the internal pointer.
5310  octave_value get_next_value (char type = 0);
5311 
5312  // Get the current value as an int and advance the internal pointer.
5313  int int_value (void);
5314 
5315  operator bool () const { return (curr_state == ok); }
5316 
5317  bool exhausted (void) { return (val_idx >= n_vals); }
5318 
5319 private:
5320 
5322  int val_idx;
5323  int elt_idx;
5324  int n_vals;
5325  int n_elts;
5329 
5330  // Must create value cache with values!
5331 
5332  printf_value_cache (void);
5333 
5334  // No copying!
5335 
5337 
5338  printf_value_cache& operator = (const printf_value_cache&);
5339 };
5340 
5343 {
5345 
5346  if (exhausted ())
5348 
5349  while (! exhausted ())
5350  {
5351  if (! have_data)
5352  {
5353  curr_val = values (val_idx);
5354 
5355  elt_idx = 0;
5356  n_elts = curr_val.numel ();
5357  have_data = true;
5358  }
5359 
5360  if (elt_idx < n_elts)
5361  {
5362  if (type == 's')
5363  {
5364  if (curr_val.is_string ())
5365  {
5366  dim_vector dv (1, curr_val.numel ());
5368 
5369  std::string sval = tmp.string_value ();
5370 
5371  retval = sval.substr (elt_idx);
5372 
5373  // We've consumed the rest of the value.
5374  elt_idx = n_elts;
5375  }
5376  else
5377  {
5378  // Convert to character string while values are
5379  // integers in the range [0 : char max]
5380  const NDArray val = curr_val.array_value ();
5381 
5382  octave_idx_type idx = elt_idx;
5383 
5384  for (; idx < n_elts; idx++)
5385  {
5386  double dval = val(idx);
5387 
5388  if (octave::math::x_nint (dval) != dval || dval < 0 || dval > 255)
5389  break;
5390  }
5391 
5392  octave_idx_type n = idx - elt_idx;
5393 
5394  if (n > 0)
5395  {
5396  std::string sval (n, '\0');
5397 
5398  for (octave_idx_type i = 0; i < n; i++)
5399  sval[i] = val(elt_idx++);
5400 
5401  retval = sval;
5402  }
5403  else
5404  retval = curr_val.fast_elem_extract (elt_idx++);
5405  }
5406  }
5407  else
5408  {
5409  retval = curr_val.fast_elem_extract (elt_idx++);
5410 
5411  if (type == 'c' && ! retval.is_string ())
5412  {
5413  double dval = retval.double_value ();
5414 
5415  if (octave::math::x_nint (dval) == dval && dval >= 0 && dval < 256)
5416  retval = static_cast<char> (dval);
5417  }
5418  }
5419 
5420  if (elt_idx >= n_elts)
5421  {
5422  elt_idx = 0;
5423  val_idx++;
5424  have_data = false;
5425  }
5426 
5427  break;
5428  }
5429  else
5430  {
5431  val_idx++;
5432  have_data = false;
5433 
5434  if (n_elts == 0)
5435  {
5436  if (elt_idx == 0 && (type == 's' || type == 'c'))
5437  {
5438  retval = "";
5439  break;
5440  }
5441 
5442  if (exhausted ())
5444  }
5445  }
5446  }
5447 
5448  return retval;
5449 }
5450 
5451 int
5453 {
5454  int retval = 0;
5455 
5457 
5458  double dval = val.double_value (true);
5459 
5460  if (octave::math::x_nint (dval) == dval)
5461  retval = octave::math::nint (dval);
5462  else
5464 
5465  return retval;
5466 }
5467 
5468 // Ugh again and again.
5469 
5470 template <typename T>
5471 int
5472 do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1,
5473  int sa_2, T arg, const std::string& who)
5474 {
5475  int retval = 0;
5476 
5477  switch (nsa)
5478  {
5479  case 2:
5480  retval = octave_format (os, fmt, sa_1, sa_2, arg);
5481  break;
5482 
5483  case 1:
5484  retval = octave_format (os, fmt, sa_1, arg);
5485  break;
5486 
5487  case 0:
5488  retval = octave_format (os, fmt, arg);
5489  break;
5490 
5491  default:
5492  ::error ("%s: internal error handling format", who.c_str ());
5493  break;
5494  }
5495 
5496  return retval;
5497 }
5498 
5499 static size_t
5500 do_printf_string (std::ostream& os, const printf_format_elt *elt,
5501  int nsa, int sa_1, int sa_2, const std::string& arg,
5502  const std::string& who)
5503 {
5504  if (nsa > 2)
5505  ::error ("%s: internal error handling format", who.c_str ());
5506 
5507  std::string flags = elt->flags;
5508 
5509  bool left = flags.find ('-') != std::string::npos;
5510 
5511  size_t len = arg.length ();
5512 
5513  size_t fw = nsa > 0 ? sa_1 : (elt->fw == -1 ? len : elt->fw);
5514  size_t prec = nsa > 1 ? sa_2 : (elt->prec == -1 ? len : elt->prec);
5515 
5516  os << std::setw (fw)
5517  << (left ? std::left : std::right)
5518  << (prec < len ? arg.substr (0, prec) : arg);
5519 
5520  return len > fw ? len : fw;
5521 }
5522 
5523 static bool
5525 {
5526  octave_value ov_isnan = val.isnan ();
5527  octave_value ov_isinf = val.isinf ();
5528 
5529  return (ov_isnan.is_true () || ov_isinf.is_true ());
5530 }
5531 
5532 static bool
5534 {
5535  uint64_t limit = std::numeric_limits<int64_t>::max ();
5536 
5537  if (val.is_string ())
5538  return true;
5539  else if (val.is_integer_type ())
5540  {
5541  if (val.is_uint64_type ())
5542  {
5543  octave_uint64 ival = val.uint64_scalar_value ();
5544 
5545  if (ival.value () <= limit)
5546  return true;
5547  }
5548  else
5549  return true;
5550  }
5551  else
5552  {
5553  double dval = val.double_value (true);
5554 
5555  if (dval == octave::math::round (dval) && dval <= limit)
5556  return true;
5557  }
5558 
5559  return false;
5560 }
5561 
5562 static bool
5564 {
5565  if (val.is_string ())
5566  return true;
5567  else if (val.is_integer_type ())
5568  {
5569  // Easier than dispatching here...
5570 
5571  octave_value ov_is_ge_zero
5573 
5574  return ov_is_ge_zero.is_true ();
5575  }
5576  else
5577  {
5578  double dval = val.double_value (true);
5579 
5580  uint64_t limit = std::numeric_limits<uint64_t>::max ();
5581 
5582  if (dval == octave::math::round (dval) && dval >= 0 && dval <= limit)
5583  return true;
5584  }
5585 
5586  return false;
5587 }
5588 
5589 static std::string
5591 {
5592  std::string tfmt = elt->text;
5593 
5594  tfmt.replace (tfmt.rfind (elt->type), 1, "g");
5595 
5596  return tfmt;
5597 }
5598 
5599 int
5601  const printf_format_elt *elt,
5602  int nsa, int sa_1, int sa_2,
5603  const octave_value& val,
5604  const std::string& who)
5605 {
5606  int retval = 0;
5607 
5608  const char *fmt = elt->text;
5609 
5610  if (is_nan_or_inf (val))
5611  {
5612  double dval = val.double_value ();
5613 
5614  std::string tfmt = fmt;
5615  std::string::size_type i1, i2;
5616 
5617  tfmt.replace ((i1 = tfmt.rfind (elt->type)), 1, 1, 's');
5618 
5619  if ((i2 = tfmt.rfind ('.')) != std::string::npos && i2 < i1)
5620  {
5621  tfmt.erase (i2, i1-i2);
5622  if (elt->prec == -2)
5623  nsa--;
5624  }
5625 
5626  const char *tval;
5627  if (lo_ieee_isinf (dval))
5628  {
5629  if (elt->flags.find ('+') != std::string::npos)
5630  tval = (dval < 0 ? "-Inf" : "+Inf");
5631  else
5632  tval = (dval < 0 ? "-Inf" : "Inf");
5633  }
5634  else
5635  {
5636  if (elt->flags.find ('+') != std::string::npos)
5637  tval = (lo_ieee_is_NA (dval) ? "+NA" : "+NaN");
5638  else
5639  tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN");
5640  }
5641 
5642  retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, who);
5643  }
5644  else
5645  {
5646  static std::string llmod
5647  = sizeof (long) == sizeof (int64_t) ? "l" : "ll";
5648 
5649  char type = elt->type;
5650 
5651  switch (type)
5652  {
5653  case 'd': case 'i': case 'c':
5654  if (ok_for_signed_int_conv (val))
5655  {
5656  octave_int64 tval = val.int64_scalar_value ();
5657 
5658  // Insert "long" modifier.
5659  std::string tfmt = fmt;
5660  tfmt.replace (tfmt.rfind (type), 1, llmod + type);
5661 
5662  retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
5663  tval.value (), who);
5664  }
5665  else
5666  {
5667  std::string tfmt = switch_to_g_format (elt);
5668 
5669  double dval = val.double_value (true);
5670 
5671  retval += do_printf_conv (os, tfmt.c_str (), nsa,
5672  sa_1, sa_2, dval, who);
5673  }
5674  break;
5675 
5676  case 'o': case 'x': case 'X': case 'u':
5677  if (ok_for_unsigned_int_conv (val))
5678  {
5679  octave_uint64 tval = val.uint64_scalar_value ();
5680 
5681  // Insert "long" modifier.
5682  std::string tfmt = fmt;
5683  tfmt.replace (tfmt.rfind (type), 1, llmod + type);
5684 
5685  retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
5686  tval.value (), who);
5687  }
5688  else
5689  {
5690  std::string tfmt = switch_to_g_format (elt);
5691 
5692  double dval = val.double_value (true);
5693 
5694  retval += do_printf_conv (os, tfmt.c_str (), nsa,
5695  sa_1, sa_2, dval, who);
5696  }
5697  break;
5698 
5699  case 'f': case 'e': case 'E':
5700  case 'g': case 'G':
5701  {
5702  double dval = val.double_value (true);
5703 
5704  retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, dval, who);
5705  }
5706  break;
5707 
5708  default:
5709  // Note: error is member fcn from octave_base_stream, not ::error.
5710  // This error does not halt execution so "return ..." must exist.
5711  error ("%s: invalid format specifier", who.c_str ());
5712  return -1;
5713  break;
5714  }
5715  }
5716 
5717  return retval;
5718 }
5719 
5720 int
5722  const octave_value_list& args,
5723  const std::string& who)
5724 {
5725  int retval = 0;
5726 
5727  octave_idx_type nconv = fmt_list.num_conversions ();
5728 
5729  std::ostream *osp = output_stream ();
5730 
5731  if (! osp)
5732  invalid_operation (who, "writing");
5733  else
5734  {
5735  std::ostream& os = *osp;
5736 
5737  const printf_format_elt *elt = fmt_list.first ();
5738 
5739  printf_value_cache val_cache (args, who);
5740 
5741  for (;;)
5742  {
5743  octave_quit ();
5744 
5745  if (! elt)
5746  ::error ("%s: internal error handling format", who.c_str ());
5747 
5748  // NSA is the number of 'star' args to convert.
5749  int nsa = (elt->fw == -2) + (elt->prec == -2);
5750 
5751  int sa_1 = 0;
5752  int sa_2 = 0;
5753 
5754  if (nsa > 0)
5755  {
5756  sa_1 = val_cache.int_value ();
5757 
5758  if (! val_cache)
5759  break;
5760  else
5761  {
5762  if (nsa > 1)
5763  {
5764  sa_2 = val_cache.int_value ();
5765 
5766  if (! val_cache)
5767  break;
5768  }
5769  }
5770  }
5771 
5772  if (elt->type == '%')
5773  {
5774  os << "%";
5775  retval++;
5776  }
5777  else if (elt->args == 0 && elt->text)
5778  {
5779  os << elt->text;
5780  retval += strlen (elt->text);
5781  }
5782  else if (elt->type == 's' || elt->type == 'c')
5783  {
5784  octave_value val = val_cache.get_next_value (elt->type);
5785 
5786  if (val_cache)
5787  {
5788  if (val.is_string ())
5789  {
5790  std::string sval = val.string_value ();
5791 
5792  retval += do_printf_string (os, elt, nsa, sa_1,
5793  sa_2, sval, who);
5794  }
5795  else
5796  retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
5797  sa_2, val, who);
5798  }
5799  else
5800  break;
5801  }
5802  else
5803  {
5804  octave_value val = val_cache.get_next_value ();
5805 
5806  if (val_cache)
5807  retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
5808  sa_2, val, who);
5809  else
5810  break;
5811  }
5812 
5813  if (! os)
5814  {
5815  error ("%s: write error", who.c_str ());
5816  break;
5817  }
5818 
5819  elt = fmt_list.next (nconv > 0 && ! val_cache.exhausted ());
5820 
5821  if (! elt || (val_cache.exhausted () && elt->args > 0))
5822  break;
5823  }
5824  }
5825 
5826  return retval;
5827 }
5828 
5829 int
5831  const octave_value_list& args,
5832  const std::string& who)
5833 {
5834  printf_format_list fmt_list (fmt);
5835 
5836  if (fmt_list.num_conversions () == -1)
5837  ::error ("%s: invalid format specified", who.c_str ());
5838 
5839  return do_printf (fmt_list, args, who);
5840 }
5841 
5842 int