My Project
feread.cc
Go to the documentation of this file.
1 /****************************************
2 * Computer Algebra System SINGULAR *
3 ****************************************/
4 /*
5 * ABSTRACT: input from ttys, simulating fgets
6 */
7 
8 #include "kernel/mod2.h"
9 #include <errno.h>
10 #include <stdio.h>
11 
12 // ----------------------------------------
13 // system settings:
14 
15 #undef USE_READLINE4
16 
17 //----------------------------------------
18 #ifdef __CYGWIN__
19 #define READLINE_STATIC
20 #endif
21 #include "omalloc/omalloc.h"
22 #include "misc/options.h"
23 
25 #include "reporter/reporter.h"
26 
27 #if defined(HAVE_DYN_RL)
28 #include <unistd.h>
29 #endif
30 
31 static char * fe_fgets_stdin_init(const char *pr,char *s, int size);
32 char * (*fe_fgets_stdin)(const char *pr,char *s, int size)
34 
35 extern char *iiArithGetCmd(int);
36 
37 /* ===================================================================*/
38 /* = static/dymanic readline = */
39 /* ===================================================================*/
40 #if defined(HAVE_READLINE) || defined(HAVE_DYN_RL) || defined(HAVE_LIBREADLINE)
41 
42 #ifndef STDOUT_FILENO
43 #define STDOUT_FILENO 1
44 #endif
45 
46 /* Generator function for command completion. STATE lets us know whether
47 * to start from scratch; without any state (i.e. STATE == 0), then we
48 * start at the top of the list.
49 */
50 #include "Singular/ipid.h"
51 extern "C"
52 char *command_generator (char *text, int state)
53 {
54  STATIC_VAR int list_index, len;
56  const char *name;
57 
58  /* If this is a new word to complete, initialize now. This includes
59  saving the length of TEXT for efficiency, and initializing the index
60  variable to 0. */
61  if (state==0)
62  {
63  list_index = 1;
64  len = strlen (text);
65  h=basePack->idroot;
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  if (len>1)
77  {
78  while (h!=NULL)
79  {
80  name=h->id;
81  h=h->next;
82  if (strncmp (name, text, len) == 0)
83  return (strdup(name));
84  }
85  }
86  /* If no names matched, then return NULL. */
87  return ((char *)NULL);
88 }
89 #endif
90 
91 /* ===================================================================*/
92 /* = static readline = */
93 /* ===================================================================*/
94 /* some procedure are shared with "dynamic readline" */
95 #if (defined(HAVE_READLINE) || defined(HAVE_LIBREADLINE) || defined(HAVE_DYN_RL))
96 #include <unistd.h>
97 #include <stdio.h>
98 #include <stdlib.h>
99 #include <sys/types.h>
100 #include <sys/file.h>
101 #include <sys/stat.h>
102 
103 // #undef READLINE_READLINE_H_OK
104 
105 extern "C" {
107  typedef char * (*RL_PROC)(const char*,int);
108  #ifdef READLINE_READLINE_H_OK
109  #include <readline/readline.h>
110  #ifdef HAVE_READLINE_HISTORY_H
111  #include <readline/history.h>
112  #endif
113  #endif
114 
115  #ifdef RL_VERSION_MAJOR
116  #if (RL_VERSION_MAJOR >= 4)
117  #define USE_READLINE4
118  #endif
119  #endif
120 
121  #ifndef USE_READLINE4
122  #define rl_filename_completion_function filename_completion_function
123  #define rl_completion_matches completion_matches
124  #endif
125  #ifndef READLINE_READLINE_H_OK
126  /* declare everything we need explicitely and do not rely on includes */
129  char *rl_filename_completion_function(const char*, int);
130  typedef char **CPPFunction ();
131 
132  extern char ** rl_completion_matches (const char*, RL_PROC);
135  extern char * readline (const char *);
136  extern void add_history (char *);
137  extern int write_history ();
138  extern void using_history();
139  extern int read_history(char *);
140  extern int history_total_bytes();
141  #endif /* READLINE_READLINE_H_OK */
142 
143  typedef char * (*PROC)();
144 
145  typedef char **RL_CPPFunction (const char*, int,int);
146 }
147 
148 
149 char * fe_fgets_stdin_rl(const char *pr,char *s, int size);
150 
151 /* Tell the GNU Readline library how to complete. We want to try to complete
152  on command names or on filenames if it is preceded by " */
153 
154 /* Attempt to complete on the contents of TEXT. START and END show the
155 * region of TEXT that contains the word to complete. We can use the
156 * entire line in case we want to do some simple parsing. Return the
157 * array of matches, or NULL if there aren't any.
158 */
159 #if defined(HAVE_DYN_RL)
160 extern "C"
161 {
162  int fe_init_dyn_rl();
163  char *(*fe_filename_completion_function)(); /* 3 */
164  char *(* fe_readline) (char *); /* 4 */
165  VAR void (*fe_add_history) (char *); /* 5 */
166  VAR char ** fe_rl_readline_name; /* 6 */
167  VAR char **fe_rl_line_buffer; /* 7 */
168  char **(*fe_completion_matches)(...); /* 8 */
170  VAR FILE ** fe_rl_outstream; /* 10 */
171  VAR int (*fe_write_history) (); /* 11 */
172  VAR int (*fe_history_total_bytes) (); /* 12 */
173  VAR void (*fe_using_history) (); /* 13 */
174  VAR int (*fe_read_history) (char *); /* 14 */
175 
176 }
177 #endif
178 char ** singular_completion (char *text, int start, int end)
179 {
180  /* If this word is not in a string, then it may be a command
181  to complete. Otherwise it may be the name of a file in the current
182  directory. */
183 #ifdef HAVE_DYN_RL
184  #define x_rl_line_buffer (*fe_rl_line_buffer)
185  #define x_rl_completion_matches (*fe_completion_matches)
186  #define x_rl_filename_completion_function (*fe_filename_completion_function)
187 #else
188  #define x_rl_line_buffer rl_line_buffer
189  #define x_rl_completion_matches rl_completion_matches
190  #define x_rl_filename_completion_function rl_filename_completion_function
191 #endif
192  if ((start>0) && (x_rl_line_buffer[start-1]=='"'))
195 #undef x_rl_line_buffer
196 #undef x_rl_completion_matches
197  if (m==NULL)
198  {
199  m=(char **)malloc(2*sizeof(char*));
200  m[0]=(char *)malloc(end-start+2);
201  strncpy(m[0],text,end-start+1);
202  m[1]=NULL;
203  }
204  return m;
205 }
206 
207 #ifndef HAVE_DYN_RL
208 char * fe_fgets_stdin_rl(const char *pr,char *s, int size)
209 {
210  if (!BVERBOSE(V_PROMPT))
211  {
212  pr="";
213  }
214  mflush();
215 
216  char *line;
217  line = readline (pr);
218 
219  if (line==NULL)
220  return NULL;
221 
222  int l=strlen(line);
223  for (int i=l-1;i>=0;i--) line[i]=line[i]&127;
224 
225  if (*line!='\0')
226  {
227  add_history (line);
228  }
229  if (l>=size-1)
230  {
231  strncpy(s,line,size);
232  }
233  else
234  {
235  strncpy(s,line,l);
236  s[l]='\n';
237  s[l+1]='\0';
238  }
239  free (line);
240 
241  return s;
242 }
243 #endif
244 #endif
245 
246 /* ===================================================================*/
247 /* = emulated readline = */
248 /* ===================================================================*/
249 #if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
250 extern "C" {
251 char * fe_fgets_stdin_fe(const char *pr,char *s, int size);
252 }
253 char * fe_fgets_stdin_emu(const char *pr,char *s, int size)
254 {
255  if (!BVERBOSE(V_PROMPT))
256  {
257  pr="";
258  }
259  mflush();
260  return fe_fgets_stdin_fe(pr,s,size);
261 }
262 #endif
263 
264 /* ===================================================================*/
265 /* = dynamic readline = */
266 /* ===================================================================*/
267 /* some procedure are shared with "static readline" */
268 #if defined(HAVE_DYN_RL)
269 char * fe_fgets_stdin_drl(const char *pr,char *s, int size)
270 {
271  if (!BVERBOSE(V_PROMPT))
272  {
273  pr="";
274  }
275  mflush();
276 
277  char *line;
278  line = (*fe_readline) ((char*)pr);
279 
280  if (line==NULL)
281  return NULL;
282 
283  int l=strlen(line);
284  for (int i=l-1;i>=0;i--) line[i]=line[i]&127;
285 
286  if (*line!='\0')
287  {
288  (*fe_add_history) (line);
289  }
290  if (l>=size-1)
291  {
292  strncpy(s,line,size);
293  }
294  else
295  {
296  strncpy(s,line,l);
297  s[l]='\n';
298  s[l+1]='\0';
299  }
300  free (line);
301 
302  return s;
303 }
304 #endif
305 
306 /* ===================================================================*/
307 /* = fgets = */
308 /* ===================================================================*/
309 char * fe_fgets(const char *pr,char *s, int size)
310 {
311  if (BVERBOSE(V_PROMPT))
312  {
313  fputs(pr,stdout);
314  }
315  mflush();
316  errno=0;
317  char *line=fgets(s,size,stdin);
318  if (line!=NULL)
319  {
320  for (int i=strlen(line)-1;i>=0;i--) line[i]=line[i]&127;
321  }
322  else
323  {
324  /* NULL can mean various things... */
325  switch(errno)
326  {
327  case 0: return NULL; /*EOF */
328  case EBADF: return NULL; /* stdin got closed */
329  case EINTR: return strcpy(s,"\n"); /* CTRL-C or other signal */
330  default: /* other error */
331  {
332  int errsv = errno;
333  fprintf(stderr,"fgets() failed with errno %d\n%s\n",errsv,strerror(errsv));
334  return NULL;
335  }
336  }
337  }
338  return line;
339 }
340 
341 /* ===================================================================*/
342 /* = init for static rl, dyn. rl, emu. rl = */
343 /* ===================================================================*/
344 static char * fe_fgets_stdin_init(const char *pr,char *s, int size)
345 {
346 #if (defined(HAVE_READLINE) || defined(HAVE_LIBREADLINE)) && !defined(HAVE_DYN_RL) && !defined(HAVE_FEREAD)
347  /* Allow conditional parsing of the ~/.inputrc file. */
348  rl_readline_name = (char*)"Singular";
349  /* Tell the completer that we want a crack first. */
350 #ifdef USE_READLINE4
351  rl_attempted_completion_function = (rl_completion_func_t *)singular_completion;
352 #else
354 #endif
355 
356  /* set the output stream */
357  if(!isatty(STDOUT_FILENO))
358  {
359  #ifdef atarist
360  rl_outstream = fopen( "/dev/tty", "w" );
361  #else
362  char *fn=ttyname(fileno(stdin));//if stdout is not a tty, maybe stdin is?
363  if (fn!=NULL) rl_outstream = fopen( fn, "w" );
364  #endif
365  }
366 
368  if(isatty(fileno(stdin)))
369  {
370  /* try to read a history */
372  using_history();
373  char *p = getenv("SINGULARHIST");
374  if (p==NULL) p=SINGULARHIST_FILE;
375  if (strlen(p) != 0)
376  {
377  read_history (p);
378  }
380  return(fe_fgets_stdin_rl(pr,s,size));
381  }
382  else
383  {
385  return(fe_fgets(pr,s,size));
386  }
387 #endif
388 #ifdef HAVE_DYN_RL
389  /* do dynamic loading */
390  int res=fe_init_dyn_rl();
392  if (res!=0)
393  {
394  //if (res==1)
395  // WarnS("dynamic loading of libreadline failed");
396  //else
397  // Warn("dynamic loading failed: %d\n",res);
398  if (res!=1)
399  Warn("dynamic loading failed: %d\n",res);
400  #ifdef HAVE_FEREAD
402  #else
404  #endif
405  return fe_fgets_stdin(pr,s,size);
406  }
407  else if (isatty(STDIN_FILENO))/*and could load libreadline: */
408  {
409  /* Allow conditional parsing of the ~/.inputrc file. */
410  *fe_rl_readline_name = "Singular";
411  /* Tell the completer that we want a crack first. */
413  /* try to read a history */
414  (*fe_using_history)();
416  char *p = getenv("SINGULARHIST");
417  if (p != NULL)
418  {
419  (*fe_read_history) (p);
420  }
421 
422  /* set the output stream */
423  if(!isatty(STDOUT_FILENO))
424  {
425  #ifdef atarist
426  *fe_rl_outstream = fopen( "/dev/tty", "w" );
427  #else
428  char *fn=ttyname(fileno(stdin));//if stdout is not a tty, maybe stdin is?
429  if (fn!=NULL) *fe_rl_outstream = fopen( fn, "w" );
430  #endif
431  }
433  return fe_fgets_stdin_drl(pr,s,size);
434  }
435  else
436  {
438  return fe_fgets(pr,s,size);
439  }
440 #else
441  #if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
443  return(fe_fgets_stdin_emu(pr,s,size));
444  #else
446  return(fe_fgets(pr,s,size));
447  #endif
448 #endif
449 }
450 
451 /* ===================================================================*/
452 /* = batch mode = */
453 /* ===================================================================*/
454 /* dummy (for batch mode): */
455 char * fe_fgets_dummy(const char */*pr*/,char */*s*/, int /*size*/)
456 {
457  return NULL;
458 }
459 
int BOOLEAN
Definition: auxiliary.h:87
#define TRUE
Definition: auxiliary.h:100
#define FALSE
Definition: auxiliary.h:96
int size(const CanonicalForm &f, const Variable &v)
int size ( const CanonicalForm & f, const Variable & v )
Definition: cf_ops.cc:600
int l
Definition: cfEzgcd.cc:100
int m
Definition: cfEzgcd.cc:128
int i
Definition: cfEzgcd.cc:132
int p
Definition: cfModGcd.cc:4078
Definition: idrec.h:35
#define Warn
Definition: emacs.cc:77
const CanonicalForm int s
Definition: facAbsFact.cc:51
CanonicalForm res
Definition: facAbsFact.cc:60
char name(const Variable &v)
Definition: factory.h:189
char * getenv()
EXTERN_VAR CPPFunction * rl_attempted_completion_function
Definition: feread.cc:133
char * iiArithGetCmd(int)
Definition: iparith.cc:9813
EXTERN_VAR FILE * rl_outstream
Definition: feread.cc:134
char * fe_fgets_stdin_emu(const char *pr, char *s, int size)
Definition: feread.cc:253
VAR BOOLEAN using_history_called
Definition: feread.cc:106
VAR char ** fe_rl_readline_name
Definition: feread.cc:166
char ** singular_completion(char *text, int start, int end)
Definition: feread.cc:178
VAR char ** fe_rl_line_buffer
Definition: feread.cc:167
#define x_rl_filename_completion_function
VAR int(* fe_read_history)(char *)
Definition: feread.cc:174
char ** CPPFunction()
Definition: feread.cc:130
char ** RL_CPPFunction(const char *, int, int)
Definition: feread.cc:145
VAR int(* fe_write_history)()
Definition: feread.cc:171
#define x_rl_completion_matches
char *(* RL_PROC)(const char *, int)
Definition: feread.cc:107
static char * fe_fgets_stdin_init(const char *pr, char *s, int size)
Definition: feread.cc:344
VAR void(* fe_using_history)()
Definition: feread.cc:173
char *(* fe_fgets_stdin)(const char *pr, char *s, int size)
Definition: feread.cc:32
char * fe_fgets(const char *pr, char *s, int size)
Definition: feread.cc:309
VAR CPPFunction ** fe_rl_attempted_completion_function
Definition: feread.cc:169
#define x_rl_line_buffer
VAR int(* fe_history_total_bytes)()
Definition: feread.cc:172
char * command_generator(char *text, int state)
Definition: feread.cc:52
int read_history(char *)
char * fe_fgets_stdin_drl(const char *pr, char *s, int size)
Definition: feread.cc:269
#define rl_completion_matches
Definition: feread.cc:123
char * fe_fgets_stdin_fe(const char *pr, char *s, int size)
void add_history(char *)
EXTERN_VAR char * rl_line_buffer
Definition: feread.cc:128
char * fe_fgets_stdin_rl(const char *pr, char *s, int size)
#define STDOUT_FILENO
Definition: feread.cc:43
#define rl_filename_completion_function
Definition: feread.cc:122
int history_total_bytes()
VAR void(* fe_add_history)(char *)
Definition: feread.cc:165
EXTERN_VAR char * rl_readline_name
Definition: feread.cc:127
void using_history()
char * fe_fgets_dummy(const char *, char *, int)
Definition: feread.cc:455
VAR FILE ** fe_rl_outstream
Definition: feread.cc:170
int write_history()
char * readline(const char *)
int fe_init_dyn_rl()
Definition: fereadl.c:756
#define SINGULARHIST_FILE
Definition: feread.h:20
#define STDIN_FILENO
Definition: fereadl.c:52
#define STATIC_VAR
Definition: globaldefs.h:7
#define EXTERN_VAR
Definition: globaldefs.h:6
#define VAR
Definition: globaldefs.h:5
VAR package basePack
Definition: ipid.cc:58
STATIC_VAR Poly * h
Definition: janet.cc:971
#define free
Definition: omAllocFunc.c:14
#define strdup
Definition: omAllocFunc.c:18
#define NULL
Definition: omList.c:12
void * malloc(size_t size)
Definition: omalloc.c:85
#define BVERBOSE(a)
Definition: options.h:35
#define V_PROMPT
Definition: options.h:54
#define mflush()
Definition: reporter.h:58