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