source: git/Singular/feread.cc @ 8f769bb

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