home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / src / input.cc < prev    next >
C/C++ Source or Header  |  1996-09-28  |  18KB  |  901 lines

  1. // input.cc                                             -*- C++ -*-
  2. /*
  3.  
  4. Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
  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 2, or (at your option) any
  11. 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, write to the Free
  20. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23.  
  24. /*
  25.  
  26. The 3 functions listed below were adapted from similar functions
  27. from GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991
  28. Free Software Foundation, Inc.
  29.  
  30.   read_octal    sub_append_string    decode_prompt_string
  31.  
  32. */
  33.  
  34. // Use the GNU readline library for command line editing and hisory.
  35.  
  36. #ifdef HAVE_CONFIG_H
  37. #include "config.h"
  38. #endif
  39.  
  40. #include <sys/types.h>
  41. #ifdef HAVE_UNISTD_H
  42. #include <unistd.h>
  43. #endif
  44. #include <time.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <iostream.h>
  48. #include <strstream.h>
  49. #include <string.h>
  50. #include <assert.h>
  51. #include <signal.h>
  52.  
  53. // This must come before anything that includes iostream.h...
  54. extern "C"
  55. {
  56. #include "readline/readline.h"
  57. #include "readline/history.h"
  58.  
  59. extern void free_undo_list ();
  60.  
  61. extern char *xmalloc ();
  62.  
  63. // Yes, this sucks, but it avoids a conflict with another readline
  64. // function declared in iostream.h.
  65.  
  66. #if 0
  67. #define LINE_SIZE 8192
  68. static int no_line_editing = 0;
  69. #endif
  70.  
  71. char *
  72. gnu_readline (char *s)
  73. {
  74. #if 0
  75.   static int state = 0;
  76.   static char *line_from_stdin = 0;
  77.   if (no_line_editing)
  78.     {
  79.       if (! state)
  80.     {
  81.       line_from_stdin = (char *) malloc (LINE_SIZE);
  82.       state = 1;
  83.     }
  84.       fputs ("octave> ", stdout);
  85.       fgets (line_from_stdin, LINE_SIZE, stdin);
  86.       return line_from_stdin;
  87.     }
  88.   else
  89. #endif
  90.     return readline (s);
  91. }
  92. }
  93.  
  94. #include "help.h"
  95. #include "error.h"
  96. #include "utils.h"
  97. #include "input.h"
  98. #include "pager.h"
  99. #include "parse.h"
  100. #include "dirfns.h"
  101. #include "octave.h"
  102. #include "sysdep.h"
  103. #include "variables.h"
  104. #include "tree-const.h"
  105. #include "octave-hist.h"
  106. #include "sighandlers.h"
  107. #include "user-prefs.h"
  108. #include "oct-obj.h"
  109. #include "defun.h"
  110.  
  111. #ifndef MAXPATHLEN
  112. #define MAXPATHLEN 1024
  113. #endif
  114.  
  115. // The size that strings change by.
  116. #ifndef DEFAULT_ARRAY_SIZE
  117. #define DEFAULT_ARRAY_SIZE 512
  118. #endif
  119.  
  120. // The growth rate for the prompt string.
  121. #ifndef PROMPT_GROWTH
  122. #define PROMPT_GROWTH 50
  123. #endif
  124.  
  125. // Global pointer for eval().
  126. const char *current_eval_string = 0;
  127.  
  128. // Nonzero means get input from current_eval_string.
  129. int get_input_from_eval_string = 0;
  130.  
  131. // Nonzero means we're parsing a function file.
  132. int reading_fcn_file = 0;
  133.  
  134. // Simple name of function file we are reading.
  135. char *curr_fcn_file_name = 0;
  136.  
  137. // Nonzero means we're parsing a script file.
  138. int reading_script_file = 0;
  139.  
  140. // If we are reading from an M-file, this is it.
  141. FILE *ff_instream = 0;
  142.  
  143. // Nonzero means we are using readline.
  144. int using_readline = 1;
  145.  
  146. // Nonzero means commands are echoed as they are executed.
  147. // (--echo-commands; -x).
  148. int echo_input = 0;
  149.  
  150. // Nonzero means this is an interactive shell.
  151. int interactive = 0;
  152.  
  153. // Nonzero means the user forced this shell to be interactive (-i).
  154. int forced_interactive = 0;
  155.  
  156. // Should we issue a prompt?
  157. int promptflag = 1;
  158.  
  159. // The current line of input, from wherever.
  160. char *current_input_line = 0;
  161.  
  162. // A line of input from readline.
  163. static char *octave_gets_line = 0;
  164.  
  165. extern tree_constant eval_string (const char *string, int print,
  166.                   int ans_assign, int& parse_status);
  167.  
  168. // Append SOURCE to TARGET at INDEX.  SIZE is the current amount of
  169. // space allocated to TARGET.  SOURCE can be NULL, in which case
  170. // nothing happens.  Gets rid of SOURCE by free ()ing it.  Returns
  171. // TARGET in case the location has changed.
  172.  
  173. static char *
  174. sub_append_string (char *source, char *target, int *index, int *size)
  175. {
  176.   if (source)
  177.     {
  178.       while ((int)strlen (source) >= (int)(*size - *index))
  179.     {
  180.       char *tmp = new char [*size += DEFAULT_ARRAY_SIZE];
  181.       strcpy (tmp, target);
  182.       delete [] target;
  183.       target = tmp;
  184.     }
  185.  
  186.       strcat (target, source);
  187.       *index += strlen (source);
  188.  
  189.       delete [] source;
  190.     }
  191.   return target;
  192. }
  193.  
  194. // Return the octal number parsed from STRING, or -1 to indicate that
  195. // the string contained a bad number.
  196.  
  197. int
  198. read_octal (const char *string)
  199. {
  200.   int result = 0;
  201.   int digits = 0;
  202.  
  203.   while (*string && *string >= '0' && *string < '8')
  204.     {
  205.       digits++;
  206.       result = (result * 8) + *string++ - '0';
  207.     }
  208.  
  209.   if (! digits || result > 0777 || *string)
  210.     result = -1;
  211.  
  212.   return result;
  213. }
  214.  
  215. // Return a string which will be printed as a prompt.  The string may
  216. // contain special characters which are decoded as follows: 
  217. //   
  218. //    \t    the time
  219. //    \d    the date
  220. //    \n    CRLF
  221. //    \s    the name of the shell (program)
  222. //    \w    the current working directory
  223. //    \W    the last element of PWD
  224. //    \u    your username
  225. //    \h    the hostname
  226. //    \#    the command number of this command
  227. //    \!    the history number of this command
  228. //    \$    a $ or a # if you are root
  229. //    \<octal> character code in octal
  230. //    \\    a backslash
  231.  
  232. static char *
  233. decode_prompt_string (const char *string)
  234. {
  235.   int result_size = PROMPT_GROWTH;
  236.   int result_index = 0;
  237.   char *result = new char [PROMPT_GROWTH];
  238.   int c;
  239.   char *temp = 0;
  240.  
  241.   result[0] = 0;
  242.   while (c = *string++)
  243.     {
  244.       if (c == '\\')
  245.     {
  246.       c = *string;
  247.  
  248.       switch (c)
  249.         {
  250.         case '0':
  251.         case '1':
  252.         case '2':
  253.         case '3':
  254.         case '4':
  255.         case '5':
  256.         case '6':
  257.         case '7':
  258.           {
  259.         char octal_string[4];
  260.         int n;
  261.  
  262.         strncpy (octal_string, string, 3);
  263.         octal_string[3] = '\0';
  264.  
  265.         n = read_octal (octal_string);
  266.  
  267.         temp = strsave ("\\");
  268.         if (n != -1)
  269.           {
  270.             string += 3;
  271.             temp[0] = n;
  272.           }
  273.  
  274.         c = 0;
  275.         goto add_string;
  276.           }
  277.       
  278.         case 't':
  279.         case 'd':
  280.           /* Make the current time/date into a string. */
  281.           {
  282.         time_t the_time = time (0);
  283.         char *ttemp = ctime (&the_time);
  284.         temp = strsave (ttemp);
  285.  
  286.         if (c == 't')
  287.           {
  288.             strcpy (temp, temp + 11);
  289.             temp[8] = '\0';
  290.           }
  291.         else
  292.           temp[10] = '\0';
  293.  
  294.         goto add_string;
  295.           }
  296.  
  297.         case 'n':
  298.           if (! no_line_editing)
  299.         temp = strsave ("\r\n");
  300.           else
  301.         temp = strsave ("\n");
  302.           goto add_string;
  303.  
  304.         case 's':
  305.           {
  306.         temp = base_pathname (prog_name);
  307.         temp = strsave (temp);
  308.         goto add_string;
  309.           }
  310.     
  311.         case 'w':
  312.         case 'W':
  313.           {
  314.         char t_string[MAXPATHLEN];
  315. #define EFFICIENT
  316. #ifdef EFFICIENT
  317.  
  318. // Use the value of PWD because it is much more effecient.
  319.  
  320.         temp = user_pref.pwd;
  321.  
  322.         if (! temp)
  323.           octave_getcwd (t_string, MAXPATHLEN);
  324.         else
  325.           strcpy (t_string, temp);
  326. #else
  327.         octave_getcwd (t_string, MAXPATHLEN);
  328. #endif    /* EFFICIENT */
  329.  
  330.         if (c == 'W')
  331.           {
  332.             char *dir = strrchr (t_string, '/');
  333.             if (dir && dir != t_string)
  334.               strcpy (t_string, dir + 1);
  335.             temp = strsave (t_string);
  336.           }
  337.         else
  338.           temp = strsave (polite_directory_format (t_string));
  339.         goto add_string;
  340.           }
  341.       
  342.         case 'u':
  343.           {
  344.         temp = strsave (user_name);
  345.  
  346.         goto add_string;
  347.           }
  348.  
  349.         case 'h':
  350.           {
  351.         char *t_string;
  352.  
  353.         temp = strsave (host_name);
  354.         if (t_string = strchr (temp, '.'))
  355.           *t_string = '\0';
  356.         
  357.         goto add_string;
  358.           }
  359.  
  360.         case '#':
  361.           {
  362.         char number_buffer[128];
  363.         sprintf (number_buffer, "%d", current_command_number);
  364.         temp = strsave (number_buffer);
  365.         goto add_string;
  366.           }
  367.  
  368.         case '!':
  369.           {
  370.         char number_buffer[128];
  371.         int num = current_history_number ();
  372.         if (num > 0)
  373.                   sprintf (number_buffer, "%d", num);
  374.         else
  375.           strcpy (number_buffer, "!");
  376.         temp = strsave (number_buffer);
  377.         goto add_string;
  378.           }
  379.  
  380.         case '$':
  381.           temp = strsave (geteuid () == 0 ? "#" : "$");
  382.           goto add_string;
  383.  
  384.         case '\\':
  385.           temp = strsave ("\\");
  386.           goto add_string;
  387.  
  388.         default:
  389.           temp = strsave ("\\ ");
  390.           temp[1] = c;
  391.  
  392.         add_string:
  393.           if (c)
  394.         string++;
  395.           result =
  396.         (char *)sub_append_string (temp, result,
  397.                        &result_index, &result_size);
  398.           temp = 0; // Free ()'ed in sub_append_string ().
  399.           result[result_index] = '\0';
  400.           break;
  401.         }
  402.     }
  403.       else
  404.     {
  405.       while (3 + result_index > result_size)
  406.         {
  407.           char *tmp = new char [result_size += PROMPT_GROWTH];
  408.           strcpy (tmp, result);
  409.           delete [] result;
  410.           result = tmp;
  411.         }
  412.       result[result_index++] = c;
  413.       result[result_index] = '\0';
  414.     }
  415.     }
  416.  
  417. #if 0
  418. // I don't really think that this is a good idea.  Do you?
  419.   if (! find_variable ("NO_PROMPT_VARS"))
  420.     {
  421.       WORD_LIST *expand_string (), *list;
  422.       char *string_list ();
  423.  
  424.       list = expand_string (result, 1);
  425.       free (result);
  426.       result = string_list (list);
  427.       dispose_words (list);
  428.     }
  429. #endif
  430.  
  431.   return result;
  432. }
  433.  
  434. static void
  435. do_input_echo (const char *input_string)
  436. {
  437.   if (echo_input)
  438.     {
  439.       ostrstream buf;
  440.  
  441.       if (! forced_interactive)
  442.     {
  443.       char *prefix = decode_prompt_string (user_pref.ps4);
  444.       buf << prefix;
  445.       delete [] prefix;
  446.     }
  447.  
  448.       if (input_string)
  449.     {
  450.       buf << input_string;
  451.       int len = strlen (input_string);
  452.       if (input_string[len-1] != '\n')
  453.         buf << "\n";
  454.     }
  455.  
  456.       maybe_page_output (buf);
  457.     }
  458. }
  459.  
  460.  
  461. // Use GNU readline to get an input line and store it in the history
  462. // list.
  463.  
  464. static char *
  465. octave_gets (void)
  466. {
  467.   if (octave_gets_line)
  468.     {
  469.       free (octave_gets_line);
  470.       octave_gets_line = 0;
  471.     }
  472.  
  473.   if (interactive || forced_interactive)
  474.     {
  475.       char *ps = (promptflag > 0) ? user_pref.ps1 : user_pref.ps2;
  476.       char *prompt = decode_prompt_string (ps);
  477.  
  478.       if (interactive)
  479.     {
  480.       pipe_handler_error_count = 0;
  481.       flush_output_to_pager ();
  482.     }
  483.  
  484.       maybe_write_to_diary_file (prompt);
  485.  
  486.       octave_gets_line = gnu_readline (prompt);
  487.  
  488.       delete [] prompt;
  489.     }
  490.   else
  491.     octave_gets_line = gnu_readline ("");
  492.  
  493.   current_input_line = octave_gets_line;
  494.  
  495.   if (octave_gets_line && *octave_gets_line)
  496.     {
  497.       maybe_save_history (octave_gets_line);
  498.  
  499.       maybe_write_to_diary_file (octave_gets_line);
  500.  
  501.       do_input_echo (octave_gets_line);
  502.     }
  503.  
  504.   maybe_write_to_diary_file ("\n");
  505.   
  506.   return octave_gets_line;
  507. }
  508.  
  509. // Read a line from the input stream.
  510.  
  511. int
  512. octave_read (char *buf, int max_size)
  513. {
  514.   int status = 0;
  515.  
  516.   static char *stashed_line = 0;
  517.  
  518.   if (get_input_from_eval_string)
  519.     {
  520.       int len = strlen (current_eval_string);
  521.       if (len < max_size - 1)
  522.     {
  523.       strcpy (buf, current_eval_string);
  524.       buf[len++] = '\n';
  525.       buf[len] = '\0';    // Paranoia.
  526.       status = len;
  527.     }
  528.       else
  529.     status = -1;
  530.  
  531.       if (stashed_line)
  532.     delete [] stashed_line;
  533.  
  534.       stashed_line = strsave (buf);
  535.       current_input_line = stashed_line;
  536.     }
  537.   else if (using_readline)
  538.     {
  539.       char *cp = octave_gets ();
  540.       if (cp)
  541.     {
  542.       int len = strlen (cp);
  543.       if (len >= max_size)
  544.         status = -1;
  545.       else
  546.         {
  547.           strcpy (buf, cp);
  548.           buf[len++] = '\n';
  549.           buf[len] = '\0';    // Paranoia.
  550.           status = len;
  551.         }
  552.     }
  553.       current_input_line = cp;
  554.     }
  555.   else
  556.     {
  557.       FILE *curr_stream = rl_instream;
  558.       if (reading_fcn_file || reading_script_file)
  559.     curr_stream = ff_instream;
  560.  
  561.       assert (curr_stream);
  562.  
  563. // Why is this required?
  564.       buf[0] = '\0';
  565.  
  566.       if (fgets (buf, max_size, curr_stream))
  567.     {
  568.       int len = strlen (buf);
  569.       if (len > max_size - 2)
  570.         status = -1;
  571.       else
  572.         {
  573.           if (buf[len-1] != '\n')
  574.         {
  575.           buf[len++] = '\n';
  576.           buf[len] = '\0';
  577.         }
  578.           status = len;
  579.         }
  580.     }
  581.       else
  582.     status = 0; // Tell yylex that we found EOF.
  583.  
  584.       if (stashed_line)
  585.     delete [] stashed_line;
  586.  
  587.       stashed_line = strsave (buf);
  588.  
  589.       current_input_line = stashed_line;
  590.  
  591.       do_input_echo (current_input_line);
  592.     }
  593.  
  594.   input_line_number++;
  595.  
  596.   return status;
  597. }
  598.  
  599. // Fix things up so that input can come from file `name', printing a
  600. // warning if the file doesn't exist.
  601.  
  602. FILE *
  603. get_input_from_file (char *name, int warn)
  604. {
  605.   FILE *instream = 0;
  606.  
  607.   if (name && *name)
  608.     instream = fopen (name, "r");
  609.  
  610.   if (! instream && warn)
  611.     warning ("%s: no such file or directory", name);
  612.  
  613.   if (reading_fcn_file || reading_script_file)
  614.     ff_instream = instream;
  615.   else
  616.     rl_instream = instream;
  617.  
  618.   return instream;
  619. }
  620.  
  621. // Fix things up so that input can come from the standard input.  This
  622. // may need to become much more complicated, which is why it's in a
  623. // separate function.
  624.  
  625. FILE *
  626. get_input_from_stdin (void)
  627. {
  628.   rl_instream = stdin;
  629.   return rl_instream;
  630. }
  631.  
  632. static char *
  633. command_generator (char *text, int state)
  634. {
  635.   static int len = 0;
  636.   static int list_index = 0;
  637.  
  638.   static char **name_list = 0;
  639.  
  640.   if (state == 0)
  641.     {
  642.       list_index = 0;
  643.       len = strlen (text);
  644.  
  645.       if (name_list)
  646.     {
  647.       char **ptr = name_list;
  648.       while (ptr && *ptr)
  649.         delete [] *ptr++;
  650.       delete [] name_list;
  651.     }
  652.  
  653.       name_list = make_name_list ();
  654.     }
  655.  
  656.   char *name;
  657.   while ((name = name_list[list_index]) != 0)
  658.     {
  659.       list_index++;
  660.       if (strncmp (name, text, len) == 0)
  661.     {
  662.       char *buf = xmalloc (1 + strlen (name));
  663.       strcpy (buf, name);
  664.       return buf;
  665.     }
  666.     }
  667.  
  668.   return 0;
  669. }
  670.  
  671. static char **
  672. command_completer (char *text, int start, int end)
  673. {
  674.   char **matches = 0;
  675.   matches = completion_matches (text, command_generator);
  676.   return matches;
  677. }
  678.  
  679. // The next two functions implement the equivalent of the K*rn shell
  680. // C-o operate-and-get-next-history-line editing command.  Stolen from
  681. // the GNU Bourne Again SHell.
  682.  
  683. // ??
  684. static int saved_history_line_to_use = 0;
  685.  
  686. // ??
  687. static Function *old_rl_startup_hook = 0;
  688.  
  689. static void
  690. set_saved_history (void)
  691. {
  692.   HIST_ENTRY *h;
  693.  
  694.   if (saved_history_line_to_use)
  695.     {
  696.       if (history_set_pos (saved_history_line_to_use))
  697.     {
  698.       h = current_history ();
  699.       if (h)
  700.         {
  701.           rl_insert_text (h->line);
  702.  
  703. // Get rid of any undo list created by the previous insert, so the
  704. // line won't totally be erased when the edits are undone (they will
  705. // be normally, because this is a history  line -- cf. readline.c:
  706. // line 380 or so).
  707.           if (rl_undo_list)
  708.         {
  709.           free_undo_list ();
  710.           rl_undo_list = 0;
  711.         }
  712.         }
  713.     }
  714.     }
  715.   saved_history_line_to_use = 0;
  716.   rl_startup_hook = old_rl_startup_hook;
  717. }
  718.  
  719. static void
  720. operate_and_get_next (int count, int c)
  721. {
  722.   int where;
  723.   extern int history_stifled, history_length, max_input_history;
  724.  
  725. // Accept the current line.
  726.   rl_newline ();
  727.  
  728. // Find the current line, and find the next line to use.
  729.   where = where_history ();
  730.  
  731.   if (history_stifled && (history_length >= max_input_history))
  732.     saved_history_line_to_use = where;
  733.   else
  734.     saved_history_line_to_use = where + 1;
  735.  
  736.   old_rl_startup_hook = rl_startup_hook;
  737.   rl_startup_hook = (Function *) set_saved_history;
  738. }
  739.  
  740. void
  741. initialize_readline (void)
  742. {
  743. // Allow conditional parsing of the ~/.inputrc file
  744.   rl_readline_name = "Octave";
  745.  
  746. // Tell the completer that we want to try first.
  747.   rl_attempted_completion_function = (CPPFunction *) command_completer;
  748.  
  749. // Bind operate-and-get-next.
  750.   rl_add_defun ("operate-and-get-next",
  751.         (Function *) operate_and_get_next, CTRL ('O'));
  752. }
  753.  
  754. static int
  755. match_sans_spaces (const char *standard, const char *test)
  756. {
  757.   char *tmp = strsave (test);
  758.  
  759.   char *tp = tmp;
  760.   while (*tp == ' ' || *tp == '\t')
  761.     tp++;
  762.  
  763.   char *ep = tmp + strlen (tmp) - 1;
  764.   while (*ep == ' ' || *ep == '\t')
  765.     ep--;
  766.  
  767.   *(ep+1) = '\0';
  768.  
  769.   int retval = strcmp (standard, tp) == 0;
  770.  
  771.   delete [] tmp;
  772.  
  773.   return retval;
  774.  
  775. }
  776.  
  777. // If the user simply hits return, this will produce an empty matrix.
  778.  
  779. static Octave_object
  780. get_user_input (const Octave_object& args, int nargout, int debug = 0)
  781. {
  782.   tree_constant retval;
  783.  
  784.   int nargin = args.length ();
  785.  
  786.   int read_as_string = 0;
  787.  
  788.   if (nargin == 2)
  789.     read_as_string++;
  790.  
  791.   char *prompt = "debug> ";
  792.   if (nargin > 0)
  793.    {
  794.      prompt = args(0).string_value ();
  795.  
  796.      if (error_state)
  797.        {
  798.      error ("input: unrecognized argument");
  799.      return retval;
  800.        }
  801.     }
  802.  
  803.  again:
  804.  
  805.   flush_output_to_pager ();
  806.  
  807.   char *input_buf = gnu_readline (prompt);
  808.  
  809.   if (input_buf)
  810.     {
  811.       maybe_save_history (input_buf);
  812.  
  813.       int len = strlen (input_buf);
  814.  
  815.       if (len < 1)
  816.     {
  817.       if (debug)
  818.         goto again;
  819.       else
  820.         {
  821.           if (read_as_string)
  822.         return "";
  823.           else
  824.         return Matrix ();
  825.         }
  826.     }
  827.  
  828.       if (match_sans_spaces ("exit", input_buf)
  829.       || match_sans_spaces ("quit", input_buf)
  830.       || match_sans_spaces ("return", input_buf))
  831.     {
  832.       return retval;
  833.     }
  834.       else if (read_as_string)
  835.     {
  836.       retval = input_buf;
  837.     }
  838.       else
  839.     {
  840.       int parse_status = 0;
  841.       retval = eval_string (input_buf, 0, 0, parse_status);
  842.       if (retval.is_defined ())
  843.         {
  844.           if (debug)
  845.         retval.eval (1);
  846.         }
  847.       else
  848.         retval = Matrix ();
  849.     }
  850.     }
  851.   else
  852.     error ("input: reading user-input failed!");
  853.  
  854.   if (debug)
  855.     goto again;
  856.  
  857.   return retval;
  858. }
  859.  
  860. DEFUN ("input", Finput, Sinput, 2, 1,
  861.   "input (PROMPT [, S])\n\
  862. \n\
  863. Prompt user for input.  If the second argument is present, return
  864. value as a string.")
  865. {
  866.   Octave_object retval;
  867.  
  868.   int nargin = args.length ();
  869.  
  870.   if (nargin == 1 || nargin == 2)
  871.     retval = get_user_input (args, nargout);
  872.   else
  873.     print_usage ("input");
  874.  
  875.   return retval;
  876. }
  877.  
  878. DEFUN ("keyboard", Fkeyboard, Skeyboard, 1, 1,
  879.   "keyboard (PROMPT)\n\
  880. \n\
  881. maybe help in debugging function files")
  882. {
  883.   Octave_object retval;
  884.  
  885.   int nargin = args.length ();
  886.  
  887.   if (nargin == 0 || nargin == 1)
  888.     retval = get_user_input (args, nargout, 1);
  889.   else
  890.     print_usage ("keyboard");
  891.  
  892.   return retval;
  893. }
  894.  
  895. /*
  896. ;;; Local Variables: ***
  897. ;;; mode: C++ ***
  898. ;;; page-delimiter: "^/\\*" ***
  899. ;;; End: ***
  900. */
  901.