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
29static char * fe_fgets_stdin_init(const char *pr,char *s, int size);
30char * (*fe_fgets_stdin)(const char *pr,char *s, int size)
32
33extern 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"
49extern "C"
50char *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
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 */
126 char *rl_filename_completion_function(const char*, int);
127 typedef char **CPPFunction ();
128
129 extern char ** rl_completion_matches (const char*, RL_PROC);
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 *);
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 VAR void (*fe_add_history) (char *); /* 5 */
163 VAR char ** fe_rl_readline_name; /* 6 */
164 VAR char **fe_rl_line_buffer; /* 7 */
165 char **(*fe_completion_matches)(...); /* 8 */
167 VAR FILE ** fe_rl_outstream; /* 10 */
168 VAR int (*fe_write_history) (); /* 11 */
169 VAR int (*fe_history_total_bytes) (); /* 12 */
170 VAR void (*fe_using_history) (); /* 13 */
171 VAR 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 ((start>0) && (x_rl_line_buffer[start-1]=='"'))
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 int l=strlen(line);
220 for (int i=l-1;i>=0;i--) line[i]=line[i]&127;
221
222 if (*line!='\0')
223 {
224 add_history (line);
225 }
226 if (l>=size-1)
227 {
228 strncpy(s,line,size);
229 }
230 else
231 {
232 strncpy(s,line,l);
233 s[l]='\n';
234 s[l+1]='\0';
235 }
236 free (line);
237
238 return s;
239}
240#endif
241#endif
242
243/* ===================================================================*/
244/* = emulated readline = */
245/* ===================================================================*/
246#if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
247extern "C" {
248char * fe_fgets_stdin_fe(const char *pr,char *s, int size);
249}
250char * fe_fgets_stdin_emu(const char *pr,char *s, int size)
251{
252 if (!BVERBOSE(V_PROMPT))
253 {
254 pr="";
255 }
256 mflush();
257 return fe_fgets_stdin_fe(pr,s,size);
258}
259#endif
260
261/* ===================================================================*/
262/* = dynamic readline = */
263/* ===================================================================*/
264/* some procedure are shared with "static readline" */
265#if defined(HAVE_DYN_RL)
266char * fe_fgets_stdin_drl(const char *pr,char *s, int size)
267{
268 if (!BVERBOSE(V_PROMPT))
269 {
270 pr="";
271 }
272 mflush();
273
274 char *line;
275 line = (*fe_readline) ((char*)pr);
276
277 if (line==NULL)
278 return NULL;
279
280 int l=strlen(line);
281 for (int i=l-1;i>=0;i--) line[i]=line[i]&127;
282
283 if (*line!='\0')
284 {
285 (*fe_add_history) (line);
286 }
287 if (l>=size-1)
288 {
289 strncpy(s,line,size);
290 }
291 else
292 {
293 strncpy(s,line,l);
294 s[l]='\n';
295 s[l+1]='\0';
296 }
297 free (line);
298
299 return s;
300}
301#endif
302
303/* ===================================================================*/
304/* = fgets = */
305/* ===================================================================*/
306char * fe_fgets(const char *pr,char *s, int size)
307{
308 if (BVERBOSE(V_PROMPT))
309 {
310 fputs(pr,stdout);
311 }
312 mflush();
313 errno=0;
314 char *line=fgets(s,size,stdin);
315 if (line!=NULL)
316 {
317 for (int i=strlen(line)-1;i>=0;i--) line[i]=line[i]&127;
318 }
319 else
320 {
321 /* NULL can mean various things... */
322 switch(errno)
323 {
324 case 0: return NULL; /*EOF */
325 case EBADF: return NULL; /* stdin got closed */
326 case EINTR: return strcpy(s,"\n"); /* CTRL-C or other signal */
327 default: /* other error */
328 {
329 int errsv = errno;
330 fprintf(stderr,"fgets() failed with errno %d\n%s\n",errsv,strerror(errsv));
331 return NULL;
332 }
333 }
334 }
335 return line;
336}
337
338/* ===================================================================*/
339/* = init for static rl, dyn. rl, emu. rl = */
340/* ===================================================================*/
341static char * fe_fgets_stdin_init(const char *pr,char *s, int size)
342{
343#if (defined(HAVE_READLINE) || defined(HAVE_LIBREADLINE)) && !defined(HAVE_DYN_RL) && !defined(HAVE_FEREAD)
344 /* Allow conditional parsing of the ~/.inputrc file. */
345 rl_readline_name = (char*)"Singular";
346 /* Tell the completer that we want a crack first. */
347#ifdef USE_READLINE4
349#else
351#endif
352
353 /* set the output stream */
354 if(!isatty(STDOUT_FILENO))
355 {
356 #ifdef atarist
357 rl_outstream = fopen( "/dev/tty", "w" );
358 #else
359 char *fn=ttyname(fileno(stdin));//if stdout is not a tty, maybe stdin is?
360 if (fn!=NULL) rl_outstream = fopen( fn, "w" );
361 #endif
362 }
363
364 if(isatty(fileno(stdin)))
365 {
366 /* try to read a history */
368 char *p = getenv("SINGULARHIST");
369 if (p != NULL)
370 {
371 read_history (p);
372 }
374 return(fe_fgets_stdin_rl(pr,s,size));
375 }
376 else
377 {
379 return(fe_fgets(pr,s,size));
380 }
381#endif
382#ifdef HAVE_DYN_RL
383 /* do dynamic loading */
384 int res=fe_init_dyn_rl();
385 if (res!=0)
386 {
387 //if (res==1)
388 // WarnS("dynamic loading of libreadline failed");
389 //else
390 // Warn("dynamic loading failed: %d\n",res);
391 if (res!=1)
392 Warn("dynamic loading failed: %d\n",res);
393 #ifdef HAVE_FEREAD
395 #else
397 #endif
398 return fe_fgets_stdin(pr,s,size);
399 }
400 else if (isatty(STDIN_FILENO))/*and could load libreadline: */
401 {
402 /* Allow conditional parsing of the ~/.inputrc file. */
403 *fe_rl_readline_name = "Singular";
404 /* Tell the completer that we want a crack first. */
406 /* try to read a history */
407 (*fe_using_history)();
408 char *p = getenv("SINGULARHIST");
409 if (p != NULL)
410 {
411 (*fe_read_history) (p);
412 }
413
414 /* set the output stream */
415 if(!isatty(STDOUT_FILENO))
416 {
417 #ifdef atarist
418 *fe_rl_outstream = fopen( "/dev/tty", "w" );
419 #else
420 char *fn=ttyname(fileno(stdin));//if stdout is not a tty, maybe stdin is?
421 if (fn!=NULL) *fe_rl_outstream = fopen( fn, "w" );
422 #endif
423 }
425 return fe_fgets_stdin_drl(pr,s,size);
426 }
427 else
428 {
430 return fe_fgets(pr,s,size);
431 }
432#else
433 #if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
435 return(fe_fgets_stdin_emu(pr,s,size));
436 #else
438 return(fe_fgets(pr,s,size));
439 #endif
440#endif
441}
442
443/* ===================================================================*/
444/* = batch mode = */
445/* ===================================================================*/
446/* dummy (for batch mode): */
447char * fe_fgets_dummy(const char */*pr*/,char */*s*/, int /*size*/)
448{
449 return NULL;
450}
451
#define NULL
Definition: auxiliary.h:104
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:4080
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:196
char * getenv()
EXTERN_VAR CPPFunction * rl_attempted_completion_function
Definition: feread.cc:130
EXTERN_VAR FILE * rl_outstream
Definition: feread.cc:131
char ** CPPFunction()
Definition: feread.cc:127
VAR char ** fe_rl_readline_name
Definition: feread.cc:163
VAR char ** fe_rl_line_buffer
Definition: feread.cc:164
#define x_rl_filename_completion_function
VAR int(* fe_read_history)(char *)
Definition: feread.cc:171
char ** RL_CPPFunction(const char *, int, int)
Definition: feread.cc:142
char * fe_fgets_dummy(const char *, char *, int)
Definition: feread.cc:447
VAR int(* fe_write_history)()
Definition: feread.cc:168
#define x_rl_completion_matches
char * command_generator(char *text, int state)
Definition: feread.cc:50
char *(* fe_fgets_stdin)(const char *pr, char *s, int size)
Definition: feread.cc:30
static char * fe_fgets_stdin_init(const char *pr, char *s, int size)
Definition: feread.cc:341
VAR void(* fe_using_history)()
Definition: feread.cc:170
VAR CPPFunction ** fe_rl_attempted_completion_function
Definition: feread.cc:166
char *(* RL_PROC)(const char *, int)
Definition: feread.cc:104
#define x_rl_line_buffer
VAR int(* fe_history_total_bytes)()
Definition: feread.cc:169
int read_history(char *)
char * readline(const char *)
#define rl_completion_matches
Definition: feread.cc:120
void add_history(char *)
char ** singular_completion(char *text, int start, int end)
Definition: feread.cc:175
char * fe_fgets(const char *pr, char *s, int size)
Definition: feread.cc:306
EXTERN_VAR char * rl_line_buffer
Definition: feread.cc:125
#define STDOUT_FILENO
Definition: feread.cc:41
#define rl_filename_completion_function
Definition: feread.cc:119
int history_total_bytes()
VAR void(* fe_add_history)(char *)
Definition: feread.cc:162
EXTERN_VAR char * rl_readline_name
Definition: feread.cc:124
char * iiArithGetCmd(int)
Definition: iparith.cc:9771
void using_history()
char * fe_fgets_stdin_rl(const char *pr, char *s, int size)
char * fe_fgets_stdin_drl(const char *pr, char *s, int size)
Definition: feread.cc:266
char * fe_fgets_stdin_emu(const char *pr, char *s, int size)
Definition: feread.cc:250
char * fe_fgets_stdin_fe(const char *pr, char *s, int size)
VAR FILE ** fe_rl_outstream
Definition: feread.cc:167
int write_history()
int fe_init_dyn_rl()
Definition: fereadl.c:755
#define STDIN_FILENO
Definition: fereadl.c:51
#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:19
void * malloc(size_t size)
Definition: omalloc.c:92
#define BVERBOSE(a)
Definition: options.h:34
#define V_PROMPT
Definition: options.h:53
#define mflush()
Definition: reporter.h:58