Loading...
Searching...
No Matches
feread.cc
Go to the documentation of this file.
/****************************************
* Computer Algebra System SINGULAR *
****************************************/
/*
* ABSTRACT: input from ttys, simulating fgets
*/
#include "kernel/mod2.h"
#include <errno.h>
#include <stdio.h>
// ----------------------------------------
// system settings:
#undef USE_READLINE4
//----------------------------------------
#ifdef __CYGWIN__
#define READLINE_STATIC
#endif
#include "omalloc/omalloc.h"
#include "misc/options.h"
#include "kernel/oswrapper/feread.h"
#include "reporter/reporter.h"
#if defined(HAVE_DYN_RL)
#include <unistd.h>
#endif
static char * fe_fgets_stdin_init(const char *pr,char *s, int size);
char * (*fe_fgets_stdin)(const char *pr,char *s, int size)
= fe_fgets_stdin_init;
extern char *iiArithGetCmd(int);
/* ===================================================================*/
/* = static/dynamic readline = */
/* ===================================================================*/
#if defined(HAVE_READLINE) || defined(HAVE_DYN_RL) || defined(HAVE_LIBREADLINE)
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
/* Generator function for command completion. STATE lets us know whether
* to start from scratch; without any state (i.e. STATE == 0), then we
* start at the top of the list.
*/
#include "Singular/ipid.h"
extern "C"
char *command_generator (char *text, int state)
{
STATIC_VAR int list_index, len;
STATIC_VAR idhdl h;
const char *name;
/* If this is a new word to complete, initialize now. This includes
saving the length of TEXT for efficiency, and initializing the index
variable to 0. */
if (state==0)
{
list_index = 1;
len = strlen (text);
h=basePack->idroot;
}
/* Return the next name which partially matches from the command list. */
while ((name = iiArithGetCmd(list_index))!=NULL)
{
list_index++;
if (strncmp (name, text, len) == 0)
return (strdup(name));
}
if (len>1)
{
while (h!=NULL)
{
name=h->id;
h=h->next;
if (strncmp (name, text, len) == 0)
return (strdup(name));
}
}
/* If no names matched, then return NULL. */
return ((char *)NULL);
}
#endif
/* ===================================================================*/
/* = static readline = */
/* ===================================================================*/
/* some procedure are shared with "dynamic readline" */
#if (defined(HAVE_READLINE) || defined(HAVE_LIBREADLINE) || defined(HAVE_DYN_RL))
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
// #undef READLINE_READLINE_H_OK
extern "C" {
VAR BOOLEAN using_history_called=FALSE;
typedef char * (*RL_PROC)(const char*,int);
#ifdef READLINE_READLINE_H_OK
#include <readline/readline.h>
#ifdef HAVE_READLINE_HISTORY_H
#include <readline/history.h>
#endif
#endif
#ifdef RL_VERSION_MAJOR
#if (RL_VERSION_MAJOR >= 4)
#define USE_READLINE4
#endif
#endif
#ifndef USE_READLINE4
#define rl_filename_completion_function filename_completion_function
#define rl_completion_matches completion_matches
#endif
#ifndef READLINE_READLINE_H_OK
/* declare everything we need explicitly and do not rely on includes */
EXTERN_VAR char * rl_readline_name;
EXTERN_VAR char *rl_line_buffer;
char *rl_filename_completion_function(const char*, int);
typedef char **CPPFunction ();
extern char ** rl_completion_matches (const char*, RL_PROC);
EXTERN_VAR CPPFunction * rl_attempted_completion_function;
EXTERN_VAR FILE * rl_outstream;
extern char * readline (const char *);
extern void add_history (char *);
extern int write_history ();
extern void using_history();
extern int read_history(char *);
extern int history_total_bytes();
#endif /* READLINE_READLINE_H_OK */
typedef char * (*PROC)();
typedef char **RL_CPPFunction (const char*, int,int);
}
char * fe_fgets_stdin_rl(const char *pr,char *s, int size);
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names or on filenames if it is preceded by " */
/* Attempt to complete on the contents of TEXT. START and END show the
* region of TEXT that contains the word to complete. We can use the
* entire line in case we want to do some simple parsing. Return the
* array of matches, or NULL if there aren't any.
*/
#if defined(HAVE_DYN_RL)
extern "C"
{
int fe_init_dyn_rl();
char *(*fe_filename_completion_function)(); /* 3 */
char *(* fe_readline) (char *); /* 4 */
VAR void (*fe_add_history) (char *); /* 5 */
VAR char ** fe_rl_readline_name; /* 6 */
VAR char **fe_rl_line_buffer; /* 7 */
char **(*fe_completion_matches)(...); /* 8 */
VAR CPPFunction **fe_rl_attempted_completion_function; /* 9 */
VAR FILE ** fe_rl_outstream; /* 10 */
VAR int (*fe_write_history) (); /* 11 */
VAR int (*fe_history_total_bytes) (); /* 12 */
VAR void (*fe_using_history) (); /* 13 */
VAR int (*fe_read_history) (char *); /* 14 */
}
#endif
char ** singular_completion (char *text, int start, int end)
{
/* If this word is not in a string, then it may be a command
to complete. Otherwise it may be the name of a file in the current
directory. */
#ifdef HAVE_DYN_RL
#define x_rl_line_buffer (*fe_rl_line_buffer)
#define x_rl_completion_matches (*fe_completion_matches)
#define x_rl_filename_completion_function (*fe_filename_completion_function)
#else
#define x_rl_line_buffer rl_line_buffer
#define x_rl_completion_matches rl_completion_matches
#define x_rl_filename_completion_function rl_filename_completion_function
#endif
if ((start>0) && (x_rl_line_buffer[start-1]=='"'))
return x_rl_completion_matches (text, (RL_PROC)x_rl_filename_completion_function);
char **m=x_rl_completion_matches (text, (RL_PROC)command_generator);
#undef x_rl_line_buffer
#undef x_rl_completion_matches
if (m==NULL)
{
m=(char **)malloc(2*sizeof(char*));
m[0]=(char *)malloc(end-start+2);
strncpy(m[0],text,end-start+1);
m[1]=NULL;
}
return m;
}
#ifndef HAVE_DYN_RL
char * fe_fgets_stdin_rl(const char *pr,char *s, int size)
{
if (!BVERBOSE(V_PROMPT))
{
pr="";
}
mflush();
char *line;
line = readline (pr);
if (line==NULL)
return NULL;
int l=strlen(line);
for (int i=l-1;i>=0;i--) line[i]=line[i]&127;
if (*line!='\0')
{
add_history (line);
}
if (l>=size-1)
{
strncpy(s,line,size);
}
else
{
strncpy(s,line,l);
s[l]='\n';
s[l+1]='\0';
}
free (line);
return s;
}
#endif
#endif
/* ===================================================================*/
/* = emulated readline = */
/* ===================================================================*/
#if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
extern "C" {
char * fe_fgets_stdin_fe(const char *pr,char *s, int size);
}
char * fe_fgets_stdin_emu(const char *pr,char *s, int size)
{
if (!BVERBOSE(V_PROMPT))
{
pr="";
}
mflush();
return fe_fgets_stdin_fe(pr,s,size);
}
#endif
/* ===================================================================*/
/* = dynamic readline = */
/* ===================================================================*/
/* some procedure are shared with "static readline" */
#if defined(HAVE_DYN_RL)
char * fe_fgets_stdin_drl(const char *pr,char *s, int size)
{
if (!BVERBOSE(V_PROMPT))
{
pr="";
}
mflush();
char *line;
line = (*fe_readline) ((char*)pr);
if (line==NULL)
return NULL;
int l=strlen(line);
for (int i=l-1;i>=0;i--) line[i]=line[i]&127;
if (*line!='\0')
{
(*fe_add_history) (line);
}
if (l>=size-1)
{
strncpy(s,line,size);
}
else
{
strncpy(s,line,l);
s[l]='\n';
s[l+1]='\0';
}
free (line);
return s;
}
#endif
/* ===================================================================*/
/* = fgets = */
/* ===================================================================*/
char * fe_fgets(const char *pr,char *s, int size)
{
if (BVERBOSE(V_PROMPT))
{
fputs(pr,stdout);
}
mflush();
errno=0;
char *line=fgets(s,size,stdin);
if (line!=NULL)
{
for (int i=strlen(line)-1;i>=0;i--) line[i]=line[i]&127;
}
else
{
/* NULL can mean various things... */
switch(errno)
{
case 0: return NULL; /*EOF */
case EBADF: return NULL; /* stdin got closed */
case EINTR: return strcpy(s,"\n"); /* CTRL-C or other signal */
default: /* other error */
{
int errsv = errno;
fprintf(stderr,"fgets() failed with errno %d\n%s\n",errsv,strerror(errsv));
return NULL;
}
}
}
return line;
}
/* ===================================================================*/
/* = init for static rl, dyn. rl, emu. rl = */
/* ===================================================================*/
static char * fe_fgets_stdin_init(const char *pr,char *s, int size)
{
#if (defined(HAVE_READLINE) || defined(HAVE_LIBREADLINE)) && !defined(HAVE_DYN_RL) && !defined(HAVE_FEREAD)
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = (char*)"Singular";
/* Tell the completer that we want a crack first. */
#ifdef USE_READLINE4
rl_attempted_completion_function = (rl_completion_func_t *)singular_completion;
#else
rl_attempted_completion_function = (CPPFunction *)singular_completion;
#endif
/* set the output stream */
if(!isatty(STDOUT_FILENO))
{
#ifdef atarist
rl_outstream = fopen( "/dev/tty", "w" );
#else
char *fn=ttyname(fileno(stdin));//if stdout is not a tty, maybe stdin is?
if (fn!=NULL) rl_outstream = fopen( fn, "w" );
#endif
}
using_history_called=FALSE;
if(isatty(fileno(stdin)))
{
/* try to read a history */
using_history_called=TRUE;
using_history();
char *p = getenv("SINGULARHIST");
if (p==NULL) p=SINGULARHIST_FILE;
if (strlen(p) != 0)
{
read_history (p);
}
fe_fgets_stdin=fe_fgets_stdin_rl;
return(fe_fgets_stdin_rl(pr,s,size));
}
else
{
fe_fgets_stdin=fe_fgets;
return(fe_fgets(pr,s,size));
}
#endif
#ifdef HAVE_DYN_RL
/* do dynamic loading */
int res=fe_init_dyn_rl();
using_history_called=FALSE;
if (res!=0)
{
//if (res==1)
// WarnS("dynamic loading of libreadline failed");
//else
// Warn("dynamic loading failed: %d\n",res);
if (res!=1)
Warn("dynamic loading failed: %d\n",res);
#ifdef HAVE_FEREAD
fe_fgets_stdin=fe_fgets_stdin_emu;
#else
fe_fgets_stdin=fe_fgets;
#endif
return fe_fgets_stdin(pr,s,size);
}
else if (isatty(STDIN_FILENO))/*and could load libreadline: */
{
/* Allow conditional parsing of the ~/.inputrc file. */
*fe_rl_readline_name = "Singular";
/* Tell the completer that we want a crack first. */
*fe_rl_attempted_completion_function = (CPPFunction *)singular_completion;
/* try to read a history */
(*fe_using_history)();
using_history_called=TRUE;
char *p = getenv("SINGULARHIST");
if (p != NULL)
{
(*fe_read_history) (p);
}
/* set the output stream */
if(!isatty(STDOUT_FILENO))
{
#ifdef atarist
*fe_rl_outstream = fopen( "/dev/tty", "w" );
#else
char *fn=ttyname(fileno(stdin));//if stdout is not a tty, maybe stdin is?
if (fn!=NULL) *fe_rl_outstream = fopen( fn, "w" );
#endif
}
fe_fgets_stdin=fe_fgets_stdin_drl;
return fe_fgets_stdin_drl(pr,s,size);
}
else
{
fe_fgets_stdin=fe_fgets;
return fe_fgets(pr,s,size);
}
#else
#if !defined(HAVE_READLINE) && defined(HAVE_FEREAD)
fe_fgets_stdin=fe_fgets_stdin_emu;
return(fe_fgets_stdin_emu(pr,s,size));
#else
fe_fgets_stdin=fe_fgets;
return(fe_fgets(pr,s,size));
#endif
#endif
}
/* ===================================================================*/
/* = batch mode = */
/* ===================================================================*/
/* dummy (for batch mode): */
char * fe_fgets_dummy(const char */*pr*/,char */*s*/, int /*size*/)
{
return NULL;
}
BOOLEAN
int BOOLEAN
Definition auxiliary.h:88
TRUE
#define TRUE
Definition auxiliary.h:101
FALSE
#define FALSE
Definition auxiliary.h:97
size
int size(const CanonicalForm &f, const Variable &v)
int size ( const CanonicalForm & f, const Variable & v )
Definition cf_ops.cc:600
l
int l
Definition cfEzgcd.cc:100
m
int m
Definition cfEzgcd.cc:128
i
int i
Definition cfEzgcd.cc:132
p
int p
Definition cfModGcd.cc:4086
Warn
#define Warn
Definition emacs.cc:77
s
const CanonicalForm int s
Definition facAbsFact.cc:51
res
CanonicalForm res
Definition facAbsFact.cc:60
name
char name(const Variable &v)
Definition factory.h:189
getenv
char * getenv()
rl_attempted_completion_function
EXTERN_VAR CPPFunction * rl_attempted_completion_function
Definition feread.cc:133
rl_outstream
EXTERN_VAR FILE * rl_outstream
Definition feread.cc:134
CPPFunction
char ** CPPFunction()
Definition feread.cc:130
using_history_called
VAR BOOLEAN using_history_called
Definition feread.cc:106
fe_rl_readline_name
VAR char ** fe_rl_readline_name
Definition feread.cc:166
fe_rl_line_buffer
VAR char ** fe_rl_line_buffer
Definition feread.cc:167
x_rl_filename_completion_function
#define x_rl_filename_completion_function
fe_read_history
VAR int(* fe_read_history)(char *)
Definition feread.cc:174
RL_CPPFunction
char ** RL_CPPFunction(const char *, int, int)
Definition feread.cc:145
fe_fgets_dummy
char * fe_fgets_dummy(const char *, char *, int)
Definition feread.cc:455
fe_write_history
VAR int(* fe_write_history)()
Definition feread.cc:171
x_rl_completion_matches
#define x_rl_completion_matches
command_generator
char * command_generator(char *text, int state)
Definition feread.cc:52
fe_fgets_stdin
char *(* fe_fgets_stdin)(const char *pr, char *s, int size)
Definition feread.cc:32
fe_fgets_stdin_init
static char * fe_fgets_stdin_init(const char *pr, char *s, int size)
Definition feread.cc:344
fe_using_history
VAR void(* fe_using_history)()
Definition feread.cc:173
fe_rl_attempted_completion_function
VAR CPPFunction ** fe_rl_attempted_completion_function
Definition feread.cc:169
RL_PROC
char *(* RL_PROC)(const char *, int)
Definition feread.cc:107
x_rl_line_buffer
#define x_rl_line_buffer
fe_history_total_bytes
VAR int(* fe_history_total_bytes)()
Definition feread.cc:172
read_history
int read_history(char *)
readline
char * readline(const char *)
rl_completion_matches
#define rl_completion_matches
Definition feread.cc:123
add_history
void add_history(char *)
singular_completion
char ** singular_completion(char *text, int start, int end)
Definition feread.cc:178
fe_fgets
char * fe_fgets(const char *pr, char *s, int size)
Definition feread.cc:309
rl_line_buffer
EXTERN_VAR char * rl_line_buffer
Definition feread.cc:128
STDOUT_FILENO
#define STDOUT_FILENO
Definition feread.cc:43
rl_filename_completion_function
#define rl_filename_completion_function
Definition feread.cc:122
history_total_bytes
int history_total_bytes()
fe_add_history
VAR void(* fe_add_history)(char *)
Definition feread.cc:165
rl_readline_name
EXTERN_VAR char * rl_readline_name
Definition feread.cc:127
iiArithGetCmd
char * iiArithGetCmd(int)
Definition iparith.cc:10083
using_history
void using_history()
fe_fgets_stdin_rl
char * fe_fgets_stdin_rl(const char *pr, char *s, int size)
fe_fgets_stdin_drl
char * fe_fgets_stdin_drl(const char *pr, char *s, int size)
Definition feread.cc:269
fe_fgets_stdin_emu
char * fe_fgets_stdin_emu(const char *pr, char *s, int size)
Definition feread.cc:253
fe_fgets_stdin_fe
char * fe_fgets_stdin_fe(const char *pr, char *s, int size)
fe_rl_outstream
VAR FILE ** fe_rl_outstream
Definition feread.cc:170
write_history
int write_history()
fe_init_dyn_rl
int fe_init_dyn_rl()
Definition fereadl.c:756
feread.h
SINGULARHIST_FILE
#define SINGULARHIST_FILE
Definition feread.h:20
STDIN_FILENO
#define STDIN_FILENO
Definition fereadl.c:52
STATIC_VAR
#define STATIC_VAR
Definition globaldefs.h:7
EXTERN_VAR
#define EXTERN_VAR
Definition globaldefs.h:6
VAR
#define VAR
Definition globaldefs.h:5
basePack
VAR package basePack
Definition ipid.cc:56
ipid.h
h
STATIC_VAR Poly * h
Definition janet.cc:971
mod2.h
free
#define free
Definition omAllocFunc.c:14
strdup
#define strdup
Definition omAllocFunc.c:18
malloc
#define malloc
Definition omAllocFunc.c:12
NULL
#define NULL
Definition omList.c:12
omalloc.h
options.h
BVERBOSE
#define BVERBOSE(a)
Definition options.h:35
V_PROMPT
#define V_PROMPT
Definition options.h:54
reporter.h
mflush
#define mflush()
Definition reporter.h:58
idhdl
idrec * idhdl
Definition ring.h:22