source: git/kernel/feread.cc @ a82c308

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