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 
11 // ----------------------------------------
12 // system settings:
13 
14 #undef USE_READLINE4
15 
16 //----------------------------------------
17 #ifdef __CYGWIN__
18 #define READLINE_STATIC
19 #endif
20 #include "omalloc/omalloc.h"
21 #include "misc/options.h"
22 
24 
25 #if defined(HAVE_DYN_RL)
26 #include <unistd.h>
27 #endif
28 
29 static char * fe_fgets_stdin_init(const char *pr,char *s, int size);
30 char * (*fe_fgets_stdin)(const char *pr,char *s, int size)
32 
33 extern char *iiArithGetCmd(int);
34 
35 /* ===================================================================*/
36 /* = static/dymanic readline = */
37 /* ===================================================================*/
38 #if defined(HAVE_READLINE) || defined(HAVE_DYN_RL) || defined(HAVE_LIBREADLINE)
39 
40 #ifndef STDOUT_FILENO
41 #define STDOUT_FILENO 1
42 #endif
43 
44 /* Generator function for command completion. STATE lets us know whether
45 * to start from scratch; without any state (i.e. STATE == 0), then we
46 * start at the top of the list.
47 */
48 #include "Singular/ipid.h"
49 extern "C"
50 char *command_generator (char *text, int state)
51 {
52  STATIC_VAR int list_index, len;
54  const char *name;
55 
56  /* If this is a new word to complete, initialize now. This includes
57  saving the length of TEXT for efficiency, and initializing the index
58  variable to 0. */
59  if (state==0)
60  {
61  list_index = 1;
62  len = strlen (text);
63  h=basePack->idroot;
64  }
65 
66  /* Return the next name which partially matches from the command list. */
67  while ((name = iiArithGetCmd(list_index))!=NULL)
68  {
69  list_index++;
70 
71  if (strncmp (name, text, len) == 0)
72  return (strdup(name));
73  }
74  if (len>1)
75  {
76  while (h!=NULL)
77  {
78  name=h->id;
79  h=h->next;
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 
101 // #undef READLINE_READLINE_H_OK
102 
103 extern "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 */
127  char *rl_filename_completion_function(const char*, int);
128  typedef char **CPPFunction ();
129 
130  extern char ** rl_completion_matches (const char*, RL_PROC);
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 
147 char * 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)
158 extern "C"
159 {
160  int fe_init_dyn_rl();
161  char *(*fe_filename_completion_function)(); /* 3 */
162  char *(* fe_readline) (char *); /* 4 */
163  VAR void (*fe_add_history) (char *); /* 5 */
164  VAR char ** fe_rl_readline_name; /* 6 */
165  VAR char **fe_rl_line_buffer; /* 7 */
166  char **(*fe_completion_matches)(...); /* 8 */
168  VAR FILE ** fe_rl_outstream; /* 10 */
169  VAR int (*fe_write_history) (); /* 11 */
170  VAR int (*fe_history_total_bytes) (); /* 12 */
171  VAR void (*fe_using_history) (); /* 13 */
172  VAR int (*fe_read_history) (char *); /* 14 */
173 
174 }
175 #endif
176 char ** 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 ((start>0) && (x_rl_line_buffer[start-1]=='"'))
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
206 char * 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  int l=strlen(line);
221  for (int i=l-1;i>=0;i--) line[i]=line[i]&127;
222 
223  if (*line!='\0')
224  {
225  add_history (line);
226  }
227  if (l>=size-1)
228  {
229  strncpy(s,line,size);
230  }
231  else
232  {
233  strncpy(s,line,l);
234  s[l]='\n';
235  s[l+1]='\0';
236  }
237  free (line);
238 
239  return s;
240 }
241 #endif
242 #endif
243 
244 /* ===================================================================*/
245 /* = emulated readline = */
246 /* ===================================================================*/
247 #if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
248 extern "C" {
249 char * fe_fgets_stdin_fe(const char *pr,char *s, int size);
250 }
251 char * fe_fgets_stdin_emu(const char *pr,char *s, int size)
252 {
253  if (!BVERBOSE(V_PROMPT))
254  {
255  pr="";
256  }
257  mflush();
258  return fe_fgets_stdin_fe(pr,s,size);
259 }
260 #endif
261 
262 /* ===================================================================*/
263 /* = dynamic readline = */
264 /* ===================================================================*/
265 /* some procedure are shared with "static readline" */
266 #if defined(HAVE_DYN_RL)
267 char * fe_fgets_stdin_drl(const char *pr,char *s, int size)
268 {
269  if (!BVERBOSE(V_PROMPT))
270  {
271  pr="";
272  }
273  mflush();
274 
275  char *line;
276  line = (*fe_readline) ((char*)pr);
277 
278  if (line==NULL)
279  return NULL;
280 
281  int l=strlen(line);
282  for (int i=l-1;i>=0;i--) line[i]=line[i]&127;
283 
284  if (*line!='\0')
285  {
286  (*fe_add_history) (line);
287  }
288  if (l>=size-1)
289  {
290  strncpy(s,line,size);
291  }
292  else
293  {
294  strncpy(s,line,l);
295  s[l]='\n';
296  s[l+1]='\0';
297  }
298  free (line);
299 
300  return s;
301 }
302 #endif
303 
304 /* ===================================================================*/
305 /* = fgets = */
306 /* ===================================================================*/
307 char * fe_fgets(const char *pr,char *s, int size)
308 {
309  if (BVERBOSE(V_PROMPT))
310  {
311  fputs(pr,stdout);
312  }
313  mflush();
314  errno=0;
315  char *line=fgets(s,size,stdin);
316  if (line!=NULL)
317  {
318  for (int i=strlen(line)-1;i>=0;i--) line[i]=line[i]&127;
319  }
320  else
321  {
322  /* NULL can mean various things... */
323  switch(errno)
324  {
325  case 0: return NULL; /*EOF */
326  case EBADF: return NULL; /* stdin got closed */
327  case EINTR: return strcpy(s,"\n"); /* CTRL-C or other signal */
328  default: /* other error */
329  {
330  int errsv = errno;
331  fprintf(stderr,"fgets() failed with errno %d\n%s\n",errsv,strerror(errsv));
332  return NULL;
333  }
334  }
335  }
336  return line;
337 }
338 
339 /* ===================================================================*/
340 /* = init for static rl, dyn. rl, emu. rl = */
341 /* ===================================================================*/
342 static char * fe_fgets_stdin_init(const char *pr,char *s, int size)
343 {
344 #if (defined(HAVE_READLINE) || defined(HAVE_LIBREADLINE)) && !defined(HAVE_DYN_RL) && !defined(HAVE_FEREAD)
345  /* Allow conditional parsing of the ~/.inputrc file. */
346  rl_readline_name = (char*)"Singular";
347  /* Tell the completer that we want a crack first. */
348 #ifdef USE_READLINE4
349  rl_attempted_completion_function = (rl_completion_func_t *)singular_completion;
350 #else
352 #endif
353 
354  /* set the output stream */
355  if(!isatty(STDOUT_FILENO))
356  {
357  #ifdef atarist
358  rl_outstream = fopen( "/dev/tty", "w" );
359  #else
360  char *fn=ttyname(fileno(stdin));//if stdout is not a tty, maybe stdin is?
361  if (fn!=NULL) rl_outstream = fopen( fn, "w" );
362  #endif
363  }
364 
366  if(isatty(fileno(stdin)))
367  {
368  /* try to read a history */
370  using_history();
371  char *p = getenv("SINGULARHIST");
372  if (p==NULL) p=SINGULARHIST_FILE;
373  if (strlen(p) != 0)
374  {
375  read_history (p);
376  }
378  return(fe_fgets_stdin_rl(pr,s,size));
379  }
380  else
381  {
383  return(fe_fgets(pr,s,size));
384  }
385 #endif
386 #ifdef HAVE_DYN_RL
387  /* do dynamic loading */
388  int res=fe_init_dyn_rl();
390  if (res!=0)
391  {
392  //if (res==1)
393  // WarnS("dynamic loading of libreadline failed");
394  //else
395  // Warn("dynamic loading failed: %d\n",res);
396  if (res!=1)
397  Warn("dynamic loading failed: %d\n",res);
398  #ifdef HAVE_FEREAD
400  #else
402  #endif
403  return fe_fgets_stdin(pr,s,size);
404  }
405  else if (isatty(STDIN_FILENO))/*and could load libreadline: */
406  {
407  /* Allow conditional parsing of the ~/.inputrc file. */
408  *fe_rl_readline_name = "Singular";
409  /* Tell the completer that we want a crack first. */
411  /* try to read a history */
412  (*fe_using_history)();
414  char *p = getenv("SINGULARHIST");
415  if (p != NULL)
416  {
417  (*fe_read_history) (p);
418  }
419 
420  /* set the output stream */
421  if(!isatty(STDOUT_FILENO))
422  {
423  #ifdef atarist
424  *fe_rl_outstream = fopen( "/dev/tty", "w" );
425  #else
426  char *fn=ttyname(fileno(stdin));//if stdout is not a tty, maybe stdin is?
427  if (fn!=NULL) *fe_rl_outstream = fopen( fn, "w" );
428  #endif
429  }
431  return fe_fgets_stdin_drl(pr,s,size);
432  }
433  else
434  {
436  return fe_fgets(pr,s,size);
437  }
438 #else
439  #if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
441  return(fe_fgets_stdin_emu(pr,s,size));
442  #else
444  return(fe_fgets(pr,s,size));
445  #endif
446 #endif
447 }
448 
449 /* ===================================================================*/
450 /* = batch mode = */
451 /* ===================================================================*/
452 /* dummy (for batch mode): */
453 char * fe_fgets_dummy(const char */*pr*/,char */*s*/, int /*size*/)
454 {
455  return NULL;
456 }
457 
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:131
char * iiArithGetCmd(int)
Definition: iparith.cc:9779
EXTERN_VAR FILE * rl_outstream
Definition: feread.cc:132
char * fe_fgets_stdin_emu(const char *pr, char *s, int size)
Definition: feread.cc:251
VAR BOOLEAN using_history_called
Definition: feread.cc:104
VAR char ** fe_rl_readline_name
Definition: feread.cc:164
char ** singular_completion(char *text, int start, int end)
Definition: feread.cc:176
VAR char ** fe_rl_line_buffer
Definition: feread.cc:165
#define x_rl_filename_completion_function
VAR int(* fe_read_history)(char *)
Definition: feread.cc:172
char ** CPPFunction()
Definition: feread.cc:128
char ** RL_CPPFunction(const char *, int, int)
Definition: feread.cc:143
VAR int(* fe_write_history)()
Definition: feread.cc:169
#define x_rl_completion_matches
char *(* RL_PROC)(const char *, int)
Definition: feread.cc:105
static char * fe_fgets_stdin_init(const char *pr, char *s, int size)
Definition: feread.cc:342
VAR void(* fe_using_history)()
Definition: feread.cc:171
char *(* fe_fgets_stdin)(const char *pr, char *s, int size)
Definition: feread.cc:30
char * fe_fgets(const char *pr, char *s, int size)
Definition: feread.cc:307
VAR CPPFunction ** fe_rl_attempted_completion_function
Definition: feread.cc:167
#define x_rl_line_buffer
VAR int(* fe_history_total_bytes)()
Definition: feread.cc:170
char * command_generator(char *text, int state)
Definition: feread.cc:50
int read_history(char *)
char * fe_fgets_stdin_drl(const char *pr, char *s, int size)
Definition: feread.cc:267
#define rl_completion_matches
Definition: feread.cc:121
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:126
char * fe_fgets_stdin_rl(const char *pr, char *s, int size)
#define STDOUT_FILENO
Definition: feread.cc:41
#define rl_filename_completion_function
Definition: feread.cc:120
int history_total_bytes()
VAR void(* fe_add_history)(char *)
Definition: feread.cc:163
EXTERN_VAR char * rl_readline_name
Definition: feread.cc:125
void using_history()
char * fe_fgets_dummy(const char *, char *, int)
Definition: feread.cc:453
VAR FILE ** fe_rl_outstream
Definition: feread.cc:168
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:34
#define V_PROMPT
Definition: options.h:53
#define mflush()
Definition: reporter.h:58