source: git/kernel/feread.cc @ 412d157

spielwiese
Last change on this file since 412d157 was 412d157, checked in by Hans Schoenemann <hannes@…>, 10 years ago
fix: strip unknown chars from terminal input
  • Property mode set to 100644
File size: 11.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: input from ttys, simulating fgets
6*/
7
8#ifdef HAVE_CONFIG_H
9#include "singularconfig.h"
10#endif /* HAVE_CONFIG_H */
11#include <kernel/mod2.h>
12
13// ----------------------------------------
14// system settings:
15
16#undef USE_READLINE4
17
18//----------------------------------------
19#ifdef ix86_Win
20#define READLINE_STATIC
21#endif
22#include <kernel/febase.h>
23#include <omalloc/omalloc.h>
24#include <misc/options.h>
25
26#ifdef HAVE_STATIC
27#undef HAVE_DYN_RL
28#endif
29
30#if defined(HAVE_DYN_RL)
31#include <unistd.h>
32#endif
33
34static char * fe_fgets_stdin_init(const char *pr,char *s, int size);
35char * (*fe_fgets_stdin)(const char *pr,char *s, int size)
36 = fe_fgets_stdin_init;
37
38extern char *iiArithGetCmd(int);
39
40/* ===================================================================*/
41/* =                   static/dymanic readline                      = */
42/* ===================================================================*/
43#if defined(HAVE_READLINE) || defined(HAVE_DYN_RL) || defined(HAVE_LIBREADLINE)
44
45#ifndef STDOUT_FILENO
46#define STDOUT_FILENO 1
47#endif
48
49/* Generator function for command completion.  STATE lets us know whether
50*   to start from scratch; without any state (i.e. STATE == 0), then we
51*   start at the top of the list.
52*/
53extern "C"
54char *command_generator (char *text, int state)
55{
56  static int list_index, len;
57  char *name;
58
59  /* If this is a new word to complete, initialize now.  This includes
60     saving the length of TEXT for efficiency, and initializing the index
61     variable to 0. */
62  if (state==0)
63  {
64    list_index = 1;
65    len = strlen (text);
66  }
67
68  /* Return the next name which partially matches from the command list. */
69  while ((name = iiArithGetCmd(list_index))!=NULL)
70  {
71    list_index++;
72
73    if (strncmp (name, text, len) == 0)
74      return (strdup(name));
75  }
76
77  /* If no names matched, then return NULL. */
78  return ((char *)NULL);
79}
80#endif
81
82/* ===================================================================*/
83/* =                      static readline                           = */
84/* ===================================================================*/
85/* some procedure are shared with "dynamic readline" */
86#if (defined(HAVE_READLINE) || defined(HAVE_LIBREADLINE) || defined(HAVE_DYN_RL))
87#include <unistd.h>
88#include <stdio.h>
89#include <stdlib.h>
90#include <sys/types.h>
91#include <sys/file.h>
92#include <sys/stat.h>
93#include <sys/errno.h>
94
95// #undef READLINE_READLINE_H_OK
96
97extern "C" {
98  typedef char * (*RL_PROC)(const char*,int);
99  #ifdef READLINE_READLINE_H_OK
100    #include <readline/readline.h>
101    #ifdef HAVE_READLINE_HISTORY_H
102      #include <readline/history.h>
103    #endif
104  #endif
105
106  #ifdef RL_VERSION_MAJOR
107    #if (RL_VERSION_MAJOR >= 4)
108      #define USE_READLINE4
109    #endif
110  #endif
111
112  #ifndef USE_READLINE4
113    #define rl_filename_completion_function filename_completion_function
114    #define rl_completion_matches           completion_matches
115  #endif
116  #ifndef READLINE_READLINE_H_OK
117    /* declare everything we need explicitely and do not rely on includes */
118    extern char * rl_readline_name;
119    extern char *rl_line_buffer;
120    char *rl_filename_completion_function(const char*, int);
121    typedef char **CPPFunction ();
122
123    extern char ** rl_completion_matches (const char*, RL_PROC);
124    extern CPPFunction * rl_attempted_completion_function;
125    extern FILE * rl_outstream;
126    extern char * readline (const char *);
127    extern void add_history (char *);
128    extern int write_history ();
129    extern void using_history();
130    extern int read_history(char *);
131    extern int history_total_bytes();
132  #endif /* READLINE_READLINE_H_OK */
133
134  typedef char * (*PROC)();
135
136  typedef char **RL_CPPFunction (const char*, int,int);
137}
138
139
140char * fe_fgets_stdin_rl(const char *pr,char *s, int size);
141
142/* Tell the GNU Readline library how to complete.  We want to try to complete
143   on command names  or on filenames if it is preceded by " */
144
145/* Attempt to complete on the contents of TEXT.  START and END show the
146*   region of TEXT that contains the word to complete.  We can use the
147*   entire line in case we want to do some simple parsing.  Return the
148*   array of matches, or NULL if there aren't any.
149*/
150#if defined(HAVE_DYN_RL)
151extern "C"
152{
153  int fe_init_dyn_rl();
154  char *(*fe_filename_completion_function)(); /* 3 */
155  char *(* fe_readline) (char *);             /* 4 */
156  void (*fe_add_history) (char *);            /* 5 */
157  char ** fe_rl_readline_name;                /* 6 */
158  char **fe_rl_line_buffer;                   /* 7 */
159  char **(*fe_completion_matches)(...);          /* 8 */
160  CPPFunction **fe_rl_attempted_completion_function; /* 9 */
161  FILE ** fe_rl_outstream;                    /* 10 */
162  int (*fe_write_history) ();                 /* 11 */
163  int (*fe_history_total_bytes) ();           /* 12 */
164  void (*fe_using_history) ();                /* 13 */
165  int (*fe_read_history) (char *);            /* 14 */
166
167}
168#endif
169char ** singular_completion (char *text, int start, int end)
170{
171  /* If this word is not in a string, then it may be a command
172     to complete.  Otherwise it may be the name of a file in the current
173     directory. */
174#ifdef HAVE_DYN_RL
175  #define x_rl_line_buffer (*fe_rl_line_buffer)
176  #define x_rl_completion_matches (*fe_completion_matches)
177  #define x_rl_filename_completion_function (*fe_filename_completion_function)
178#else
179  #define x_rl_line_buffer rl_line_buffer
180  #define x_rl_completion_matches rl_completion_matches
181  #define x_rl_filename_completion_function rl_filename_completion_function
182#endif
183  if (x_rl_line_buffer[start-1]=='"')
184    return x_rl_completion_matches (text, (RL_PROC)x_rl_filename_completion_function);
185  char **m=x_rl_completion_matches (text, (RL_PROC)command_generator);
186#undef x_rl_line_buffer
187#undef x_rl_completion_matches
188  if (m==NULL)
189  {
190    m=(char **)malloc(2*sizeof(char*));
191    m[0]=(char *)malloc(end-start+2);
192    strncpy(m[0],text,end-start+1);
193    m[1]=NULL;
194  }
195  return m;
196}
197
198#ifndef HAVE_DYN_RL
199char * fe_fgets_stdin_rl(const char *pr,char *s, int size)
200{
201  if (!BVERBOSE(V_PROMPT))
202  {
203    pr="";
204  }
205  mflush();
206
207  char *line;
208  line = readline (pr);
209
210  int i;
211  for (i=strlen(line)-1;i>=0;i--) line[i]=line[i]&127;
212
213  if (line==NULL)
214    return NULL;
215
216  if (*line!='\0')
217  {
218    add_history (line);
219  }
220  int l=strlen(line);
221  if (l>=size-1)
222  {
223    strncpy(s,line,size);
224  }
225  else
226  {
227    strncpy(s,line,l);
228    s[l]='\n';
229    s[l+1]='\0';
230  }
231  free (line);
232
233  return s;
234}
235#endif
236#endif
237
238/* ===================================================================*/
239/* =                    emulated readline                           = */
240/* ===================================================================*/
241#if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
242extern "C" {
243char * fe_fgets_stdin_fe(const char *pr,char *s, int size);
244}
245char * fe_fgets_stdin_emu(const char *pr,char *s, int size)
246{
247  if (!BVERBOSE(V_PROMPT))
248  {
249    pr="";
250  }
251  mflush();
252  return fe_fgets_stdin_fe(pr,s,size);
253}
254#endif
255
256/* ===================================================================*/
257/* =                     dynamic readline                           = */
258/* ===================================================================*/
259/* some procedure are shared with "static readline" */
260#if defined(HAVE_DYN_RL)
261char * fe_fgets_stdin_drl(const char *pr,char *s, int size)
262{
263  if (!BVERBOSE(V_PROMPT))
264  {
265    pr="";
266  }
267  mflush();
268
269  char *line;
270  line = (*fe_readline) ((char*)pr);
271
272  if (line==NULL)
273    return NULL;
274
275  int i;
276  for (i=strlen(line)-1;i>=0;i--) line[i]=line[i]&127;
277
278  if (*line!='\0')
279  {
280    (*fe_add_history) (line);
281  }
282  int l=strlen(line);
283  if (l>=size-1)
284  {
285    strncpy(s,line,size);
286  }
287  else
288  {
289    strncpy(s,line,l);
290    s[l]='\n';
291    s[l+1]='\0';
292  }
293  free (line);
294
295  return s;
296}
297#endif
298
299/* ===================================================================*/
300/* =                        fgets                                   = */
301/* ===================================================================*/
302char * fe_fgets(const char *pr,char *s, int size)
303{
304  if (BVERBOSE(V_PROMPT))
305  {
306    fprintf(stdout,"%s",pr);
307  }
308  mflush();
309  char *line=fgets(s,size,stdin);
310  int i;
311  for (i=strlen(line)-1;i>=0;i--) line[i]=line[i]&127;
312  return line;
313}
314
315/* ===================================================================*/
316/* =       init for static rl, dyn. rl, emu. rl                     = */
317/* ===================================================================*/
318static char * fe_fgets_stdin_init(const char *pr,char *s, int size)
319{
320#if (defined(HAVE_READLINE) || defined(HAVE_LIBREADLINE)) && !defined(HAVE_DYN_RL) && !defined(HAVE_FEREAD)
321  /* Allow conditional parsing of the ~/.inputrc file. */
322  rl_readline_name = "Singular";
323  /* Tell the completer that we want a crack first. */
324#ifdef USE_READLINE4
325  rl_attempted_completion_function = (rl_completion_func_t *)singular_completion;
326#else
327  rl_attempted_completion_function = (CPPFunction *)singular_completion;
328#endif
329
330  /* set the output stream */
331  if(!isatty(STDOUT_FILENO))
332  {
333    #ifdef atarist
334      rl_outstream = fopen( "/dev/tty", "w" );
335    #else
336      rl_outstream = fopen( ttyname(fileno(stdin)), "w" );
337    #endif
338  }
339
340  /* try to read a history */
341  using_history();
342  char *p = getenv("SINGULARHIST");
343  if (p != NULL)
344  {
345    read_history (p);
346  }
347  fe_fgets_stdin=fe_fgets_stdin_rl;
348  return(fe_fgets_stdin_rl(pr,s,size));
349#endif
350#ifdef HAVE_DYN_RL
351  /* do dynamic loading */
352  int res=fe_init_dyn_rl();
353  if (res!=0)
354  {
355    //if (res==1)
356    //  WarnS("dynamic loading of libreadline failed");
357    //else
358    //  Warn("dynamic loading failed: %d\n",res);
359    if (res!=1)
360      Warn("dynamic loading failed: %d\n",res);
361    #ifdef HAVE_FEREAD
362    fe_fgets_stdin=fe_fgets_stdin_emu;
363    #else
364    fe_fgets_stdin=fe_fgets;
365    #endif
366    return fe_fgets_stdin(pr,s,size);
367  }
368  else /* could load libreadline: */
369  {
370    /* Allow conditional parsing of the ~/.inputrc file. */
371    *fe_rl_readline_name = "Singular";
372    /* Tell the completer that we want a crack first. */
373    *fe_rl_attempted_completion_function = (CPPFunction *)singular_completion;
374    /* try to read a history */
375    (*fe_using_history)();
376    char *p = getenv("SINGULARHIST");
377    if (p != NULL)
378    {
379      (*fe_read_history) (p);
380    }
381  }
382
383  /* set the output stream */
384  if(!isatty(STDOUT_FILENO))
385  {
386    #ifdef atarist
387      *fe_rl_outstream = fopen( "/dev/tty", "w" );
388    #else
389      *fe_rl_outstream = fopen( ttyname(fileno(stdin)), "w" );
390    #endif
391  }
392
393  fe_fgets_stdin=fe_fgets_stdin_drl;
394  return fe_fgets_stdin_drl(pr,s,size);
395#else
396  #if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
397    fe_fgets_stdin=fe_fgets_stdin_emu;
398    return(fe_fgets_stdin_emu(pr,s,size));
399  #else
400    fe_fgets_stdin=fe_fgets;
401    return(fe_fgets(pr,s,size));
402  #endif
403#endif
404}
405
406/* ===================================================================*/
407/* =                      batch mode                                = */
408/* ===================================================================*/
409/* dummy (for batch mode): */
410char * fe_fgets_dummy(const char */*pr*/,char */*s*/, int /*size*/)
411{
412  return NULL;
413}
414
Note: See TracBrowser for help on using the repository browser.