source: git/kernel/feread.cc @ f2b6f0b

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