home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21ep.zip / octave / SOURCE.ZIP / liboctave / cmd-edit.cc next >
C/C++ Source or Header  |  1999-05-30  |  18KB  |  1,010 lines

  1. /*
  2.  
  3. Copyright (C) 1996, 1997 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. #ifdef HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. #include <cstdlib>
  28. #include <cstring>
  29. #include <ctime>
  30.  
  31. #include <string>
  32.  
  33. #ifdef HAVE_UNISTD_H
  34. #ifdef HAVE_SYS_TYPES_H
  35. #include <sys/types.h>
  36. #endif
  37. #include <unistd.h>
  38. #endif
  39.  
  40. #include "cmd-edit.h"
  41. #include "cmd-hist.h"
  42. #include "lo-error.h"
  43. #include "lo-utils.h"
  44. #include "oct-env.h"
  45.  
  46. command_editor *command_editor::instance = 0;
  47.  
  48. #if defined (USE_READLINE)
  49.  
  50. #include <cstdio>
  51. #include <cstdlib>
  52.  
  53. #include <readline/readline.h>
  54.  
  55. #ifdef __EMX__
  56. extern "C"
  57. {
  58.   extern void tputs ();
  59.   extern char *term_clrpag;
  60.   extern void _rl_output_character_function ();
  61. }
  62. #endif
  63.  
  64. // It would be nice if readline.h declared these, I think.
  65.  
  66. extern int rl_blink_matching_paren;
  67.  
  68. extern int screenheight;
  69.  
  70. extern int screenwidth;
  71.  
  72. class
  73. gnu_readline : public command_editor
  74. {
  75. public:
  76.  
  77.   typedef command_editor::fcn fcn;
  78.  
  79.   typedef command_editor::completion_fcn completion_fcn;
  80.  
  81.   gnu_readline (void);
  82.  
  83.   ~gnu_readline (void) { }
  84.  
  85.   void do_set_name (const string& n);
  86.  
  87.   string do_readline (const string& prompt, bool& eof);
  88.  
  89.   void do_set_input_stream (FILE *f);
  90.  
  91.   FILE *do_get_input_stream (void);
  92.  
  93.   void do_set_output_stream (FILE *f);
  94.  
  95.   FILE *do_get_output_stream (void);
  96.  
  97.   int do_terminal_rows (void);
  98.  
  99.   int do_terminal_cols (void);
  100.  
  101.   void do_clear_screen (void);
  102.  
  103.   string newline_chars (void);
  104.  
  105.   void do_restore_terminal_state (void);
  106.  
  107.   void do_blink_matching_paren (bool flag);
  108.  
  109.   void do_set_basic_quote_characters (const string& s);
  110.  
  111.   void do_set_completion_append_character (char c);
  112.  
  113.   void do_set_completion_function (completion_fcn f);
  114.  
  115.   completion_fcn do_get_completion_function (void) const;
  116.  
  117.   void do_insert_text (const string& text);
  118.  
  119.   void do_newline (void);
  120.  
  121.   void do_clear_undo_list (void);
  122.  
  123.   void do_set_startup_hook (fcn f);
  124.  
  125.   void do_restore_startup_hook (void);
  126.  
  127.   void do_set_event_hook (fcn f);
  128.  
  129.   void do_restore_event_hook (void);
  130.  
  131.   void do_read_init_file (const string& file);
  132.  
  133.   static void operate_and_get_next (int, int);
  134.  
  135. private:
  136.  
  137.   fcn previous_startup_hook;
  138.  
  139.   fcn previous_event_hook;
  140.  
  141.   completion_fcn completion_function;
  142.  
  143.   static char *command_generator (const char *text, int state);
  144.  
  145.   static char **command_completer (char *text, int start, int end);
  146. };
  147.  
  148. gnu_readline::gnu_readline ()
  149.   : command_editor (), previous_startup_hook (0),
  150.     previous_event_hook (0), completion_function (0)
  151. {
  152.   rl_terminal_name = ::getenv ("TERM");
  153.  
  154.   rl_initialize ();
  155.  
  156.   do_blink_matching_paren (true);
  157.  
  158.   // Bind operate-and-get-next.
  159.  
  160.   rl_add_defun ("operate-and-get-next",
  161.         gnu_readline::operate_and_get_next, CTRL ('O'));
  162.  
  163.   // And the history search functions.
  164.  
  165.   rl_add_defun ("history-search-backward",
  166.         rl_history_search_backward, META ('p'));
  167.  
  168.   rl_add_defun ("history-search-forward",
  169.         rl_history_search_forward, META ('n'));
  170. }
  171.  
  172. void
  173. gnu_readline::do_set_name (const string& n)
  174. {
  175.   static char *nm = 0;
  176.  
  177.   delete [] nm;
  178.  
  179.   nm = strsave (n.c_str ());
  180.  
  181.   rl_readline_name = nm;
  182.  
  183.   // Since we've already called rl_initialize, we need to re-read the
  184.   // init file to take advantage of the conditional parsing feature
  185.   // based on rl_readline_name;
  186.  
  187.   rl_re_read_init_file ();
  188. }
  189.  
  190. string
  191. gnu_readline::do_readline (const string& prompt, bool& eof)
  192. {
  193.   string retval;
  194.  
  195.   eof = false;
  196.  
  197.   char *line = ::readline (prompt.c_str ());
  198.  
  199.   if (line)
  200.     {
  201.       retval = line;
  202.  
  203.       free (line);
  204.     }
  205.   else
  206.     eof = true;
  207.  
  208.   return retval;
  209. }
  210.  
  211. void
  212. gnu_readline::do_set_input_stream (FILE *f)
  213. {
  214.   rl_instream = f;
  215. }
  216.  
  217. FILE *
  218. gnu_readline::do_get_input_stream (void)
  219. {
  220.   return rl_instream;
  221. }
  222.  
  223. void
  224. gnu_readline::do_set_output_stream (FILE *f)
  225. {
  226.   rl_outstream = f;
  227. }
  228.  
  229. FILE *
  230. gnu_readline::do_get_output_stream (void)
  231. {
  232.   return rl_outstream;
  233. }
  234.  
  235. // GNU readline handles SIGWINCH, so these values have a good chance
  236. // of being correct even if the window changes size (they may be
  237. // wrong if, for example, the luser changes the window size while the
  238. // pager is running, and the signal is handled by the pager instead of
  239. // us.
  240.  
  241. int
  242. gnu_readline::do_terminal_rows (void)
  243. {
  244.   return screenheight > 0 ? screenheight : 24;
  245. }
  246.  
  247. int
  248. gnu_readline::do_terminal_cols (void)
  249. {
  250.   return screenwidth > 0 ? screenwidth : 80;
  251. }
  252.  
  253. void
  254. gnu_readline::do_clear_screen (void)
  255. {
  256. #ifdef __EMX__
  257.   rl_beg_of_line ();
  258.   rl_kill_line (1);
  259.  
  260.   if (term_clrpag)
  261.     tputs (term_clrpag, 1, _rl_output_character_function);
  262.   else
  263.     crlf ();
  264.  
  265.   fflush (rl_outstream);
  266. #else
  267.   rl_clear_screen ();
  268. #endif
  269. }
  270.  
  271. string
  272. gnu_readline::newline_chars (void)
  273. {
  274.   return "\r\n";
  275. }
  276.  
  277. void
  278. gnu_readline::do_restore_terminal_state (void)
  279. {
  280.   if (rl_deprep_term_function)
  281.     rl_deprep_term_function ();
  282. }
  283.  
  284. void
  285. gnu_readline::do_blink_matching_paren (bool flag)
  286. {
  287.   rl_blink_matching_paren = flag ? 1 : 0;
  288. }
  289.  
  290. void
  291. gnu_readline::do_set_basic_quote_characters (const string& s)
  292. {
  293.   static char *ss = 0;
  294.  
  295.   delete [] ss;
  296.  
  297.   ss = strsave (s.c_str ());
  298.  
  299.   rl_basic_quote_characters = ss;
  300. }
  301.  
  302. void
  303. gnu_readline::do_set_completion_append_character (char c)
  304. {
  305.   rl_completion_append_character = c;
  306. }
  307.  
  308. void
  309. gnu_readline::do_set_completion_function (completion_fcn f)
  310. {
  311.   completion_function = f;
  312.  
  313.   typedef char** (*foo) (...);
  314.  
  315.   rl_attempted_completion_function
  316.     = completion_function
  317.     ? reinterpret_cast<foo> (gnu_readline::command_completer) : 0;
  318. }
  319.  
  320. gnu_readline::completion_fcn
  321. gnu_readline::do_get_completion_function (void) const
  322. {
  323.   return completion_function;
  324. }
  325.  
  326. void
  327. gnu_readline::do_insert_text (const string& text)
  328. {
  329.   rl_insert_text (text.c_str ());
  330. }
  331.  
  332. void
  333. gnu_readline::do_newline (void)
  334. {
  335.   rl_newline ();
  336. }
  337.  
  338. void
  339. gnu_readline::do_clear_undo_list ()
  340. {
  341.   if (rl_undo_list)
  342.     {
  343.       free_undo_list ();
  344.  
  345.       rl_undo_list = 0;
  346.     }
  347. }
  348.  
  349. void
  350. gnu_readline::do_set_startup_hook (fcn f)
  351. {
  352.   previous_startup_hook = rl_startup_hook;
  353.  
  354.   rl_startup_hook = f;
  355. }
  356.  
  357. void
  358. gnu_readline::do_restore_startup_hook (void)
  359. {
  360.   rl_startup_hook = previous_startup_hook;
  361. }
  362.  
  363. void
  364. gnu_readline::do_set_event_hook (fcn f)
  365. {
  366.   previous_event_hook = rl_event_hook;
  367.  
  368.   rl_event_hook = f;
  369. }
  370.  
  371. void
  372. gnu_readline::do_restore_event_hook (void)
  373. {
  374.   rl_event_hook = previous_event_hook;
  375. }
  376.  
  377. void
  378. gnu_readline::do_read_init_file (const string& file)
  379. {
  380.   if (file.empty ())
  381.     rl_re_read_init_file ();
  382.   else
  383.     rl_read_init_file (file.c_str ());
  384. }
  385.  
  386. void
  387. gnu_readline::operate_and_get_next (int /* count */, int /* c */)
  388. {
  389.   // Accept the current line.
  390.  
  391.   command_editor::newline ();
  392.  
  393.   // Find the current line, and find the next line to use.
  394.  
  395.   int x_where = command_history::where ();
  396.  
  397.   int x_length = command_history::length ();
  398.  
  399.   if ((command_history::is_stifled ()
  400.        && (x_length >= command_history::max_input_history ()))
  401.       || (x_where >= x_length - 1))
  402.     command_history::set_mark (x_where);
  403.   else
  404.     command_history::set_mark (x_where + 1);
  405.  
  406.   command_editor::set_startup_hook (command_history::goto_mark);
  407. }
  408.  
  409. char *
  410. gnu_readline::command_generator (const char *text, int state)
  411. {
  412.   char *retval = 0;
  413.  
  414.   completion_fcn f = command_editor::get_completion_function ();
  415.  
  416.   string tmp = f (text, state);
  417.  
  418.   size_t len = tmp.length ();
  419.  
  420.   if (len > 0)
  421.     {
  422.       retval = static_cast<char *> (malloc (len+1));
  423.  
  424.       strcpy (retval, tmp.c_str ());
  425.     }
  426.  
  427.   return retval;
  428. }
  429.  
  430. char **
  431. gnu_readline::command_completer (char *text, int /* start */, int /* end */)
  432. {
  433.   char **matches = 0;
  434.   matches = completion_matches (text, gnu_readline::command_generator);
  435.   return matches;
  436. }
  437.  
  438. #endif
  439.  
  440. class
  441. default_command_editor : public command_editor
  442. {
  443. public:
  444.  
  445.   default_command_editor (void)
  446.     : command_editor (), input_stream (stdin), output_stream (stdout) { }
  447.  
  448.   ~default_command_editor (void) { }
  449.  
  450.   string do_readline (const string& prompt, bool& eof);
  451.  
  452.   void do_set_input_stream (FILE *f);
  453.  
  454.   FILE *do_get_input_stream (void);
  455.  
  456.   void do_set_output_stream (FILE *f);
  457.  
  458.   FILE *do_get_output_stream (void);
  459.  
  460.   void do_insert_text (const string&);
  461.  
  462.   void do_newline (void);
  463.  
  464. private:
  465.  
  466.   FILE *input_stream;
  467.  
  468.   FILE *output_stream;
  469. };
  470.  
  471. string
  472. default_command_editor::do_readline (const string& prompt, bool& eof)
  473. {
  474.   eof = false;
  475.  
  476.   fprintf (output_stream, prompt.c_str ());
  477.   fflush (output_stream);
  478.  
  479.   return octave_fgets (input_stream);
  480. }
  481.  
  482. void
  483. default_command_editor::do_set_input_stream (FILE *f)
  484. {
  485.   input_stream = f;
  486. }
  487.  
  488. FILE *
  489. default_command_editor::do_get_input_stream (void)
  490. {
  491.   return input_stream;
  492. }
  493.  
  494. void
  495. default_command_editor::do_set_output_stream (FILE *f)
  496. {
  497.   output_stream = f;
  498. }
  499.  
  500. FILE *
  501. default_command_editor::do_get_output_stream (void)
  502. {
  503.   return output_stream;
  504. }
  505.  
  506. void
  507. default_command_editor::do_insert_text (const string&)
  508. {
  509.   // XXX FIXME XXX
  510. }
  511.  
  512. void
  513. default_command_editor::do_newline (void)
  514. {
  515.   // XXX FIXME XXX
  516. }
  517.  
  518. bool
  519. command_editor::instance_ok (void)
  520. {
  521.   bool retval = true;
  522.  
  523.   if (! instance)
  524.     make_command_editor ();
  525.  
  526.   if (! instance)
  527.     {
  528.       current_liboctave_error_handler
  529.     ("unable to create command history object!");
  530.  
  531.       retval = false;
  532.     }
  533.  
  534.   return retval;
  535. }
  536.  
  537. void
  538. command_editor::make_command_editor (void)
  539. {
  540. #if defined (USE_READLINE)
  541.   instance = new gnu_readline ();
  542. #else
  543.   instance = new default_command_editor ();
  544. #endif
  545. }
  546.  
  547. void
  548. command_editor::set_name (const string& n)
  549. {
  550.   if (instance_ok ())
  551.     instance->do_set_name (n);
  552. }
  553.  
  554. string
  555. command_editor::readline (const string& prompt)
  556. {
  557.   bool eof;
  558.  
  559.   return readline (prompt, eof);
  560. }
  561.  
  562. string
  563. command_editor::readline (const string& prompt, bool& eof)
  564. {
  565.   return (instance_ok ())
  566.     ? instance->do_readline (prompt, eof) : string ();
  567. }
  568.  
  569. void
  570. command_editor::set_input_stream (FILE *f)
  571. {
  572.   if (instance_ok ())
  573.     instance->do_set_input_stream (f);
  574. }
  575.  
  576. FILE *
  577. command_editor::get_input_stream (void)
  578. {
  579.   return (instance_ok ())
  580.     ? instance->do_get_input_stream () : 0;
  581. }
  582.  
  583. void
  584. command_editor::set_output_stream (FILE *f)
  585. {
  586.   if (instance_ok ())
  587.     instance->do_set_output_stream (f);
  588. }
  589.  
  590. FILE *
  591. command_editor::get_output_stream (void)
  592. {
  593.   return (instance_ok ())
  594.     ? instance->do_get_output_stream () : 0;
  595. }
  596.  
  597. int
  598. command_editor::terminal_rows (void)
  599. {
  600.   return (instance_ok ())
  601.     ? instance->do_terminal_rows () : -1;
  602. }
  603.  
  604. int
  605. command_editor::terminal_cols (void)
  606. {
  607.   return (instance_ok ())
  608.     ? instance->do_terminal_cols () : -1;
  609. }
  610.  
  611. void
  612. command_editor::clear_screen (void)
  613. {
  614.   if (instance_ok ())
  615.     instance->do_clear_screen ();
  616. }
  617.  
  618. string
  619. command_editor::decode_prompt_string (const string& s)
  620. {
  621.   return (instance_ok ())
  622.     ? instance->do_decode_prompt_string (s) : string ();
  623. }
  624.  
  625. int
  626. command_editor::current_command_number (void)
  627. {
  628.   return (instance_ok ())
  629.     ? instance->command_number : 0;
  630. }
  631.  
  632. void
  633. command_editor::reset_current_command_number (int n)
  634. {
  635.   if (instance_ok ())
  636.     instance->command_number = n;
  637. }
  638.  
  639. void
  640. command_editor::add_current_command_number (int n)
  641. {
  642.   if (instance_ok ())
  643.     instance->command_number += n;
  644. }
  645.  
  646. void
  647. command_editor::increment_current_command_number (void)
  648. {
  649.   if (instance_ok ())
  650.     instance->command_number++;
  651. }
  652.  
  653. void
  654. command_editor::restore_terminal_state (void)
  655. {
  656.   if (instance_ok ())
  657.     instance->do_restore_terminal_state ();
  658. }
  659.  
  660. void
  661. command_editor::blink_matching_paren (bool flag)
  662. {
  663.   if (instance_ok ())
  664.     instance->do_blink_matching_paren (flag);
  665. }
  666.  
  667. void
  668. command_editor::set_basic_quote_characters (const string& s)
  669. {
  670.   if (instance_ok ())
  671.     instance->do_set_basic_quote_characters (s);
  672. }
  673.  
  674. void
  675. command_editor::set_completion_append_character (char c)
  676. {
  677.   if (instance_ok ())
  678.     instance->do_set_completion_append_character (c);
  679. }
  680.  
  681. void
  682. command_editor::set_completion_function (completion_fcn f)
  683. {
  684.   if (instance_ok ())
  685.     instance->do_set_completion_function (f);
  686. }
  687.  
  688. command_editor::completion_fcn
  689. command_editor::get_completion_function (void)
  690. {
  691.   return (instance_ok ())
  692.     ? instance->do_get_completion_function () : 0;
  693. }
  694.  
  695. void
  696. command_editor::insert_text (const string& text)
  697. {
  698.   if (instance_ok ())
  699.     instance->do_insert_text (text);
  700. }
  701.  
  702. void
  703. command_editor::newline (void)
  704. {
  705.   if (instance_ok ())
  706.     instance->do_newline ();
  707. }
  708.  
  709. void
  710. command_editor::clear_undo_list (void)
  711. {
  712.   if (instance_ok ())
  713.     instance->do_clear_undo_list ();
  714. }
  715.  
  716. void
  717. command_editor::set_startup_hook (fcn f)
  718. {
  719.   if (instance_ok ())
  720.     instance->do_set_startup_hook (f);
  721. }
  722.  
  723. void
  724. command_editor::restore_startup_hook (void)
  725. {
  726.   if (instance_ok ())
  727.     instance->do_restore_startup_hook ();
  728. }
  729.  
  730. void
  731. command_editor::set_event_hook (fcn f)
  732. {
  733.   if (instance_ok ())
  734.     instance->do_set_event_hook (f);
  735. }
  736.  
  737. void
  738. command_editor::restore_event_hook (void)
  739. {
  740.   if (instance_ok ())
  741.     instance->do_restore_event_hook ();
  742. }
  743.  
  744. void
  745. command_editor::read_init_file (const string& file)
  746. {
  747.   if (instance_ok ())
  748.     instance->do_read_init_file (file);
  749. }
  750.  
  751. // Return a string which will be printed as a prompt.  The string may
  752. // contain special characters which are decoded as follows: 
  753. //   
  754. //    \t    the time
  755. //    \d    the date
  756. //    \n    CRLF
  757. //    \s    the name of the shell (program)
  758. //    \w    the current working directory
  759. //    \W    the last element of PWD
  760. //    \u    your username
  761. //    \h    the hostname
  762. //    \#    the command number of this command
  763. //    \!    the history number of this command
  764. //    \$    a $ or a # if you are root
  765. //    \<octal> character code in octal
  766. //    \\    a backslash
  767.  
  768. string
  769. command_editor::do_decode_prompt_string (const string& s)
  770. {
  771.   string result;
  772.   string temp;
  773.   size_t i = 0;
  774.   size_t slen = s.length ();
  775.   int c;
  776.  
  777.   while (i < slen)
  778.     {
  779.       c = s[i];
  780.  
  781.       i++;
  782.  
  783.       if (c == '\\')
  784.     {
  785.       c = s[i];
  786.  
  787.       switch (c)
  788.         {
  789.         case '0':
  790.         case '1':
  791.         case '2':
  792.         case '3':
  793.         case '4':
  794.         case '5':
  795.         case '6':
  796.         case '7':
  797.           // Maybe convert an octal number.
  798.           {
  799.         int n = read_octal (s.substr (i, 3));
  800.  
  801.         temp = "\\";
  802.  
  803.         if (n != -1)
  804.           {
  805.             i += 3;
  806.             temp[0] = n;
  807.           }
  808.  
  809.         c = 0;
  810.         goto add_string;
  811.           }
  812.       
  813.         case 't':
  814.         case 'd':
  815.           // Make the current time/date into a string.
  816.           {
  817.         time_t now = time (0);
  818.  
  819.         temp = ctime (&now);
  820.  
  821.         if (c == 't')
  822.           {
  823.             temp = temp.substr (11);
  824.             temp.resize (8);
  825.           }
  826.         else
  827.           temp.resize (10);
  828.  
  829.         goto add_string;
  830.           }
  831.  
  832.         case 'n':
  833.           {
  834.         temp = newline_chars ();
  835.  
  836.         goto add_string;
  837.           }
  838.  
  839.         case 's':
  840.           {
  841.         temp = octave_env::get_program_name ();
  842.         temp = octave_env::base_pathname (temp);
  843.  
  844.         goto add_string;
  845.           }
  846.     
  847.         case 'w':
  848.         case 'W':
  849.           {
  850.         temp = octave_env::getcwd ();
  851.  
  852.         if (c == 'W')
  853.           {
  854.             size_t pos = temp.rfind ('/');
  855.  
  856.             if (pos != NPOS && pos != 0)
  857.               temp = temp.substr (pos + 1);
  858.           }
  859.         else
  860.           temp = octave_env::polite_directory_format (temp);
  861.  
  862.         goto add_string;
  863.           }
  864.       
  865.         case 'u':
  866.           {
  867.         temp = octave_env::get_user_name ();
  868.  
  869.         goto add_string;
  870.           }
  871.  
  872.         case 'H':
  873.           {
  874.         temp = octave_env::get_host_name ();
  875.  
  876.         goto add_string;
  877.           }
  878.  
  879.         case 'h':
  880.           {
  881.         temp = octave_env::get_host_name ();
  882.  
  883.         size_t pos = temp.find ('.');
  884.  
  885.         if (pos != NPOS)
  886.           temp.resize (pos);
  887.         
  888.         goto add_string;
  889.           }
  890.  
  891.         case '#':
  892.           {
  893.         char number_buffer[128];
  894.         sprintf (number_buffer, "%d", command_number);
  895.         temp = number_buffer;
  896.  
  897.         goto add_string;
  898.           }
  899.  
  900.         case '!':
  901.           {
  902.         char number_buffer[128];
  903.         int num = command_history::current_number ();
  904.         if (num > 0)
  905.                   sprintf (number_buffer, "%d", num);
  906.         else
  907.           strcpy (number_buffer, "!");
  908.         temp = number_buffer;
  909.  
  910.         goto add_string;
  911.           }
  912.  
  913.         case '$':
  914.           {
  915.         temp = (::geteuid () == 0 ? "#" : "$");
  916.  
  917.         goto add_string;
  918.           }
  919.  
  920. #if defined (USE_READLINE)
  921.         case '[':
  922.         case ']':
  923.           {
  924.         temp.resize (2);
  925.  
  926.         temp[0] = '\001';
  927.         temp[1] = ((c == '[')
  928.                ? RL_PROMPT_START_IGNORE
  929.                : RL_PROMPT_END_IGNORE);
  930.  
  931.         goto add_string;
  932.           }
  933. #endif
  934.  
  935.         case '\\':
  936.           {
  937.         temp = "\\";
  938.  
  939.         goto add_string;
  940.           }
  941.  
  942.         default:
  943.           {
  944.         temp = "\\ ";
  945.         temp[1] = c;
  946.  
  947.         goto add_string;
  948.           }
  949.  
  950.         add_string:
  951.           {
  952.         if (c)
  953.           i++;
  954.  
  955.         result.append (temp);
  956.  
  957.         break;
  958.           }
  959.         }
  960.     }
  961.       else
  962.     result += c;
  963.     }
  964.  
  965.   return result;
  966. }
  967.  
  968. // Return the octal number parsed from STRING, or -1 to indicate that
  969. // the string contained a bad number.
  970.  
  971. int
  972. command_editor::read_octal (const string& s)
  973. {
  974.   int result = 0;
  975.   int digits = 0;
  976.  
  977.   size_t i = 0;
  978.   size_t slen = s.length ();
  979.  
  980.   while (i < slen && s[i] >= '0' && s[i] < '8')
  981.     {
  982.       digits++;
  983.       result = (result * 8) + s[i] - '0';
  984.       i++;
  985.     }
  986.  
  987.   if (! digits || result > 0777 || i < slen)
  988.     result = -1;
  989.  
  990.   return result;
  991. }
  992.  
  993. void
  994. command_editor::error (int err_num)
  995. {
  996.   current_liboctave_error_handler ("%s", strerror (err_num));
  997. }
  998.  
  999. void
  1000. command_editor::error (const string& s)
  1001. {
  1002.   current_liboctave_error_handler ("%s", s.c_str ());
  1003. }
  1004.  
  1005. /*
  1006. ;;; Local Variables: ***
  1007. ;;; mode: C++ ***
  1008. ;;; End: ***
  1009. */
  1010.