/src/r-source/src/unix/sys-std.c
Line | Count | Source |
1 | | /* |
2 | | * R : A Computer Language for Statistical Data Analysis |
3 | | * Copyright (C) 1997--2026 The R Core Team |
4 | | * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka |
5 | | * |
6 | | * This program is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, a copy is available at |
18 | | * https://www.R-project.org/Licenses/ |
19 | | */ |
20 | | |
21 | | /* <UTF8> char here is mainly handled as a whole string. |
22 | | Does need readline to support it. |
23 | | Appending \n\0 is OK in UTF-8, not general MBCS. |
24 | | Removal of \r is OK on UTF-8. |
25 | | ? use of isspace OK? |
26 | | */ |
27 | | |
28 | | |
29 | | /* See system.txt for a description of functions */ |
30 | | |
31 | | /* select() is essential here, but configure has required it */ |
32 | | |
33 | | #ifdef HAVE_CONFIG_H |
34 | | # include <config.h> |
35 | | #endif |
36 | | |
37 | | #define R_USE_SIGNALS 1 |
38 | | #include <Defn.h> |
39 | | #include <Internal.h> |
40 | | |
41 | | #ifdef HAVE_STRINGS_H |
42 | | /* may be needed to define bzero in FD_ZERO (eg AIX) */ |
43 | | #include <strings.h> |
44 | | #endif |
45 | | |
46 | | #include "Fileio.h" |
47 | | #include "Runix.h" |
48 | | #include "Startup.h" |
49 | | #include <R_ext/Riconv.h> |
50 | | #include <R_ext/Print.h> // for REprintf |
51 | | #include <R_ext/RS.h> // for R_Calloc |
52 | | |
53 | | #define __SYSTEM__ |
54 | | /* includes <sys/select.h> and <sys/time.h> */ |
55 | | #include <R_ext/eventloop.h> |
56 | | #undef __SYSTEM__ |
57 | | |
58 | | #ifdef HAVE_UNISTD_H |
59 | | # include <unistd.h> /* for unlink */ |
60 | | #endif |
61 | | |
62 | | extern SA_TYPE SaveAction; |
63 | | extern Rboolean UsingReadline; |
64 | | extern FILE* ifp; /* from system.c */ |
65 | | |
66 | | /* |
67 | | * 1) FATAL MESSAGES AT STARTUP |
68 | | */ |
69 | | |
70 | | attribute_hidden void Rstd_Suicide(const char *s) |
71 | 0 | { |
72 | 0 | REprintf("Fatal error: %s\n", s); |
73 | | /* Might be called before translation is running */ |
74 | 0 | R_CleanUp(SA_SUICIDE, 2, 0); |
75 | 0 | } |
76 | | |
77 | | /* |
78 | | * 2. CONSOLE I/O |
79 | | */ |
80 | | |
81 | | |
82 | | |
83 | | /*--- I/O Support Code ---*/ |
84 | | |
85 | | /* These routines provide hooks for supporting console I/O. |
86 | | * Under raw Unix these routines simply provide a |
87 | | * connection to the stdio library. |
88 | | * Under a Motif interface the routines would be |
89 | | * considerably more complex. |
90 | | */ |
91 | | |
92 | | /* |
93 | | The following provides a version of select() that catches interrupts |
94 | | and handles them using the supplied interrupt handler or the default |
95 | | one if NULL is supplied. The interrupt handler can return, |
96 | | e.g. after invoking a resume restart. If the interrupt handler |
97 | | returns then the select call is retried. If the timeout is not NULL |
98 | | then the timeout is adjusted for the elapsed time before the retry. |
99 | | If the supplied timeout value is zero, select is called without |
100 | | setting up an error handler since it should return immediately. |
101 | | */ |
102 | | |
103 | | static SIGJMP_BUF seljmpbuf; |
104 | | |
105 | | static void (*oldSigintHandler)(int) = SIG_DFL; |
106 | | |
107 | | typedef void (*sel_intr_handler_t)(void); |
108 | | |
109 | | NORET static void handleSelectInterrupt(int dummy) |
110 | 0 | { |
111 | 0 | signal(SIGINT, oldSigintHandler); |
112 | 0 | SIGLONGJMP(seljmpbuf, 1); |
113 | 0 | } |
114 | | |
115 | | int R_SelectEx(int n, fd_set *readfds, fd_set *writefds, |
116 | | fd_set *exceptfds, struct timeval *timeout, |
117 | | void (*intr)(void)) |
118 | 0 | { |
119 | | /* FD_SETSIZE should be at least 1024 on all supported |
120 | | platforms. If this still turns out to be limiting we will |
121 | | probably need to rewrite internals to use poll() instead of |
122 | | select(). LT */ |
123 | 0 | if (n >= FD_SETSIZE) |
124 | 0 | error("file descriptor is too large for select()"); |
125 | |
|
126 | 0 | if (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0) |
127 | 0 | return select(n, readfds, writefds, exceptfds, timeout); |
128 | 0 | else { |
129 | 0 | volatile sel_intr_handler_t myintr = intr != NULL ? |
130 | 0 | intr : onintr; |
131 | 0 | volatile Rboolean old_interrupts_suspended = R_interrupts_suspended; |
132 | 0 | volatile double base_time = currentTime(); |
133 | 0 | struct timeval tm; |
134 | 0 | if (timeout != NULL) |
135 | 0 | tm = *timeout; |
136 | 0 | retry: |
137 | 0 | if (SIGSETJMP(seljmpbuf, 1)) { |
138 | 0 | myintr(); |
139 | |
|
140 | 0 | if (timeout != NULL) { |
141 | | /* Adjust timeout for elapsed complete seconds; ignore |
142 | | microseconds for now. This modifies the data pointed to |
143 | | by timeval, which is what select() on Linux does as |
144 | | well. */ |
145 | 0 | double new_time = currentTime(); |
146 | 0 | double elapsed = new_time - base_time; |
147 | 0 | base_time = new_time; |
148 | 0 | time_t elapsed_sec = (time_t) elapsed; |
149 | 0 | if (tm.tv_sec > elapsed_sec) |
150 | 0 | tm.tv_sec -= elapsed_sec; |
151 | 0 | else |
152 | 0 | tm.tv_sec = 0; |
153 | 0 | *timeout = tm; |
154 | 0 | } |
155 | |
|
156 | 0 | goto retry; |
157 | 0 | } |
158 | 0 | else { |
159 | 0 | int val; |
160 | | |
161 | | /* make sure interrupts are enabled -- this will be |
162 | | restored if there is a LONGJMP from myintr() to another |
163 | | context. */ |
164 | 0 | R_interrupts_suspended = FALSE; |
165 | | |
166 | | /* check for and handle any pending interrupt registered |
167 | | by the standard handler. */ |
168 | 0 | if (R_interrupts_pending) |
169 | 0 | myintr(); |
170 | | |
171 | | /* install a temporary signal handler for breaking out of |
172 | | a blocking select */ |
173 | 0 | oldSigintHandler = signal(SIGINT, handleSelectInterrupt); |
174 | | |
175 | | /* now do the (possibly blocking) select, restore the |
176 | | signal handler, and return the result of the select. */ |
177 | 0 | val = select(n, readfds, writefds, exceptfds, timeout); |
178 | 0 | signal(SIGINT, oldSigintHandler); |
179 | 0 | R_interrupts_suspended = old_interrupts_suspended; |
180 | 0 | return val; |
181 | 0 | } |
182 | 0 | } |
183 | 0 | } |
184 | | |
185 | | |
186 | | /* |
187 | | This object is used for the standard input and its file descriptor |
188 | | value is reset by setSelectwblplotMask() each time to ensure that it points |
189 | | to the correct value of stdin. |
190 | | */ |
191 | | static InputHandler BasicInputHandler = {StdinActivity, -1, NULL}; |
192 | | |
193 | | /* |
194 | | This can be reset by the initialization routines which |
195 | | can ignore stdin, etc.. |
196 | | */ |
197 | | InputHandler *R_InputHandlers = &BasicInputHandler; |
198 | | |
199 | | /* |
200 | | Initialize the input source handlers used to check for input on the |
201 | | different file descriptors. |
202 | | */ |
203 | | static InputHandler * initStdinHandler(void) |
204 | 0 | { |
205 | 0 | InputHandler *inputs; |
206 | |
|
207 | 0 | inputs = addInputHandler(R_InputHandlers, fileno(stdin), NULL, |
208 | 0 | StdinActivity); |
209 | | /* Defer the X11 registration until it is loaded and actually used. */ |
210 | |
|
211 | 0 | return(inputs); |
212 | 0 | } |
213 | | |
214 | | /* |
215 | | Creates and registers a new InputHandler with the linked list `handlers'. |
216 | | This sets the global variable InputHandlers if it is not already set. |
217 | | In the standard interactive case, this will have been set to be the |
218 | | BasicInputHandler object. |
219 | | |
220 | | Returns the newly created handler which can be used in a call to |
221 | | removeInputHandler. |
222 | | */ |
223 | | InputHandler * |
224 | | addInputHandler(InputHandler *handlers, int fd, InputHandlerProc handler, |
225 | | int activity) |
226 | 0 | { |
227 | 0 | InputHandler *input, *tmp; |
228 | 0 | input = R_Calloc(1, InputHandler); |
229 | |
|
230 | 0 | input->activity = activity; |
231 | 0 | if (fd >= FD_SETSIZE) |
232 | 0 | error("file descriptor is too large for select()"); |
233 | 0 | input->fileDescriptor = fd; |
234 | 0 | input->handler = handler; |
235 | |
|
236 | 0 | tmp = handlers; |
237 | |
|
238 | 0 | if(handlers == NULL) { |
239 | 0 | R_InputHandlers = input; |
240 | 0 | return(input); |
241 | 0 | } |
242 | | |
243 | | /* Go to the end of the list to append the new one. */ |
244 | 0 | while(tmp->next != NULL) { |
245 | 0 | tmp = tmp->next; |
246 | 0 | } |
247 | 0 | tmp->next = input; |
248 | |
|
249 | 0 | return(input); |
250 | 0 | } |
251 | | |
252 | | /* |
253 | | Removes the specified handler from the linked list. |
254 | | |
255 | | See getInputHandler() for first locating the target handler instance. |
256 | | */ |
257 | | int |
258 | | removeInputHandler(InputHandler **handlers, InputHandler *it) |
259 | 0 | { |
260 | 0 | InputHandler *tmp; |
261 | | |
262 | | /* If the handler is the first one in the list, move the list to point |
263 | | to the second element. That's why we use the address of the first |
264 | | element as the first argument. |
265 | | */ |
266 | |
|
267 | 0 | if (it == NULL) return(0); |
268 | | |
269 | 0 | if(*handlers == it) { |
270 | 0 | *handlers = (*handlers)->next; |
271 | 0 | R_Free(it); // use R_Free to match allocation with R_Calloc |
272 | 0 | return(1); |
273 | 0 | } |
274 | | |
275 | 0 | tmp = *handlers; |
276 | |
|
277 | 0 | while(tmp) { |
278 | 0 | if(tmp->next == it) { |
279 | 0 | tmp->next = it->next; |
280 | 0 | R_Free(it); // use R_Free to match allocation with R_Calloc |
281 | 0 | return(1); |
282 | 0 | } |
283 | 0 | tmp = tmp->next; |
284 | 0 | } |
285 | | |
286 | 0 | return(0); |
287 | 0 | } |
288 | | |
289 | | |
290 | | InputHandler * |
291 | | getInputHandler(InputHandler *handlers, int fd) |
292 | 0 | { |
293 | 0 | InputHandler *tmp; |
294 | 0 | tmp = handlers; |
295 | |
|
296 | 0 | while(tmp != NULL) { |
297 | 0 | if(tmp->fileDescriptor == fd) |
298 | 0 | return(tmp); |
299 | 0 | tmp = tmp->next; |
300 | 0 | } |
301 | | |
302 | 0 | return(tmp); |
303 | 0 | } |
304 | | |
305 | | /* |
306 | | Arrange to wait until there is some activity or input pending |
307 | | on one of the file descriptors to which we are listening. |
308 | | |
309 | | We could make the file descriptor mask persistent across |
310 | | calls and change it only when a listener is added or deleted. |
311 | | Later. |
312 | | |
313 | | This replaces the previous version which looked only on stdin and the |
314 | | X11 device connection. This allows more than one X11 device to be |
315 | | open on a different connection. Also, it allows connections a la S4 |
316 | | to be developed on top of this mechanism. |
317 | | */ |
318 | | |
319 | | /* A package can enable polled event handling by making R_PolledEvents |
320 | | point to a non-dummy routine and setting R_wait_usec to a suitable |
321 | | timeout value (e.g. 100000) */ |
322 | | |
323 | 607k | static void nop(void){} |
324 | | |
325 | | void (* R_PolledEvents)(void) = nop; |
326 | | int R_wait_usec = 0; /* 0 means no timeout */ |
327 | | |
328 | | /* For X11 devices */ |
329 | | void (* Rg_PolledEvents)(void) = nop; |
330 | | int Rg_wait_usec = 0; |
331 | | |
332 | | |
333 | | static int setSelectMask(InputHandler *, fd_set *); |
334 | | |
335 | | |
336 | | static |
337 | | fd_set *R_checkActivityEx(int usec, int ignore_stdin, void (*intr)(void)) |
338 | 0 | { |
339 | 0 | int maxfd; |
340 | 0 | struct timeval tv; |
341 | 0 | static fd_set readMask; |
342 | |
|
343 | 0 | if (R_interrupts_pending) { |
344 | 0 | if (intr != NULL) intr(); |
345 | 0 | else onintr(); |
346 | 0 | } |
347 | | |
348 | | /* Solaris (but not POSIX) requires these times to be normalized. |
349 | | POSIX requires up to 31 days to be supported, and we only |
350 | | use up to 2147 secs here. |
351 | | */ |
352 | 0 | tv.tv_sec = usec/1000000; |
353 | 0 | tv.tv_usec = usec % 1000000; |
354 | 0 | maxfd = setSelectMask(R_InputHandlers, &readMask); |
355 | 0 | if (ignore_stdin) |
356 | 0 | FD_CLR(fileno(stdin), &readMask); |
357 | 0 | if (R_SelectEx(maxfd+1, &readMask, NULL, NULL, |
358 | 0 | (usec >= 0) ? &tv : NULL, intr) > 0) |
359 | 0 | return(&readMask); |
360 | 0 | else |
361 | 0 | return(NULL); |
362 | 0 | } |
363 | | |
364 | | fd_set *R_checkActivity(int usec, int ignore_stdin) |
365 | 0 | { |
366 | 0 | return R_checkActivityEx(usec, ignore_stdin, NULL); |
367 | 0 | } |
368 | | |
369 | | /* |
370 | | Create the mask representing the file descriptors select() should |
371 | | monitor and return the maximum of these file descriptors so that |
372 | | it can be passed directly to select(). |
373 | | |
374 | | If the first element of the handlers is the standard input handler |
375 | | then we set its file descriptor to the current value of stdin - its |
376 | | file descriptor. |
377 | | */ |
378 | | |
379 | | static int |
380 | | setSelectMask(InputHandler *handlers, fd_set *readMask) |
381 | 0 | { |
382 | 0 | int maxfd = -1; |
383 | 0 | InputHandler *tmp = handlers; |
384 | 0 | FD_ZERO(readMask); |
385 | | |
386 | | /* If we are dealing with BasicInputHandler always put stdin */ |
387 | 0 | if(handlers == &BasicInputHandler) { |
388 | 0 | handlers->fileDescriptor = fileno(stdin); |
389 | 0 | if (handlers->fileDescriptor >= FD_SETSIZE) |
390 | 0 | error("file descriptor is too large for select()"); |
391 | 0 | } |
392 | |
|
393 | 0 | while(tmp) { |
394 | 0 | FD_SET(tmp->fileDescriptor, readMask); |
395 | 0 | maxfd = maxfd < tmp->fileDescriptor ? tmp->fileDescriptor : maxfd; |
396 | 0 | tmp = tmp->next; |
397 | 0 | } |
398 | |
|
399 | 0 | return(maxfd); |
400 | 0 | } |
401 | | |
402 | | void R_runHandlers(InputHandler *handlers, fd_set *readMask) |
403 | 0 | { |
404 | 0 | InputHandler *tmp = handlers, *next; |
405 | |
|
406 | 0 | if (readMask == NULL) { |
407 | 0 | Rg_PolledEvents(); |
408 | 0 | R_PolledEvents(); |
409 | 0 | } else |
410 | 0 | while(tmp) { |
411 | | /* Do this way as the handler function might call |
412 | | removeInputHandlers */ |
413 | 0 | next = tmp->next; |
414 | 0 | if(FD_ISSET(tmp->fileDescriptor, readMask) |
415 | 0 | && tmp->handler != NULL) |
416 | 0 | tmp->handler((void*) tmp->userData); |
417 | 0 | tmp = next; |
418 | 0 | } |
419 | 0 | } |
420 | | |
421 | | /* The following routine is still used by the internet routines, but |
422 | | * it should eventually go away. */ |
423 | | |
424 | | InputHandler * |
425 | | getSelectedHandler(InputHandler *handlers, fd_set *readMask) |
426 | 0 | { |
427 | 0 | InputHandler *tmp = handlers; |
428 | | |
429 | | /* |
430 | | Temporarily skip the first one if a) there is another one, and |
431 | | b) this is the BasicInputHandler. |
432 | | */ |
433 | 0 | if(handlers == &BasicInputHandler && handlers->next) |
434 | 0 | tmp = handlers->next; |
435 | |
|
436 | 0 | while(tmp) { |
437 | 0 | if(FD_ISSET(tmp->fileDescriptor, readMask)) |
438 | 0 | return(tmp); |
439 | 0 | tmp = tmp->next; |
440 | 0 | } |
441 | | /* Now deal with the first one. */ |
442 | 0 | if(FD_ISSET(handlers->fileDescriptor, readMask)) |
443 | 0 | return(handlers); |
444 | | |
445 | 0 | return((InputHandler*) NULL); |
446 | 0 | } |
447 | | |
448 | | |
449 | | #ifdef HAVE_LIBREADLINE |
450 | | /* As from R 3.4.0, this implies we have the headers too. |
451 | | We use entry points |
452 | | |
453 | | rl_callback_handler_install |
454 | | rl_callback_handler_remove |
455 | | rl_callback_read_char |
456 | | rl_readline_name |
457 | | |
458 | | , if HAVE_RL_COMPLETION_MATCHES (>= 4.2) |
459 | | |
460 | | rl_attempted_completion_function |
461 | | rl_attempted_completion_over |
462 | | rl_basic_word_break_characters |
463 | | rl_completer_word_break_characters |
464 | | rl_completion_append_character |
465 | | rl_completion_matches |
466 | | rl_line_buffer |
467 | | |
468 | | and others conditionally: |
469 | | |
470 | | rl_cleanup_after_signal (>= 4.0) |
471 | | rl_done |
472 | | rl_end |
473 | | rl_free_line_state (>= 4.0) |
474 | | rl_line_buffer |
475 | | rl_mark |
476 | | rl_point |
477 | | rl_readline_state (>= 4.2) |
478 | | rl_resize_terminal (>= 4.0) |
479 | | rl_sort_completion_matches (>= 6.0) |
480 | | */ |
481 | | |
482 | | # include <readline/readline.h> |
483 | | |
484 | | /* For compatibility with pre-readline-4.2 systems, also missing in |
485 | | Apple's emulation via the NetBSD editline library, aka libedit. |
486 | | _RL_FUNCTION_TYPEDEF is not currently defined anywhere. |
487 | | */ |
488 | | # if !defined (_RL_FUNCTION_TYPEDEF) |
489 | | typedef void rl_vcpfunc_t (char *); |
490 | | # endif /* _RL_FUNCTION_TYPEDEF */ |
491 | | |
492 | | # if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0603 |
493 | | /* readline 6.3's rl_callback_handler_install() no longer installs |
494 | | signal handlers, so as from that version we need an explicit |
495 | | one. (PR#16604) (This could have been controlled in earlier versions |
496 | | by setting rl_catch_sigwinch.) |
497 | | */ |
498 | | # define NEED_INT_HANDLER |
499 | | # endif |
500 | | |
501 | | #if defined(HAVE_LIBREADLINE) && defined(HAVE_TILDE_EXPAND_WORD) |
502 | | attribute_hidden |
503 | | char *R_ExpandFileName_readline(const char *s, char *buff) |
504 | 41.0k | { |
505 | 41.0k | char *s2 = tilde_expand_word(s); |
506 | 41.0k | size_t len = strlen(s2); |
507 | | |
508 | 41.0k | strncpy(buff, s2, R_PATH_MAX); |
509 | 41.0k | if(len >= R_PATH_MAX) { |
510 | 0 | buff[R_PATH_MAX-1] = '\0'; |
511 | 0 | warning(_("expanded path length %lld would be too long for\n%s\n"), |
512 | 0 | (long long)len, s); |
513 | 0 | } |
514 | 41.0k | free(s2); |
515 | 41.0k | return buff; |
516 | 41.0k | } |
517 | | #endif |
518 | | |
519 | | # ifdef HAVE_READLINE_HISTORY_H |
520 | | # include <readline/history.h> |
521 | | # endif |
522 | | |
523 | | |
524 | | /* callback for rl_callback_read_char */ |
525 | | |
526 | | |
527 | | /* |
528 | | |
529 | | There has been a general problem with asynchronous calls to browser and |
530 | | anything that uses the standard console reading facilities asynchronously |
531 | | (e.g. scan(), parse(), menu()). The basic problem is as follows. We |
532 | | are in the usual input loop awaiting characters typed by the user. Then |
533 | | asynchronously, we enter the browser due to a callback that is invoked |
534 | | from the background event loop that is active while waiting for the user |
535 | | input. At this point, we essentially are starting a new readline |
536 | | session and it is important that we restore the old one when we complete |
537 | | the browse-related one. But unfortunately, we are using global variables |
538 | | and restoring it is not currently being done. |
539 | | So this is an attempt to a) remove the global variables (which will |
540 | | help with threading), and b) ensure that the relevant readline handlers |
541 | | are restored when an asynchronous reader completes its task. |
542 | | |
543 | | Cleaning up after errors is still an issue that needs investigation |
544 | | and whether the current setup does the correct thing. |
545 | | Related to this is whether nested calls (e.g. within a browser, we |
546 | | do other calls to browser() or scan and whether these i) |
547 | | accumulate on our readline stack, and ii) are unwound correctly. |
548 | | If they don't accumulate, we need only keep function pointers on |
549 | | this stack. 10 seems safe for most use and is an improvement |
550 | | over the abort's that we were getting due to the lack of |
551 | | a readline handler being registered. |
552 | | DTL. |
553 | | */ |
554 | | |
555 | | typedef struct _R_ReadlineData R_ReadlineData; |
556 | | |
557 | | struct _R_ReadlineData { |
558 | | |
559 | | int readline_gotaline; |
560 | | int readline_addtohistory; |
561 | | int readline_len; |
562 | | int readline_eof; |
563 | | unsigned char *readline_buf; |
564 | | unsigned char *readline_rest; |
565 | | R_ReadlineData *prev; |
566 | | |
567 | | }; |
568 | | |
569 | | static R_ReadlineData *rl_top = NULL; |
570 | | |
571 | | #define MAX_READLINE_NESTING 10 |
572 | | |
573 | | static struct { |
574 | | int current; |
575 | | int max; |
576 | | rl_vcpfunc_t *fun[MAX_READLINE_NESTING]; |
577 | | } ReadlineStack = {-1, MAX_READLINE_NESTING - 1}; |
578 | | |
579 | | #ifdef NEED_INT_HANDLER |
580 | | static volatile Rboolean caught_sigwinch = FALSE; |
581 | | |
582 | | static void |
583 | | R_readline_sigwinch_handler(int sig) |
584 | 0 | { |
585 | 0 | caught_sigwinch = TRUE; |
586 | 0 | } |
587 | | #endif |
588 | | |
589 | | /* |
590 | | Registers the specified routine and prompt with readline |
591 | | and keeps a record of it on the top of the R readline stack. |
592 | | */ |
593 | | static void |
594 | | pushReadline(const char *prompt, rl_vcpfunc_t f) |
595 | 0 | { |
596 | 0 | if(ReadlineStack.current >= ReadlineStack.max) { |
597 | 0 | warning(_("An unusual circumstance has arisen in the nesting of readline input. Please report using bug.report()")); |
598 | 0 | } else |
599 | 0 | ReadlineStack.fun[++ReadlineStack.current] = f; |
600 | |
|
601 | 0 | rl_callback_handler_install(prompt, f); |
602 | |
|
603 | 0 | #ifdef NEED_INT_HANDLER |
604 | 0 | struct sigaction sa; |
605 | 0 | sigemptyset(&sa.sa_mask); |
606 | 0 | sa.sa_handler = &R_readline_sigwinch_handler; |
607 | 0 | sa.sa_flags = SA_RESTART; |
608 | 0 | sigaction(SIGWINCH, &sa, NULL); |
609 | 0 | #endif |
610 | | |
611 | | /* flush stdout in case readline wrote the prompt, but didn't flush |
612 | | stdout to make it visible. (needed for Apple's readline emulation). */ |
613 | 0 | fflush(stdout); |
614 | 0 | } |
615 | | |
616 | | #if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0600 |
617 | | /* |
618 | | Fix for PR#16603, for readline >= 6.0. |
619 | | |
620 | | The readline interface is somewhat messy. readline contains the |
621 | | function rl_free_line_state(), which its internal SIGINT handler |
622 | | calls. However, it only cancels keyboard macros and certain other |
623 | | things: it does not clear the line. Also, as of readline 6.3, its |
624 | | SIGINT handler is no longer triggered during our select() loop since |
625 | | rl_callback_handler_install() no longer installs signal handlers. |
626 | | So we have to catch the signal and do all the work ourselves to get |
627 | | Bash-like behavior on Ctrl-C. |
628 | | */ |
629 | | static void resetReadline(void) |
630 | 0 | { |
631 | 0 | rl_free_line_state(); |
632 | | /* This might be helpful/needed in future, but we cannot tell until |
633 | | readline 7.0 is released. Only info so far: |
634 | | https://lists.gnu.org/archive/html/bug-readline/2016-02/msg00000.html |
635 | | #ifdef HAVE_RL_CALLBACK_SIGCLEANUP |
636 | | rl_callback_sigcleanup(); |
637 | | #endif |
638 | | */ |
639 | 0 | rl_cleanup_after_signal(); |
640 | 0 | RL_UNSETSTATE(RL_STATE_ISEARCH | RL_STATE_NSEARCH | RL_STATE_VIMOTION | |
641 | 0 | RL_STATE_NUMERICARG | RL_STATE_MULTIKEY); |
642 | | /* The following two lines should be equivalent, but doing both |
643 | | won't hurt. */ |
644 | 0 | rl_line_buffer[rl_point = rl_end = rl_mark = 0] = 0; |
645 | 0 | rl_done = 1; |
646 | 0 | } |
647 | | #endif |
648 | | |
649 | | /* |
650 | | Unregister the current readline handler and pop it from R's readline |
651 | | stack, followed by re-registering the previous one. |
652 | | */ |
653 | | static void popReadline(void) |
654 | 0 | { |
655 | 0 | if(ReadlineStack.current > -1) { |
656 | 0 | #if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0600 |
657 | 0 | resetReadline(); |
658 | 0 | #endif |
659 | 0 | rl_callback_handler_remove(); |
660 | 0 | ReadlineStack.fun[ReadlineStack.current--] = NULL; |
661 | 0 | if(ReadlineStack.current > -1 && ReadlineStack.fun[ReadlineStack.current]) |
662 | 0 | rl_callback_handler_install("", ReadlineStack.fun[ReadlineStack.current]); |
663 | 0 | } |
664 | 0 | } |
665 | | |
666 | | static void readline_handler(char *line) |
667 | 0 | { |
668 | 0 | R_size_t buflen = rl_top->readline_len; |
669 | |
|
670 | | #if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0802 |
671 | | /* In this version of readline, rl_redisplay called from |
672 | | popReadline -> rl_free_line_state (-> rl_clear_message -> rl_redisplay) |
673 | | wipes the prompt and moves the cursor accordingly, causing |
674 | | undesirable indentation here when the input is empty, but the |
675 | | cursor has been moved to the next line. |
676 | | As a work-around, clear the prompt. */ |
677 | | if (line && !line[0]) rl_set_prompt(""); |
678 | | #endif |
679 | 0 | popReadline(); |
680 | |
|
681 | 0 | if ((rl_top->readline_eof = !line)) /* Yes, I don't mean ==...*/ |
682 | 0 | return; |
683 | 0 | if (line[0]) { |
684 | 0 | # ifdef HAVE_READLINE_HISTORY_H |
685 | 0 | if (strlen(line) && rl_top->readline_addtohistory) |
686 | 0 | add_history(line); |
687 | 0 | # endif |
688 | | /* line does not include \n. We should behave like fgets(), so pretend |
689 | | that the line terminator was read and return it in the buffer. We |
690 | | should terminate the string by \0 (regardless of that R_ReplConsole |
691 | | is robust against non-termination). |
692 | | |
693 | | If the line does not fit into the buffer, we should only return |
694 | | a \0 terminated prefix that fits (not terminated by \n\0), like |
695 | | fgets(). We place the rest into readline_rest so that it can |
696 | | be returned by subsequent calls to ReadConsole. |
697 | | |
698 | | In principle. we might as well return the original buffer with the |
699 | | whole line we get from readline, but the readline documentation |
700 | | states that the buffer should be freed by the _handler_ (emphasis |
701 | | added) when it is done with it. So better copy to be safe. */ |
702 | 0 | size_t l = strlen(line); |
703 | 0 | if(l < buflen - 1) { |
704 | 0 | memcpy(rl_top->readline_buf, line, l); |
705 | 0 | rl_top->readline_buf[l] = '\n'; |
706 | 0 | rl_top->readline_buf[l+1] = '\0'; |
707 | 0 | } else { |
708 | 0 | memcpy(rl_top->readline_buf, line, buflen - 1); |
709 | 0 | rl_top->readline_buf[buflen - 1] = '\0'; |
710 | 0 | size_t lrest = l - buflen + 1; |
711 | 0 | rl_top->readline_rest = R_Calloc(lrest + 2, unsigned char); |
712 | 0 | memcpy(rl_top->readline_rest, line + buflen - 1, lrest); |
713 | 0 | rl_top->readline_rest[lrest] = '\n'; |
714 | 0 | rl_top->readline_rest[lrest + 1] = '\0'; |
715 | 0 | } |
716 | 0 | } |
717 | 0 | else { |
718 | 0 | rl_top->readline_buf[0] = '\n'; |
719 | 0 | rl_top->readline_buf[1] = '\0'; |
720 | 0 | } |
721 | 0 | free(line); |
722 | 0 | rl_top->readline_gotaline = 1; |
723 | 0 | } |
724 | | |
725 | | /* |
726 | | An extension or override for the standard interrupt handler (Ctrl-C) |
727 | | that pops the readline stack and then calls the regular/standard |
728 | | interrupt handler. This could be done in a nicer and more general way. |
729 | | It may be necessary for embedding, etc. although it may not be an issue |
730 | | there (as the host application will presumably handle signals). |
731 | | by allowing us to add C routines to be called |
732 | | at the conclusion of the context. At the moment there is only one such routine |
733 | | allowed, and so we would have to chain them. This just leads to a different set of |
734 | | maintenance problems when we rely on the authors of individual routines to |
735 | | not break the chain! |
736 | | Note that the readline stack is not popped when a SIGUSR1 or SIGUSR2 occurs |
737 | | during the select. But of course, we are about to terminate the R session at |
738 | | that point so it shouldn't be relevant except in the embedded case. But |
739 | | the host application will probably not let things get that far and trap the |
740 | | signals itself. |
741 | | */ |
742 | | static void |
743 | | handleInterrupt(void) |
744 | 0 | { |
745 | 0 | popReadline(); |
746 | 0 | onintrNoResume(); |
747 | 0 | } |
748 | | |
749 | | #ifdef HAVE_RL_COMPLETION_MATCHES |
750 | | /* ============================================================ |
751 | | function-completion interface formerly in package rcompletion by |
752 | | Deepayan Sarkar, whose comments these are (mainly). |
753 | | */ |
754 | | |
755 | | static char **R_custom_completion(const char *text, int start, int end); |
756 | | static char *R_completion_generator(const char *text, int state); |
757 | | |
758 | | static SEXP |
759 | | RComp_assignBufferSym, |
760 | | RComp_assignStartSym, |
761 | | RComp_assignEndSym, |
762 | | RComp_assignTokenSym, |
763 | | RComp_completeTokenSym, |
764 | | RComp_getFileCompSym, |
765 | | RComp_retrieveCompsSym; |
766 | | |
767 | | attribute_hidden |
768 | | void set_rl_word_breaks(const char *str) |
769 | 32 | { |
770 | 32 | static char p1[201], p2[203]; |
771 | 32 | strncpy(p1, str, 200); p1[200]= '\0'; |
772 | 32 | strncpy(p2, p1, 200); p2[200] = '\0'; |
773 | 32 | strcat(p2, "[]"); |
774 | 32 | rl_basic_word_break_characters = p2; |
775 | 32 | rl_completer_word_break_characters = p1; |
776 | 32 | } |
777 | | |
778 | | |
779 | | /* Tell the GNU Readline library how to complete. */ |
780 | | |
781 | | static int rcompgen_active = -1; |
782 | | static SEXP rcompgen_rho; |
783 | | |
784 | | #include <R_ext/Parse.h> |
785 | | static void initialize_rlcompletion(void) |
786 | 0 | { |
787 | 0 | if(rcompgen_active >= 0) return; |
788 | | |
789 | | /* Find if package utils is around */ |
790 | 0 | if(rcompgen_active < 0) { |
791 | 0 | char *p = getenv("R_COMPLETION"); |
792 | 0 | if(p && streql(p, "FALSE")) { |
793 | 0 | rcompgen_active = 0; |
794 | 0 | return; |
795 | 0 | } |
796 | | /* First check if namespace is loaded */ |
797 | 0 | if(R_findVarInFrame(R_NamespaceRegistry, install("utils")) |
798 | 0 | != R_UnboundValue) rcompgen_active = 1; |
799 | 0 | else { /* Then try to load it */ |
800 | 0 | SEXP cmdSexp, cmdexpr; |
801 | 0 | ParseStatus status; |
802 | 0 | int i; |
803 | 0 | char *p = "try(loadNamespace('utils'), silent=TRUE)"; |
804 | |
|
805 | 0 | PROTECT(cmdSexp = mkString(p)); |
806 | 0 | cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue)); |
807 | 0 | if(status == PARSE_OK) { |
808 | 0 | for(i = 0; i < length(cmdexpr); i++) |
809 | 0 | eval(VECTOR_ELT(cmdexpr, i), R_GlobalEnv); |
810 | 0 | } |
811 | 0 | UNPROTECT(2); |
812 | 0 | if(R_findVarInFrame(R_NamespaceRegistry, install("utils")) |
813 | 0 | != R_UnboundValue) rcompgen_active = 1; |
814 | 0 | else { |
815 | 0 | rcompgen_active = 0; |
816 | 0 | return; |
817 | 0 | } |
818 | 0 | } |
819 | 0 | } |
820 | | |
821 | 0 | rcompgen_rho = R_FindNamespace(mkString("utils")); |
822 | |
|
823 | 0 | RComp_assignBufferSym = install(".assignLinebuffer"); |
824 | 0 | RComp_assignStartSym = install(".assignStart"); |
825 | 0 | RComp_assignEndSym = install(".assignEnd"); |
826 | 0 | RComp_assignTokenSym = install(".assignToken"); |
827 | 0 | RComp_completeTokenSym = install(".completeToken"); |
828 | 0 | RComp_getFileCompSym = install(".getFileComp"); |
829 | 0 | RComp_retrieveCompsSym = install(".retrieveCompletions"); |
830 | | |
831 | | /* Tell the completer that we want a crack first. */ |
832 | 0 | rl_attempted_completion_function = R_custom_completion; |
833 | | |
834 | | // This was added in readline 6.0: default is 1 (and was in earlier versions) |
835 | 0 | #ifdef HAVE_RL_SORT_COMPLETION_MATCHES |
836 | 0 | rl_sort_completion_matches = 0; |
837 | 0 | #endif |
838 | | |
839 | | /* token boundaries. Includes *,+ etc, but not $,@ because those |
840 | | are easier to handle at the R level if the whole thing is |
841 | | available. However, this breaks filename completion if partial |
842 | | filenames contain things like $, % etc. Might be possible to |
843 | | associate a M-/ override like bash does. One compromise is that |
844 | | we exclude / from the breakers because that is frequently found |
845 | | in filenames even though it is also an operator. This can be |
846 | | handled in R code (although it shouldn't be necessary if users |
847 | | surround operators with spaces, as they should). */ |
848 | | |
849 | | /* FIXME: quotes currently lead to filename completion without any |
850 | | further ado. This is not necessarily the best we can do, since |
851 | | quotes after a [, $, [[, etc should be treated differently. I'm |
852 | | not testing this now, but this should be doable by removing quote |
853 | | characters from the strings below and handle it with other things |
854 | | in 'specialCompletions()' in R. The problem with that approach |
855 | | is that file name completion will probably have to be done |
856 | | manually in R, which is not trivial. One way to go might be to |
857 | | forego file name completion altogether when TAB completing, and |
858 | | associate M-/ or something to filename completion (a startup |
859 | | message might say so, to remind users) |
860 | | |
861 | | All that might not be worth the pain though (vector names would |
862 | | be practically impossible, to begin with) */ |
863 | | |
864 | |
|
865 | 0 | return; |
866 | 0 | } |
867 | | |
868 | | |
869 | | |
870 | | /* Attempt to complete on the contents of TEXT. START and END bound the |
871 | | region of rl_line_buffer that contains the word to complete. TEXT is |
872 | | the word to complete. We can use the entire contents of rl_line_buffer |
873 | | in case we want to do some simple parsing. Return the array of matches, |
874 | | or NULL if there aren't any. */ |
875 | | |
876 | | static char ** |
877 | | R_custom_completion(const char *text, int start, int end) |
878 | | /* |
879 | | Make some relevant information available to R, then call |
880 | | rl_completion_matches to generate matches. FIXME: It would be |
881 | | nice if we could figure whether we are in a partially |
882 | | completed line (R prompt == "+"), in which case we could keep |
883 | | the old line buffer around and do useful things with it. |
884 | | */ |
885 | 0 | { |
886 | 0 | char **matches = (char **)NULL; |
887 | 0 | SEXP infile, |
888 | 0 | linebufferCall = PROTECT(lang2(RComp_assignBufferSym, |
889 | 0 | mkString(rl_line_buffer))), |
890 | 0 | startCall = PROTECT(lang2(RComp_assignStartSym, ScalarInteger(start))), |
891 | 0 | endCall = PROTECT(lang2(RComp_assignEndSym,ScalarInteger(end))); |
892 | 0 | SEXP filecompCall; |
893 | | |
894 | | /* Don't want spaces appended at the end. Need to do this |
895 | | everytime, as readline>=6 resets it to ' ' */ |
896 | 0 | rl_completion_append_character = '\0'; |
897 | |
|
898 | 0 | eval(linebufferCall, rcompgen_rho); |
899 | 0 | eval(startCall, rcompgen_rho); |
900 | 0 | eval(endCall, rcompgen_rho); |
901 | 0 | UNPROTECT(3); |
902 | 0 | matches = rl_completion_matches(text, R_completion_generator); |
903 | 0 | filecompCall = PROTECT(lang1(RComp_getFileCompSym)); |
904 | 0 | infile = PROTECT(eval(filecompCall, rcompgen_rho)); |
905 | 0 | if (!asLogical(infile)) rl_attempted_completion_over = 1; |
906 | 0 | UNPROTECT(2); |
907 | 0 | return matches; |
908 | 0 | } |
909 | | |
910 | | /* R_completion_generator does the actual work (it is called from |
911 | | somewhere inside rl_completion_matches repeatedly). See readline |
912 | | documentation for details, but one important fact is that the |
913 | | return value of R_completion_generator will be free()-d by |
914 | | readline */ |
915 | | |
916 | | /* Generator function for command completion. STATE lets us know |
917 | | whether to start from scratch: we do so when STATE == 0 */ |
918 | | |
919 | | static char *R_completion_generator(const char *text, int state) |
920 | 0 | { |
921 | 0 | static int list_index, ncomp; |
922 | 0 | static char **compstrings; |
923 | | |
924 | | /* If this is a new word to complete, initialize now. This |
925 | | involves saving 'text' to somewhere R can get at it, calling |
926 | | completeToken(), and retrieving the completions. */ |
927 | |
|
928 | 0 | if (!state) { |
929 | 0 | SEXP |
930 | 0 | assignCall = PROTECT(lang2(RComp_assignTokenSym, mkString(text))), |
931 | 0 | completionCall = PROTECT(lang1(RComp_completeTokenSym)), |
932 | 0 | retrieveCall = PROTECT(lang1(RComp_retrieveCompsSym)); |
933 | 0 | const void *vmax = vmaxget(); |
934 | |
|
935 | 0 | eval(assignCall, rcompgen_rho); |
936 | 0 | eval(completionCall, rcompgen_rho); |
937 | 0 | SEXP completions = PROTECT(eval(retrieveCall, rcompgen_rho)); |
938 | 0 | list_index = 0; |
939 | 0 | ncomp = length(completions); |
940 | 0 | if (ncomp > 0) { |
941 | 0 | compstrings = (char **) malloc(ncomp * sizeof(char*)); |
942 | 0 | if (!compstrings) { |
943 | 0 | UNPROTECT(4); |
944 | 0 | return (char *)NULL; |
945 | 0 | } |
946 | 0 | for (int i = 0; i < ncomp; i++) { |
947 | 0 | compstrings[i] = |
948 | 0 | strdup(translateChar(STRING_ELT(completions, i))); |
949 | 0 | if (!compstrings[i]) { |
950 | 0 | UNPROTECT(4); |
951 | 0 | for (int j = 0; j < i; j++) free(compstrings[j]); |
952 | 0 | free(compstrings); |
953 | 0 | return (char *)NULL; |
954 | 0 | } |
955 | 0 | } |
956 | 0 | } |
957 | 0 | UNPROTECT(4); |
958 | 0 | vmaxset(vmax); |
959 | 0 | } |
960 | | |
961 | 0 | if (list_index < ncomp) |
962 | 0 | return compstrings[list_index++]; |
963 | 0 | else { |
964 | | /* nothing matched or remaining, so return NULL. */ |
965 | 0 | if (ncomp > 0) free(compstrings); |
966 | 0 | } |
967 | 0 | return (char *)NULL; |
968 | 0 | } |
969 | | |
970 | | /* ============================================================ */ |
971 | | #else |
972 | | attribute_hidden |
973 | | void set_rl_word_breaks(const char *str) |
974 | | { |
975 | | } |
976 | | #endif /* HAVE_RL_COMPLETION_MATCHES */ |
977 | | |
978 | | #else |
979 | | static void |
980 | | handleInterrupt(void) |
981 | | { |
982 | | onintrNoResume(); |
983 | | } |
984 | | #endif /* HAVE_LIBREADLINE */ |
985 | | |
986 | | |
987 | | /* Fill a text buffer from stdin or with user typed console input. */ |
988 | | static void *cd = NULL; |
989 | | |
990 | | attribute_hidden int |
991 | | Rstd_ReadConsole(const char *prompt, unsigned char *buf, int len, |
992 | | int addtohistory) |
993 | 0 | { |
994 | 0 | if(!R_Interactive) { |
995 | 0 | size_t ll; |
996 | 0 | int err = 0; |
997 | 0 | if (!R_NoEcho) { |
998 | 0 | fputs(prompt, stdout); |
999 | 0 | fflush(stdout); /* make sure prompt is output */ |
1000 | 0 | } |
1001 | 0 | if (fgets((char *)buf, len, ifp ? ifp: stdin) == NULL) |
1002 | 0 | return 0; |
1003 | 0 | ll = strlen((char *)buf); |
1004 | | /* remove CR in CRLF ending */ |
1005 | 0 | if (ll >= 2 && buf[ll - 1] == '\n' && buf[ll - 2] == '\r') { |
1006 | 0 | buf[ll - 2] = '\n'; |
1007 | 0 | buf[--ll] = '\0'; |
1008 | 0 | } |
1009 | | /* translate if necessary */ |
1010 | 0 | if(strlen(R_StdinEnc) && strcmp(R_StdinEnc, "native.enc")) { |
1011 | 0 | size_t res, inb = strlen((char *)buf), onb = len; |
1012 | | /* NB: this is somewhat dangerous. R's main loop and |
1013 | | scan will not call it with a larger value, but |
1014 | | contributed code might. */ |
1015 | 0 | char obuf[CONSOLE_BUFFER_SIZE+1]; |
1016 | 0 | const char *ib = (const char *)buf; |
1017 | 0 | char *ob = obuf; |
1018 | 0 | if(!cd) { |
1019 | 0 | cd = Riconv_open("", R_StdinEnc); |
1020 | 0 | if(cd == (void *)-1) error(_("encoding '%s' is not recognised"), R_StdinEnc); |
1021 | 0 | } |
1022 | 0 | res = Riconv(cd, &ib, &inb, &ob, &onb); |
1023 | 0 | *ob = '\0'; |
1024 | 0 | err = res == (size_t)(-1); |
1025 | | /* errors lead to part of the input line being ignored */ |
1026 | 0 | if(err) { |
1027 | | /* Should re-set with a stateful encoding, but some iconv |
1028 | | implementations forget byte-order learned from BOM. |
1029 | | |
1030 | | Riconv(cd, NULL, NULL, &ob, &onb); |
1031 | | *ob = '\0'; |
1032 | | */ |
1033 | 0 | printf(_("<ERROR: re-encoding failure from encoding '%s'>\n"), |
1034 | 0 | R_StdinEnc); |
1035 | 0 | strncpy((char *)buf, obuf, len); |
1036 | 0 | strcat((char *)buf, "...\n"); |
1037 | 0 | } else |
1038 | 0 | strncpy((char *)buf, obuf, len); |
1039 | 0 | } |
1040 | | /* according to system.txt, should be terminated in \n, so check this |
1041 | | at eof and error */ |
1042 | 0 | if ((err || feof(ifp ? ifp : stdin)) |
1043 | 0 | && (ll == 0 || buf[ll - 1] != '\n') && ll < (size_t)len) { |
1044 | 0 | buf[ll++] = '\n'; buf[ll] = '\0'; |
1045 | 0 | } |
1046 | 0 | if (!R_NoEcho) { |
1047 | 0 | fputs((char *)buf, stdout); |
1048 | 0 | fflush(stdout); |
1049 | 0 | } |
1050 | 0 | return 1; |
1051 | 0 | } |
1052 | 0 | else { |
1053 | 0 | #ifdef HAVE_LIBREADLINE |
1054 | 0 | static unsigned char *rl_rest = NULL; |
1055 | 0 | static size_t rl_rest_offset = 0; |
1056 | |
|
1057 | 0 | if (rl_rest) { |
1058 | | /* remaining line data (too long line) from a previous call */ |
1059 | 0 | size_t r = strlen((char *)rl_rest + rl_rest_offset); |
1060 | 0 | if (r < len) { |
1061 | 0 | memcpy(buf, rl_rest + rl_rest_offset, r); |
1062 | 0 | buf[r] = '\0'; /* buf[r-1] is \n */ |
1063 | 0 | R_Free(rl_rest); |
1064 | 0 | rl_rest = NULL; |
1065 | 0 | rl_rest_offset = 0; |
1066 | 0 | } else { |
1067 | 0 | memcpy(buf, rl_rest + rl_rest_offset, len - 1); |
1068 | 0 | buf[len - 1] = '\0'; |
1069 | 0 | rl_rest_offset += len - 1; |
1070 | 0 | } |
1071 | 0 | return 1; |
1072 | 0 | } |
1073 | | |
1074 | 0 | R_ReadlineData rl_data; |
1075 | 0 | if (UsingReadline) { |
1076 | 0 | rl_data.readline_gotaline = 0; |
1077 | 0 | rl_data.readline_buf = buf; |
1078 | 0 | rl_data.readline_rest = NULL; |
1079 | 0 | rl_data.readline_addtohistory = addtohistory; |
1080 | 0 | rl_data.readline_len = len; |
1081 | 0 | rl_data.readline_eof = 0; |
1082 | 0 | rl_data.prev = rl_top; |
1083 | 0 | rl_top = &rl_data; |
1084 | | /* Allow conditional parsing of the ~/.inputrc file. */ |
1085 | 0 | rl_readline_name = "R"; |
1086 | 0 | pushReadline(prompt, readline_handler); |
1087 | 0 | #ifdef HAVE_RL_COMPLETION_MATCHES |
1088 | 0 | initialize_rlcompletion(); |
1089 | 0 | #endif |
1090 | 0 | } |
1091 | 0 | else |
1092 | 0 | #endif /* HAVE_LIBREADLINE */ |
1093 | 0 | { |
1094 | 0 | fputs(prompt, stdout); |
1095 | 0 | fflush(stdout); |
1096 | 0 | } |
1097 | |
|
1098 | 0 | if(R_InputHandlers == NULL) |
1099 | 0 | initStdinHandler(); |
1100 | |
|
1101 | 0 | for (;;) { |
1102 | 0 | fd_set *what; |
1103 | |
|
1104 | 0 | int wt = -1; |
1105 | 0 | if (R_wait_usec > 0) wt = R_wait_usec; |
1106 | 0 | if (Rg_wait_usec > 0 && (wt < 0 || wt > Rg_wait_usec)) |
1107 | 0 | wt = Rg_wait_usec; |
1108 | 0 | what = R_checkActivityEx(wt, 0, handleInterrupt); |
1109 | 0 | #ifdef NEED_INT_HANDLER |
1110 | 0 | if (UsingReadline && caught_sigwinch) { |
1111 | 0 | caught_sigwinch = FALSE; |
1112 | | // introduced in readline 4.0: only used for >= 6.3 |
1113 | 0 | #ifdef HAVE_RL_RESIZE_TERMINAL |
1114 | 0 | rl_resize_terminal(); |
1115 | 0 | static int oldwidth; |
1116 | 0 | int height, width; |
1117 | 0 | rl_get_screen_size(&height,&width); |
1118 | 0 | if (oldwidth >= 0 && oldwidth != width) { |
1119 | 0 | static SEXP opsym = NULL; |
1120 | 0 | if (! opsym) |
1121 | 0 | opsym = install("setWidthOnResize"); |
1122 | 0 | Rboolean setOK = asLogical(GetOption1(opsym)); |
1123 | 0 | oldwidth = width; |
1124 | 0 | if (setOK != NA_LOGICAL && setOK) |
1125 | 0 | R_SetOptionWidth(width); |
1126 | 0 | } |
1127 | 0 | #endif |
1128 | 0 | } |
1129 | 0 | #endif |
1130 | | |
1131 | | /* This is slightly clumsy. We have advertised the |
1132 | | * convention that R_wait_usec == 0 means "wait forever", |
1133 | | * but we also need to enable R_checkActivity to return |
1134 | | * immediately. */ |
1135 | |
|
1136 | 0 | R_runHandlers(R_InputHandlers, what); |
1137 | 0 | if (what == NULL) |
1138 | 0 | continue; |
1139 | 0 | if (FD_ISSET(fileno(stdin), what)) { |
1140 | | /* We could make this a regular handler, but we need |
1141 | | * to pass additional arguments. */ |
1142 | 0 | #ifdef HAVE_LIBREADLINE |
1143 | 0 | if (UsingReadline) { |
1144 | 0 | rl_callback_read_char(); |
1145 | 0 | if(rl_data.readline_eof || rl_data.readline_gotaline) { |
1146 | 0 | rl_top = rl_data.prev; |
1147 | 0 | if (rl_data.readline_rest) |
1148 | 0 | rl_rest = rl_data.readline_rest; |
1149 | 0 | return(rl_data.readline_eof ? 0 : 1); |
1150 | 0 | } |
1151 | 0 | } |
1152 | 0 | else |
1153 | 0 | #endif /* HAVE_LIBREADLINE */ |
1154 | 0 | { |
1155 | 0 | if(fgets((char *)buf, len, stdin) == NULL) |
1156 | 0 | return 0; |
1157 | 0 | else |
1158 | 0 | return 1; |
1159 | 0 | } |
1160 | 0 | } |
1161 | 0 | } |
1162 | 0 | } |
1163 | 0 | } |
1164 | | |
1165 | | /* Write a text buffer to the console. */ |
1166 | | /* All system output is filtered through this routine (unless R_Consolefile is used). */ |
1167 | | |
1168 | | attribute_hidden void Rstd_WriteConsole(const char *buf, int len) |
1169 | 0 | { |
1170 | 0 | printf("%s", buf); |
1171 | 0 | fflush(stdout); |
1172 | 0 | } |
1173 | | |
1174 | | /* The extended version allows the distinction of errors and warnings. |
1175 | | It is not enabled by default unless pretty-printing is desired. */ |
1176 | | attribute_hidden void Rstd_WriteConsoleEx(const char *buf, int len, int otype) |
1177 | 0 | { |
1178 | 0 | if (otype) |
1179 | 0 | printf("\033[1m%s\033[0m", buf); |
1180 | 0 | else |
1181 | 0 | printf("%s", buf); |
1182 | 0 | fflush(stdout); |
1183 | 0 | } |
1184 | | |
1185 | | |
1186 | | /* Indicate that input is coming from the console */ |
1187 | | |
1188 | | attribute_hidden void Rstd_ResetConsole(void) |
1189 | 17.5k | { |
1190 | 17.5k | } |
1191 | | |
1192 | | |
1193 | | /* Stdio support to ensure the console file buffer is flushed */ |
1194 | | |
1195 | | attribute_hidden void Rstd_FlushConsole(void) |
1196 | 17.5k | { |
1197 | | /* fflush(stdin); really work on Solaris on pipes */ |
1198 | 17.5k | } |
1199 | | |
1200 | | /* Reset stdin if the user types EOF on the console. */ |
1201 | | |
1202 | | attribute_hidden void Rstd_ClearerrConsole(void) |
1203 | 17.5k | { |
1204 | 17.5k | clearerr(stdin); |
1205 | 17.5k | } |
1206 | | |
1207 | | /* |
1208 | | * 3) ACTIONS DURING (LONG) COMPUTATIONS |
1209 | | */ |
1210 | | |
1211 | | attribute_hidden void Rstd_Busy(int which) |
1212 | 0 | { |
1213 | 0 | } |
1214 | | |
1215 | | /* |
1216 | | * 4) INITIALIZATION AND TERMINATION ACTIONS |
1217 | | */ |
1218 | | |
1219 | | /* |
1220 | | R_CleanUp is invoked at the end of the session to give the user the |
1221 | | option of saving their data. |
1222 | | If ask == SA_SAVEASK the user should be asked if possible (and this |
1223 | | option should not occur in non-interactive use). |
1224 | | If ask = SA_SAVE or SA_NOSAVE the decision is known. |
1225 | | If ask = SA_DEFAULT use the SaveAction set at startup. |
1226 | | In all these cases run .Last() unless quitting is cancelled. |
1227 | | If ask = SA_SUICIDE, no save, no .Last, possibly other things. |
1228 | | */ |
1229 | | |
1230 | | NORET attribute_hidden |
1231 | | void Rstd_CleanUp(SA_TYPE saveact, int status, int runLast) |
1232 | 0 | { |
1233 | 0 | if(saveact == SA_DEFAULT) /* The normal case apart from R_Suicide */ |
1234 | 0 | saveact = SaveAction; |
1235 | |
|
1236 | 0 | if(saveact == SA_SAVEASK) { |
1237 | 0 | if(R_Interactive) { |
1238 | 0 | unsigned char buf[1024]; |
1239 | 0 | qask: |
1240 | |
|
1241 | 0 | R_ClearerrConsole(); |
1242 | 0 | R_FlushConsole(); |
1243 | 0 | int res = R_ReadConsole("Save workspace image? [y/n/c]: ", |
1244 | 0 | buf, 128, 0); |
1245 | 0 | if(res) { |
1246 | 0 | switch (buf[0]) { |
1247 | 0 | case 'y': |
1248 | 0 | case 'Y': |
1249 | 0 | saveact = SA_SAVE; |
1250 | 0 | break; |
1251 | 0 | case 'n': |
1252 | 0 | case 'N': |
1253 | 0 | saveact = SA_NOSAVE; |
1254 | 0 | break; |
1255 | 0 | case 'c': |
1256 | 0 | case 'C': |
1257 | 0 | jump_to_toplevel(); |
1258 | 0 | break; |
1259 | 0 | default: |
1260 | 0 | goto qask; |
1261 | 0 | } |
1262 | 0 | } else saveact = SA_NOSAVE; /* probably EOF */ |
1263 | 0 | } else |
1264 | 0 | saveact = SaveAction; |
1265 | 0 | } |
1266 | 0 | switch (saveact) { |
1267 | 0 | case SA_SAVE: |
1268 | 0 | if(runLast) R_dot_Last(); |
1269 | 0 | if(R_DirtyImage) R_SaveGlobalEnv(); |
1270 | 0 | #if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H) |
1271 | 0 | if(R_Interactive && UsingReadline) { |
1272 | 0 | int err; |
1273 | 0 | R_setupHistory(); /* re-read the history size and filename */ |
1274 | 0 | stifle_history(R_HistorySize); |
1275 | 0 | err = write_history(R_HistoryFile); |
1276 | 0 | if(err) warning(_("problem in saving the history file '%s'"), |
1277 | 0 | R_HistoryFile); |
1278 | 0 | } |
1279 | 0 | #endif |
1280 | 0 | break; |
1281 | 0 | case SA_NOSAVE: |
1282 | 0 | if(runLast) R_dot_Last(); |
1283 | 0 | break; |
1284 | 0 | case SA_SUICIDE: |
1285 | 0 | default: |
1286 | 0 | break; |
1287 | 0 | } |
1288 | 0 | R_RunExitFinalizers(); |
1289 | 0 | CleanEd(); |
1290 | 0 | if(saveact != SA_SUICIDE) KillAllDevices(); |
1291 | 0 | R_CleanTempDir(); |
1292 | 0 | if(saveact != SA_SUICIDE && R_CollectWarnings) |
1293 | 0 | PrintWarnings(); /* from device close and (if run) .Last */ |
1294 | 0 | if(ifp) { |
1295 | 0 | fclose(ifp); /* input file from -f or --file= */ |
1296 | 0 | ifp = NULL; /* To avoid trying to close it again */ |
1297 | 0 | } |
1298 | 0 | fpu_setup(FALSE); |
1299 | |
|
1300 | 0 | exit(status); |
1301 | 0 | } |
1302 | | |
1303 | | /* |
1304 | | * 7) PLATFORM DEPENDENT FUNCTIONS |
1305 | | */ |
1306 | | |
1307 | | # include <errno.h> |
1308 | | |
1309 | | attribute_hidden int |
1310 | | Rstd_ShowFiles(int nfile, /* number of files */ |
1311 | | const char **file, /* array of filenames */ |
1312 | | const char **headers, /* the `headers' args of file.show. |
1313 | | Printed before each file. */ |
1314 | | const char *wtitle, /* title for window |
1315 | | = `title' arg of file.show */ |
1316 | | Rboolean del, /* should files be deleted after use? */ |
1317 | | const char *pager) /* pager to be used */ |
1318 | | |
1319 | 0 | { |
1320 | | /* |
1321 | | This function can be used to display the named files with the |
1322 | | given titles and overall title. On GUI platforms we could |
1323 | | use a read-only window to display the result. Here we just |
1324 | | make up a temporary file and invoke a pager on it. |
1325 | | */ |
1326 | |
|
1327 | 0 | int c, i, res; |
1328 | 0 | char *filename; |
1329 | 0 | FILE *fp, *tfp; |
1330 | 0 | char buf[1024]; |
1331 | |
|
1332 | 0 | if (nfile > 0) { |
1333 | 0 | if (pager == NULL || strlen(pager) == 0) pager = "more"; |
1334 | 0 | filename = R_tmpnam(NULL, R_TempDir); /* mallocs result */ |
1335 | 0 | if ((tfp = R_fopen(filename, "w")) != NULL) { |
1336 | 0 | for(i = 0; i < nfile; i++) { |
1337 | 0 | if (headers[i] && *headers[i]) |
1338 | 0 | fprintf(tfp, "%s\n\n", headers[i]); |
1339 | 0 | errno = 0; /* some systems require this */ |
1340 | | /* File expansion is now done in file.show(), but |
1341 | | left here in case other callers assumed it */ |
1342 | 0 | if ((fp = R_fopen(R_ExpandFileName(file[i]), "r")) |
1343 | 0 | != NULL) { |
1344 | 0 | while ((c = fgetc(fp)) != EOF) |
1345 | 0 | fputc(c, tfp); |
1346 | 0 | fprintf(tfp, "\n"); |
1347 | 0 | fclose(fp); |
1348 | 0 | if(del) |
1349 | 0 | unlink(R_ExpandFileName(file[i])); |
1350 | 0 | } |
1351 | 0 | else |
1352 | 0 | fprintf(tfp, _("Cannot open file '%s': %s\n\n"), |
1353 | 0 | file[i], strerror(errno)); |
1354 | 0 | } |
1355 | 0 | fclose(tfp); |
1356 | 0 | } |
1357 | 0 | snprintf(buf, 1024, "'%s' < '%s'", pager, filename); //might contain spaces |
1358 | 0 | res = R_system(buf); |
1359 | 0 | if (res == 127) |
1360 | 0 | warningcall(R_NilValue, _("error in running command")); |
1361 | 0 | unlink(filename); |
1362 | 0 | free(filename); |
1363 | 0 | return (res != 0); |
1364 | 0 | } |
1365 | 0 | return 1; |
1366 | 0 | } |
1367 | | |
1368 | | |
1369 | | /* |
1370 | | Prompt the user for a file name. Return the length of |
1371 | | the name typed. On Gui platforms, this should bring up |
1372 | | a dialog box so a user can choose files that way. |
1373 | | */ |
1374 | | |
1375 | | |
1376 | | #include <ctype.h> /* for isspace */ |
1377 | | |
1378 | | attribute_hidden int Rstd_ChooseFile(int _new, char *buf, int len) |
1379 | 0 | { |
1380 | 0 | if (!R_ReadConsole("Enter file name: ", (unsigned char *)buf, len, 0)) |
1381 | 0 | return 0; |
1382 | 0 | size_t namelen = strlen(buf); |
1383 | 0 | if (namelen == 0) |
1384 | 0 | return 0; |
1385 | 0 | char *bufp = &buf[namelen - 1]; |
1386 | 0 | while (bufp >= buf && isspace((int)*bufp)) |
1387 | 0 | *bufp-- = '\0'; |
1388 | 0 | return (int) strlen(buf); |
1389 | 0 | } |
1390 | | |
1391 | | |
1392 | | attribute_hidden void Rstd_ShowMessage(const char *s) |
1393 | 0 | { |
1394 | 0 | REprintf("%s\n", s); |
1395 | 0 | } |
1396 | | |
1397 | | |
1398 | | attribute_hidden void Rstd_read_history(const char *s) |
1399 | 0 | { |
1400 | 0 | #if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H) |
1401 | 0 | if(R_Interactive && UsingReadline) { |
1402 | 0 | read_history(s); |
1403 | 0 | } |
1404 | 0 | #endif |
1405 | 0 | } |
1406 | | |
1407 | | attribute_hidden void Rstd_loadhistory(SEXP call, SEXP op, SEXP args, SEXP env) |
1408 | 0 | { |
1409 | 0 | SEXP sfile; |
1410 | 0 | char file[R_PATH_MAX]; |
1411 | 0 | const char *p; |
1412 | |
|
1413 | 0 | sfile = CAR(args); |
1414 | 0 | if (!isString(sfile) || LENGTH(sfile) < 1) |
1415 | 0 | errorcall(call, _("invalid '%s' argument"), "file"); |
1416 | 0 | p = R_ExpandFileName(translateCharFP(STRING_ELT(sfile, 0))); |
1417 | 0 | if(strlen(p) > R_PATH_MAX - 1) |
1418 | 0 | errorcall(call, _("'file' argument is too long")); |
1419 | 0 | strcpy(file, p); |
1420 | 0 | #if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H) |
1421 | 0 | if(R_Interactive && UsingReadline) { |
1422 | 0 | clear_history(); |
1423 | 0 | read_history(file); |
1424 | 0 | } else errorcall(call, _("no history mechanism available")); |
1425 | | #else |
1426 | | errorcall(call, _("no history mechanism available")); |
1427 | | #endif |
1428 | 0 | } |
1429 | | |
1430 | | attribute_hidden void Rstd_savehistory(SEXP call, SEXP op, SEXP args, SEXP env) |
1431 | 0 | { |
1432 | 0 | SEXP sfile; |
1433 | 0 | char file[R_PATH_MAX]; |
1434 | 0 | const char *p; |
1435 | |
|
1436 | 0 | sfile = CAR(args); |
1437 | 0 | if (!isString(sfile) || LENGTH(sfile) < 1) |
1438 | 0 | errorcall(call, _("invalid '%s' argument"), "file"); |
1439 | 0 | p = R_ExpandFileName(translateCharFP(STRING_ELT(sfile, 0))); |
1440 | 0 | if(strlen(p) > R_PATH_MAX - 1) |
1441 | 0 | errorcall(call, _("'file' argument is too long")); |
1442 | 0 | strcpy(file, p); |
1443 | 0 | #if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H) |
1444 | 0 | if(R_Interactive && UsingReadline) { |
1445 | 0 | int err; |
1446 | 0 | err = write_history(file); |
1447 | 0 | if(err) error(_("problem in saving the history file '%s'"), file); |
1448 | | /* Note that q() uses stifle_history, but here we do not want |
1449 | | * to truncate the active history when saving during a session */ |
1450 | 0 | #ifdef HAVE_HISTORY_TRUNCATE_FILE |
1451 | 0 | R_setupHistory(); /* re-read the history size */ |
1452 | 0 | err = history_truncate_file(file, R_HistorySize); |
1453 | 0 | if(err) warning(_("problem in truncating the history file")); |
1454 | 0 | #endif |
1455 | 0 | } else errorcall(call, _("no history available to save")); |
1456 | | #else |
1457 | | errorcall(call, _("no history available to save")); |
1458 | | #endif |
1459 | 0 | } |
1460 | | |
1461 | | attribute_hidden void Rstd_addhistory(SEXP call, SEXP op, SEXP args, SEXP env) |
1462 | 0 | { |
1463 | 0 | SEXP stamp; |
1464 | 0 | int i; |
1465 | |
|
1466 | 0 | checkArity(op, args); |
1467 | 0 | stamp = CAR(args); |
1468 | 0 | if (!isString(stamp)) |
1469 | 0 | errorcall(call, _("invalid timestamp")); |
1470 | 0 | #if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H) |
1471 | 0 | if(R_Interactive && UsingReadline) |
1472 | 0 | for (i = 0; i < LENGTH(stamp); i++) |
1473 | 0 | add_history(CHAR(STRING_ELT(stamp, i))); /* ASCII */ |
1474 | 0 | # endif |
1475 | 0 | } |
1476 | | |
1477 | | |
1478 | 0 | #define R_MIN(a, b) ((a) < (b) ? (a) : (b)) |
1479 | | |
1480 | | void Rsleep(double timeint) |
1481 | 0 | { |
1482 | 0 | double tm = timeint * 1e6, start = currentTime(), elapsed; |
1483 | 0 | for (;;) { |
1484 | 0 | fd_set *what; |
1485 | 0 | tm = R_MIN(tm, 2e9); /* avoid integer overflow */ |
1486 | |
|
1487 | 0 | int wt = -1; |
1488 | 0 | if (R_wait_usec > 0) wt = R_wait_usec; |
1489 | 0 | if (Rg_wait_usec > 0 && (wt < 0 || wt > Rg_wait_usec)) |
1490 | 0 | wt = Rg_wait_usec; |
1491 | 0 | int Timeout = (int) (wt > 0 ? R_MIN(tm, wt) : tm); |
1492 | 0 | what = R_checkActivity(Timeout, 1); |
1493 | | /* For polling, elapsed time limit ... */ |
1494 | 0 | R_CheckUserInterrupt(); |
1495 | | /* Time up? */ |
1496 | 0 | elapsed = currentTime() - start; |
1497 | 0 | if(elapsed >= timeint) break; |
1498 | | |
1499 | | /* Nope, service pending events */ |
1500 | 0 | R_runHandlers(R_InputHandlers, what); |
1501 | | |
1502 | | /* Servicing events might take some time, so recheck: */ |
1503 | 0 | elapsed = currentTime() - start; |
1504 | 0 | if(elapsed >= timeint) break; |
1505 | | |
1506 | 0 | tm = 1e6*(timeint - elapsed); |
1507 | 0 | } |
1508 | 0 | } |