diff src/input.cc @ 529:7ea224e713cd

[project @ 1994-07-20 18:54:27 by jwe]
author jwe
date Wed, 20 Jul 1994 19:19:08 +0000
parents 94f0f219a946
children bc813f5eb025
line wrap: on
line diff
--- a/src/input.cc	Wed Jul 20 18:53:50 1994 +0000
+++ b/src/input.cc	Wed Jul 20 19:19:08 1994 +0000
@@ -27,6 +27,11 @@
 #include "config.h"
 #endif
 
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <iostream.h>
@@ -49,7 +54,7 @@
  */
 #if 0
 #define LINE_SIZE 8192
-static int no_line_editing = 1;
+static int no_line_editing = 0;
 #endif
 
 char *
@@ -57,7 +62,7 @@
 {
 #if 0
   static int state = 0;
-  static char *line_from_stdin = (char *) NULL;
+  static char *line_from_stdin = 0;
   if (no_line_editing)
     {
       if (! state)
@@ -75,20 +80,38 @@
 }
 }
 
-#include "variables.h"
+#include "help.h"
 #include "error.h"
 #include "utils.h"
 #include "input.h"
 #include "pager.h"
-#include "help.h"
+#include "parse.h"
+#include "dirfns.h"
+#include "octave.h"
+#include "variables.h"
+#include "tree-const.h"
 #include "octave-hist.h"
 #include "sighandlers.h"
-#include "parse.h"
 #include "user-prefs.h"
-#include "builtins.h"
+#include "oct-obj.h"
+#include "defun.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+// The size that strings change by.
+#ifndef DEFAULT_ARRAY_SIZE
+#define DEFAULT_ARRAY_SIZE 512
+#endif
+
+// The growth rate for the prompt string.
+#ifndef PROMPT_GROWTH
+#define PROMPT_GROWTH 50
+#endif
 
 // Global pointer for eval().
-const char *current_eval_string = (char *) NULL;
+const char *current_eval_string = 0;
 
 // Nonzero means get input from current_eval_string.
 int get_input_from_eval_string = 0;
@@ -97,13 +120,13 @@
 int reading_fcn_file = 0;
 
 // Simple name of function file we are reading.
-char *curr_fcn_file_name = (char *) NULL;
+char *curr_fcn_file_name = 0;
 
 // Nonzero means we're parsing a script file.
 int reading_script_file = 0;
 
 // If we are reading from an M-file, this is it.
-FILE *ff_instream = (FILE *) NULL;
+FILE *ff_instream = 0;
 
 // Nonzero means we are using readline.
 int using_readline = 1;
@@ -121,11 +144,282 @@
 int promptflag = 1;
 
 // The current line of input, from wherever.
-char *current_input_line = (char *) NULL;
+char *current_input_line = 0;
 
 // A line of input from readline.
-static char *octave_gets_line = (char *) NULL;
+static char *octave_gets_line = 0;
+
+extern tree_constant eval_string (const char *string, int print,
+				  int ans_assign, int& parse_status);
+
+/*
+ * Append SOURCE to TARGET at INDEX.  SIZE is the current amount of
+ * space allocated to TARGET.  SOURCE can be NULL, in which case
+ * nothing happens.  Gets rid of SOURCE by free ()ing it.  Returns
+ * TARGET in case the location has changed.
+ */
+static char *
+sub_append_string (char *source, char *target, int *index, int *size)
+{
+  if (source)
+    {
+      while ((int)strlen (source) >= (int)(*size - *index))
+	{
+	  char *tmp = new char [*size += DEFAULT_ARRAY_SIZE];
+	  strcpy (tmp, target);
+	  delete [] target;
+	  target = tmp;
+	}
+
+      strcat (target, source);
+      *index += strlen (source);
+
+      delete [] source;
+    }
+  return target;
+}
+
+/*
+ * Return the octal number parsed from STRING, or -1 to indicate that
+ * the string contained a bad number.
+ */
+int
+read_octal (const char *string)
+{
+  int result = 0;
+  int digits = 0;
+
+  while (*string && *string >= '0' && *string < '8')
+    {
+      digits++;
+      result = (result * 8) + *string++ - '0';
+    }
+
+  if (! digits || result > 0777 || *string)
+    result = -1;
+
+  return result;
+}
+
+/*
+ * Return a string which will be printed as a prompt.  The string may
+ * contain special characters which are decoded as follows: 
+ *   
+ *	\t	the time
+ *	\d	the date
+ *	\n	CRLF
+ *	\s	the name of the shell (program)
+ *	\w	the current working directory
+ *	\W	the last element of PWD
+ *	\u	your username
+ *	\h	the hostname
+ *	\#	the command number of this command
+ *	\!	the history number of this command
+ *	\$	a $ or a # if you are root
+ *	\<octal> character code in octal
+ *	\\	a backslash
+ */
+static char *
+decode_prompt_string (const char *string)
+{
+  int result_size = PROMPT_GROWTH;
+  int result_index = 0;
+  char *result = new char [PROMPT_GROWTH];
+  int c;
+  char *temp = 0;
+
+  result[0] = 0;
+  while (c = *string++)
+    {
+      if (c == '\\')
+	{
+	  c = *string;
+
+	  switch (c)
+	    {
+	    case '0':
+	    case '1':
+	    case '2':
+	    case '3':
+	    case '4':
+	    case '5':
+	    case '6':
+	    case '7':
+	      {
+		char octal_string[4];
+		int n;
+
+		strncpy (octal_string, string, 3);
+		octal_string[3] = '\0';
+
+		n = read_octal (octal_string);
+
+		temp = strsave ("\\");
+		if (n != -1)
+		  {
+		    string += 3;
+		    temp[0] = n;
+		  }
+
+		c = 0;
+		goto add_string;
+	      }
+	  
+	    case 't':
+	    case 'd':
+	      /* Make the current time/date into a string. */
+	      {
+		time_t the_time = time (0);
+		char *ttemp = ctime (&the_time);
+		temp = strsave (ttemp);
+
+		if (c == 't')
+		  {
+		    strcpy (temp, temp + 11);
+		    temp[8] = '\0';
+		  }
+		else
+		  temp[10] = '\0';
+
+		goto add_string;
+	      }
 
+	    case 'n':
+	      if (! no_line_editing)
+		temp = strsave ("\r\n");
+	      else
+		temp = strsave ("\n");
+	      goto add_string;
+
+	    case 's':
+	      {
+		temp = base_pathname (prog_name);
+		temp = strsave (temp);
+		goto add_string;
+	      }
+	
+	    case 'w':
+	    case 'W':
+	      {
+		char t_string[MAXPATHLEN];
+#define EFFICIENT
+#ifdef EFFICIENT
+
+// Use the value of PWD because it is much more effecient.
+
+		temp = user_pref.pwd;
+
+		if (! temp)
+		  getcwd (t_string, MAXPATHLEN);
+		else
+		  strcpy (t_string, temp);
+#else
+		getcwd (t_string, MAXPATHLEN);
+#endif	/* EFFICIENT */
+
+		if (c == 'W')
+		  {
+		    char *dir = strrchr (t_string, '/');
+		    if (dir && dir != t_string)
+		      strcpy (t_string, dir + 1);
+		    temp = strsave (t_string);
+		  }
+		else
+		  temp = strsave (polite_directory_format (t_string));
+		goto add_string;
+	      }
+      
+	    case 'u':
+	      {
+		temp = strsave (user_name);
+
+		goto add_string;
+	      }
+
+	    case 'h':
+	      {
+		char *t_string;
+
+		temp = strsave (host_name);
+		if (t_string = strchr (temp, '.'))
+		  *t_string = '\0';
+		
+		goto add_string;
+	      }
+
+	    case '#':
+	      {
+		char number_buffer[128];
+		sprintf (number_buffer, "%d", current_command_number);
+		temp = strsave (number_buffer);
+		goto add_string;
+	      }
+
+	    case '!':
+	      {
+		char number_buffer[128];
+		int num = current_history_number ();
+		if (num > 0)
+                  sprintf (number_buffer, "%d", num);
+		else
+		  strcpy (number_buffer, "!");
+		temp = strsave (number_buffer);
+		goto add_string;
+	      }
+
+	    case '$':
+	      temp = strsave (geteuid () == 0 ? "#" : "$");
+	      goto add_string;
+
+	    case '\\':
+	      temp = strsave ("\\");
+	      goto add_string;
+
+	    default:
+	      temp = strsave ("\\ ");
+	      temp[1] = c;
+
+	    add_string:
+	      if (c)
+		string++;
+	      result =
+		(char *)sub_append_string (temp, result,
+					   &result_index, &result_size);
+	      temp = 0; /* Free ()'ed in sub_append_string (). */
+	      result[result_index] = '\0';
+	      break;
+	    }
+	}
+      else
+	{
+	  while (3 + result_index > result_size)
+	    {
+	      char *tmp = new char [result_size += PROMPT_GROWTH];
+	      strcpy (tmp, result);
+	      delete [] result;
+	      result = tmp;
+	    }
+	  result[result_index++] = c;
+	  result[result_index] = '\0';
+	}
+    }
+
+#if 0
+  /* I don't really think that this is a good idea.  Do you? */
+  if (! find_variable ("NO_PROMPT_VARS"))
+    {
+      WORD_LIST *expand_string (), *list;
+      char *string_list ();
+
+      list = expand_string (result, 1);
+      free (result);
+      result = string_list (list);
+      dispose_words (list);
+    }
+#endif
+
+  return result;
+}
 /*
  * Use GNU readline to get an input line and store it in the history
  * list.
@@ -133,10 +427,10 @@
 static char *
 octave_gets (void)
 {
-  if (octave_gets_line != NULL)
+  if (octave_gets_line)
     {
       free (octave_gets_line);
-      octave_gets_line = (char *) NULL;
+      octave_gets_line = 0;
     }
 
   if (interactive || forced_interactive)
@@ -181,7 +475,7 @@
 {
   int status = 0;
 
-  static char *stashed_line = (char *) NULL;
+  static char *stashed_line = 0;
 
   if (get_input_from_eval_string)
     {
@@ -205,7 +499,7 @@
   else if (using_readline)
     {
       char *cp = octave_gets ();
-      if (cp != (char *) NULL)
+      if (cp)
 	{
 	  int len = strlen (cp);
 	  if (len >= max_size)
@@ -226,12 +520,12 @@
       if (reading_fcn_file || reading_script_file)
 	curr_stream = ff_instream;
 
-      assert (curr_stream != (FILE *) NULL);
+      assert (curr_stream);
 
 // Why is this required?
       buf[0] = '\0';
 
-      if (fgets (buf, max_size, curr_stream) != (char *) NULL)
+      if (fgets (buf, max_size, curr_stream))
 	{
 	  int len = strlen (buf);
 	  if (len > max_size - 2)
@@ -272,14 +566,14 @@
  * warning if the file doesn't exist.
  */
 FILE *
-get_input_from_file (char *name, int warn = 1)
+get_input_from_file (char *name, int warn)
 {
-  FILE *instream = (FILE *) NULL;
+  FILE *instream = 0;
 
   if (name && *name)
     instream = fopen (name, "r");
 
-  if (instream == (FILE *) NULL && warn)
+  if (! instream && warn)
     warning ("%s: no such file or directory", name);
 
   if (reading_fcn_file || reading_script_file)
@@ -308,14 +602,14 @@
   static int len = 0;
   static int list_index = 0;
 
-  static char **name_list = (char **) NULL;
+  static char **name_list = 0;
 
   if (state == 0)
     {
       list_index = 0;
       len = strlen (text);
 
-      if (name_list != (char **) NULL)
+      if (name_list)
 	{
 	  char **ptr = name_list;
 	  while (ptr && *ptr)
@@ -327,7 +621,7 @@
     }
 
   char *name;
-  while ((name = name_list[list_index]) != (char *) NULL)
+  while ((name = name_list[list_index]) != 0)
     {
       list_index++;
       if (strncmp (name, text, len) == 0)
@@ -338,13 +632,13 @@
 	}
     }
 
-  return (char *) NULL;
+  return 0;
 }
 
 static char **
 command_completer (char *text, int start, int end)
 {
-  char **matches = (char **) NULL;
+  char **matches = 0;
   matches = completion_matches (text, command_generator);
   return matches;
 }
@@ -359,7 +653,7 @@
 static int saved_history_line_to_use = 0;
 
 // ??
-static Function *old_rl_startup_hook = (Function *) NULL;
+static Function *old_rl_startup_hook = 0;
 
 static void
 set_saved_history (void)
@@ -382,7 +676,7 @@
 	      if (rl_undo_list)
 		{
 		  free_undo_list ();
-		  rl_undo_list = (UNDO_LIST *) NULL;
+		  rl_undo_list = 0;
 		}
 	    }
 	}
@@ -426,6 +720,124 @@
 		(Function *) operate_and_get_next, CTRL ('O'));
 }
 
+static int
+match_sans_spaces (const char *standard, const char *test)
+{
+  const char *tp = test;
+  while (*tp == ' ' || *tp == '\t')
+    tp++;
+
+  const char *ep = test + strlen (test) - 1;
+  while (*ep == ' ' || *ep == '\t')
+    ep--;
+
+  int len = ep - tp + 1;
+
+  return (strncmp (standard, tp, len) == 0);
+}
+
+static Octave_object
+get_user_input (const Octave_object& args, int nargout, int debug = 0)
+{
+  tree_constant retval;
+
+  int nargin = args.length ();
+
+  int read_as_string = 0;
+
+  if (nargin == 3)
+    read_as_string++;
+
+  char *prompt = "debug> ";
+  if (nargin > 1)
+   {
+      if (args(1).is_string_type ())
+	prompt = args(1).string_value ();
+      else
+	{
+	  error ("input: unrecognized argument");
+	  return retval;
+	}
+    }
+
+ again:
+
+  flush_output_to_pager ();
+
+  char *input_buf = gnu_readline (prompt);
+
+  if (input_buf)
+    {
+      maybe_save_history (input_buf);
+
+      int len = strlen (input_buf);
+
+      if (len < 1)
+	{
+	  if (debug)
+	    goto again;
+	  else
+	    return retval;
+	}
+
+      if (match_sans_spaces ("exit", input_buf)
+	  || match_sans_spaces ("quit", input_buf)
+	  || match_sans_spaces ("return", input_buf))
+	return tree_constant ();
+      else if (read_as_string)
+	retval = input_buf;
+      else
+	{
+	  int parse_status = 0;
+	  retval = eval_string (input_buf, 0, 0, parse_status);
+	  if (debug && retval.is_defined ())
+	    retval.eval (1);
+	}
+    }
+  else
+    error ("input: reading user-input failed!");
+
+  if (debug)
+    goto again;
+
+  return retval;
+}
+
+DEFUN ("input", Finput, Sinput, 3, 1,
+  "input (PROMPT [, S])\n\
+\n\
+Prompt user for input.  If the second argument is present, return
+value as a string.")
+{
+  Octave_object retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 2 || nargin == 3)
+    retval = get_user_input (args, nargout);
+  else
+    print_usage ("input");
+
+  return retval;
+}
+
+DEFUN ("keyboard", Fkeyboard, Skeyboard, 2, 1,
+  "keyboard (PROMPT)\n\
+\n\
+maybe help in debugging function files")
+{
+  Octave_object retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1 || nargin == 2)
+    retval = get_user_input (args, nargout, 1);
+  else
+    print_usage ("keyboard");
+
+  return retval;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***