Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /*******************************************************************/
16 : /** **/
17 : /** PARI CALCULATOR **/
18 : /** **/
19 : /*******************************************************************/
20 : #ifdef _WIN32
21 : # include "../systems/mingw/pwinver.h"
22 : # include <windows.h>
23 : # include "../systems/mingw/mingw.h"
24 : #endif
25 : #include "pari.h"
26 : #include "paripriv.h"
27 : #include "gp.h"
28 :
29 : static jmp_buf *env;
30 : static pari_stack s_env;
31 : void (*cb_gp_output)(GEN z) = NULL;
32 : void (*cb_pari_end_output)(void) = NULL;
33 :
34 : static void
35 0 : gp_ask_confirm(const char *s)
36 : {
37 0 : err_printf(s);
38 0 : err_printf(". OK ? (^C if not)\n");
39 0 : pari_hit_return();
40 0 : }
41 :
42 : /* numerr < 0: after changing PARI stack size
43 : * numerr > 0: normal error, including SIGINT */
44 : static void
45 11492 : gp_err_recover(long numerr)
46 : {
47 11492 : longjmp(env[s_env.n-1], numerr);
48 : }
49 :
50 : /* numerr >= 0 */
51 : static void
52 10984 : gp_pre_recover(long numerr)
53 : {
54 10984 : out_puts(pariErr, "\n"); pariErr->flush();
55 10984 : gp_err_recover(numerr);
56 0 : }
57 :
58 : static void
59 123530 : reset_ctrlc(void)
60 : {
61 : #if defined(_WIN32) || defined(__CYGWIN32__)
62 : win32ctrlc = 0;
63 : #endif
64 123530 : }
65 :
66 : static int
67 78525 : is_silent(char *s) { return s[strlen(s) - 1] == ';'; }
68 :
69 : static int stdin_isatty = 0;
70 : static int
71 1905 : is_interactive(void)
72 1905 : { return pari_infile == stdin && stdin_isatty; }
73 :
74 : /*******************************************************************/
75 : /** **/
76 : /** INITIALIZATION **/
77 : /** **/
78 : /*******************************************************************/
79 : static void
80 2 : print_shortversion(void)
81 : {
82 2 : const ulong mask = (1UL<<PARI_VERSION_SHIFT) - 1;
83 2 : ulong n = paricfg_version_code, major, minor, patch;
84 :
85 2 : patch = n & mask; n >>= PARI_VERSION_SHIFT;
86 2 : minor = n & mask; n >>= PARI_VERSION_SHIFT;
87 2 : major = n;
88 2 : printf("%lu.%lu.%lu\n", major,minor,patch); exit(0);
89 : }
90 :
91 : static void
92 2 : usage(char *s)
93 : {
94 2 : printf("### Usage: %s [options] [GP files]\n", s);
95 2 : printf("Available options:\n");
96 2 : printf(" [-f,--fast]\t\tFast start: do not read .gprc\n");
97 2 : printf(" [-q,--quiet]\t\tQuiet mode: do not print banner and history numbers\n");
98 2 : printf(" [-s stacksize]\tStart with the PARI stack of given size (in bytes)\n");
99 2 : printf(" [--default key=val]\tExecute default(key,val) on startup\n");
100 2 : printf(" [--emacs]\t\tRun as if in Emacs shell\n");
101 2 : printf(" [--help]\t\tPrint this message\n");
102 2 : printf(" [--test]\t\tTest mode. No history, wrap long lines (bench only)\n");
103 2 : printf(" [--texmacs]\t\tRun as if using TeXmacs frontend\n");
104 2 : printf(" [--version]\t\tOutput version info and exit\n");
105 2 : printf(" [--version-short]\tOutput version number and exit\n\n");
106 2 : exit(0);
107 : }
108 :
109 : static void
110 2 : gp_head(void)
111 : {
112 2 : pari_print_version();
113 2 : pari_putc('\n');
114 2 : pari_center("Copyright (C) 2000-2022 The PARI Group");
115 2 : pari_putc('\n');
116 2 : print_text("PARI/GP is free software, covered by the GNU General Public \
117 : License, and comes WITHOUT ANY WARRANTY WHATSOEVER.");
118 2 : pari_puts("\nType ? for help, \\q to quit.\n");
119 2 : pari_printf("Type ?%d for how to get moral"
120 : " (and possibly technical) support.\n", pari_community());
121 2 : if (pari_mainstack->vsize)
122 0 : pari_printf("\nparisizemax = %lu, primelimit = %lu",
123 0 : pari_mainstack->vsize,GP_DATA->primelimit);
124 : else
125 4 : pari_printf("\nparisize = %lu, primelimit = %lu",
126 2 : pari_mainstack->rsize,GP_DATA->primelimit);
127 2 : if (pari_mt_nbthreads > 1)
128 0 : pari_printf(", nbthreads = %lu", pari_mt_nbthreads);
129 2 : pari_putc('\n');
130 2 : }
131 :
132 : static char *
133 0 : read_arg(long *nread, char *t, long argc, char **argv)
134 : {
135 0 : long i = *nread;
136 0 : if (isdigit((int)*t)) return t;
137 0 : if (*t || i==argc) usage(argv[0]);
138 0 : *nread = i+1; return argv[i];
139 : }
140 :
141 : static char *
142 0 : read_arg_equal(long *nread, char *t, long argc, char **argv)
143 : {
144 0 : long i = *nread;
145 0 : if (*t=='=' && isdigit((int)t[1])) return t+1;
146 0 : if (*t || i==argc) usage(argv[0]);
147 0 : *nread = i+1; return argv[i];
148 : }
149 :
150 : static void
151 4 : init_trivial_stack(void)
152 : {
153 4 : const size_t s = 2048;
154 4 : pari_mainstack->size = s;
155 4 : pari_mainstack->bot = (pari_sp)pari_malloc(s);
156 4 : avma = pari_mainstack->top = pari_mainstack->bot + s;
157 4 : }
158 :
159 : static void
160 4 : free_trivial_stack(void)
161 : {
162 4 : free((void*)pari_mainstack->bot);
163 4 : }
164 :
165 : typedef struct { char *key, *val; } pair_t;
166 : /* If ab of the form key=val, record pair in new stack entry
167 : * P[n].key must be freed by caller to avoid memory leak */
168 : static void
169 6 : record_default(pari_stack *s_P, char *ab)
170 : {
171 6 : pair_t *P = (pair_t*)*pari_stack_base(s_P);
172 : char *k, *v;
173 : long n;
174 6 : ab = pari_strdup(ab);
175 6 : parse_key_val(ab, &k, &v);
176 6 : n = pari_stack_new(s_P);
177 6 : P[n].key = k;
178 6 : P[n].val = v;
179 6 : }
180 : static void
181 1802 : read_opt(pari_stack *p_A, long argc, char **argv)
182 : {
183 : pair_t *P;
184 : pari_stack s_P; /* key / value to record default() settings */
185 1802 : char *b = NULL, *p = NULL, *s = NULL;
186 1802 : ulong f = GP_DATA->flags;
187 1802 : long i = 1, initrc = 1;
188 :
189 : (void)&p; (void)&b; (void)&s; /* -Wall gcc-2.95 */
190 :
191 1802 : pari_stack_init(&s_P,sizeof(*P),(void**)&P);
192 1802 : pari_stack_alloc(&s_P, 64);
193 1802 : pari_outfile = stderr;
194 5388 : while (i < argc)
195 : {
196 3594 : char *t = argv[i];
197 :
198 3594 : if (*t++ != '-') break;
199 3594 : i++;
200 3594 : START:
201 3594 : switch(*t++)
202 : {
203 0 : case 'p': p = read_arg(&i,t,argc,argv); break;
204 0 : case 's': s = read_arg(&i,t,argc,argv); break;
205 0 : case 'e':
206 0 : f |= gpd_EMACS; if (*t) goto START;
207 0 : break;
208 1788 : case 'q':
209 1788 : f |= gpd_QUIET; if (*t) goto START;
210 1788 : break;
211 0 : case 't':
212 0 : f |= gpd_TEST; if (*t) goto START;
213 0 : break;
214 33 : case 'f':
215 33 : initrc = 0; if (*t) goto START;
216 33 : break;
217 4 : case 'D':
218 4 : if (*t || i == argc) usage(argv[0]);
219 4 : record_default(&s_P, argv[i++]);
220 4 : break;
221 1769 : case '-':
222 1769 : if (strcmp(t, "version-short") == 0) { print_shortversion(); exit(0); }
223 1767 : if (strcmp(t, "version") == 0) {
224 4 : init_trivial_stack(); pari_print_version();
225 4 : free_trivial_stack(); exit(0);
226 : }
227 1763 : if (strcmp(t, "default") == 0) {
228 2 : if (i == argc) usage(argv[0]);
229 2 : record_default(&s_P, argv[i++]);
230 2 : break;
231 : }
232 1761 : if (strcmp(t, "texmacs") == 0) { f |= gpd_TEXMACS; break; }
233 1761 : if (strcmp(t, "emacs") == 0) { f |= gpd_EMACS; break; }
234 1761 : if (strcmp(t, "test") == 0) { f |= gpd_TEST; initrc = 0; break; }
235 6 : if (strcmp(t, "quiet") == 0) { f |= gpd_QUIET; break; }
236 4 : if (strcmp(t, "fast") == 0) { initrc = 0; break; }
237 2 : if (strncmp(t, "primelimit",10) == 0) {p = read_arg_equal(&i,t+10,argc,argv); break; }
238 2 : if (strncmp(t, "stacksize",9) == 0) {s = read_arg_equal(&i,t+9,argc,argv); break; }
239 : /* fall through */
240 : default:
241 2 : usage(argv[0]);
242 : }
243 : }
244 1794 : if (f & gpd_TEST) stdin_isatty = 0;
245 1794 : GP_DATA->flags = f;
246 : #ifdef READLINE
247 1794 : GP_DATA->use_readline = stdin_isatty;
248 : #endif
249 1794 : if (!is_interactive()) GP_DATA->breakloop = 0;
250 1794 : if (initrc) gp_initrc(p_A);
251 1794 : for ( ; i < argc; i++) pari_stack_pushp(p_A, pari_strdup(argv[i]));
252 :
253 : /* override the values from gprc */
254 1794 : if (p) (void)sd_primelimit(p, d_INITRC);
255 1794 : if (s) (void)sd_parisize(s, d_INITRC);
256 1798 : for (i = 0; i < s_P.n; i++) {
257 6 : setdefault(P[i].key, P[i].val, d_INITRC);
258 4 : free((void*)P[i].key);
259 : }
260 1792 : pari_stack_delete(&s_P);
261 1792 : pari_outfile = stdout;
262 1792 : }
263 :
264 : /*******************************************************************/
265 : /** **/
266 : /** TEST MODE **/
267 : /** **/
268 : /*******************************************************************/
269 : static int
270 230003 : test_is_interactive(void) { return 0; }
271 :
272 : static void
273 52869 : test_output(GEN z) { init_linewrap(76); gen_output(z); }
274 : void
275 1755 : init_test(void)
276 : {
277 1755 : disable_color = 1;
278 1755 : init_linewrap(76);
279 1755 : pari_errfile = stdout;
280 1755 : cb_gp_output = test_output;
281 1755 : cb_pari_is_interactive = test_is_interactive;
282 1755 : }
283 :
284 : /*******************************************************************/
285 : /** **/
286 : /** FORMAT GP OUTPUT **/
287 : /** **/
288 : /*******************************************************************/
289 : /* REGULAR */
290 : static void
291 4 : normal_output(GEN z, long n)
292 : {
293 4 : long l = 0;
294 : char *s;
295 : /* history number */
296 4 : if (n)
297 : {
298 : char buf[64];
299 4 : if (!(GP_DATA->flags & gpd_QUIET))
300 : {
301 2 : term_color(c_HIST);
302 2 : sprintf(buf, "%%%ld = ", n);
303 2 : pari_puts(buf);
304 2 : l = strlen(buf);
305 : }
306 : }
307 : /* output */
308 4 : term_color(c_OUTPUT);
309 4 : s = GENtostr(z);
310 4 : if (GP_DATA->lim_lines)
311 2 : lim_lines_output(s, l, GP_DATA->lim_lines);
312 : else
313 2 : pari_puts(s);
314 4 : pari_free(s);
315 4 : term_color(c_NONE); pari_putc('\n');
316 4 : }
317 :
318 : static void
319 52873 : gp_output(GEN z)
320 : {
321 52873 : if (cb_gp_output) { cb_gp_output(z); return; }
322 4 : if (GP_DATA->fmt->prettyp == f_PRETTY)
323 0 : { if (tex2mail_output(z, GP_DATA->hist->total)) return; }
324 4 : normal_output(z, GP_DATA->hist->total);
325 4 : pari_flush();
326 : }
327 :
328 : static GEN
329 1792 : gp_main_loop(long ismain)
330 : {
331 1792 : VOLATILE GEN z = gnil;
332 1792 : VOLATILE long t = 0, r = 0;
333 1792 : VOLATILE pari_sp av = avma;
334 : filtre_t F;
335 1792 : Buffer *b = filtered_buffer(&F);
336 : struct gp_context rec;
337 : long er;
338 1792 : if ((er = setjmp(env[s_env.n-1])))
339 : { /* recover: jump from error [ > 0 ] or allocatemem [ -1 ] */
340 11462 : if (er > 0) { /* true error */
341 10975 : if (!(GP_DATA->recover)) exit(1);
342 10975 : gp_context_restore(&rec);
343 : /* true error not from main instance, let caller sort it out */
344 10975 : if (!ismain) { kill_buffers_upto_including(b); return NULL; }
345 : } else { /* allocatemem */
346 487 : tmp_restore(rec.file.file);
347 487 : gp_context_save(&rec);
348 : }
349 11462 : set_avma(av = pari_mainstack->top);
350 11462 : parivstack_reset();
351 11462 : kill_buffers_upto(b);
352 11462 : pari_alarm(0);
353 : }
354 : for(;;)
355 : {
356 125147 : gp_context_save(&rec);
357 125147 : if (! gp_read_line(&F, NULL))
358 : {
359 1792 : if (popinfile()) gp_quit(0);
360 0 : if (ismain) continue;
361 0 : pop_buffer(); return z;
362 : }
363 123355 : if (ismain)
364 : {
365 123355 : reset_ctrlc();
366 123355 : timer_start(GP_DATA->T);
367 123355 : walltimer_start(GP_DATA->Tw);
368 123355 : pari_set_last_newline(1);
369 : }
370 123355 : if (gp_meta(b->buf,ismain)) continue;
371 103985 : z = pari_compile_str(b->buf);
372 103908 : z = closure_evalres(z);
373 92544 : if (!ismain) continue;
374 :
375 92544 : t = timer_delay(GP_DATA->T);
376 92544 : r = walltimer_delay(GP_DATA->Tw);
377 92544 : if (!pari_last_was_newline()) pari_putc('\n');
378 92544 : pari_alarm(0);
379 92544 : if (t && GP_DATA->chrono)
380 : {
381 0 : if (pari_mt_nbthreads==1)
382 : {
383 0 : pari_puts("time = ");
384 0 : pari_puts(gp_format_time(t));
385 : }
386 : else
387 : {
388 0 : pari_puts("cpu time = ");
389 0 : pari_puts(gp_format_time(t));
390 0 : pari_puts(", real time = ");
391 0 : pari_puts(gp_format_time(r));
392 : }
393 0 : pari_puts(".\n");
394 : }
395 92544 : if (GP_DATA->simplify) z = simplify_shallow(z);
396 92544 : pari_add_hist(z, t, r);
397 92544 : if (z != gnil && ! is_silent(b->buf) ) gp_output(z);
398 92544 : set_avma(av);
399 92544 : parivstack_reset();
400 : }
401 : }
402 :
403 : /* as gp_read_file, before running the main gp instance */
404 : static void
405 0 : read_main(const char *s)
406 : {
407 : GEN z;
408 0 : if (setjmp(env[s_env.n-1]))
409 0 : z = NULL;
410 : else {
411 0 : FILE *f = switchin(s);
412 0 : if (file_is_binary(f)) {
413 0 : z = readbin(s,f, NULL);
414 0 : popinfile();
415 : }
416 0 : else z = gp_main_loop(0);
417 : }
418 0 : if (!z) err_printf("... skipping file '%s'\n", s);
419 0 : set_avma(pari_mainstack->top);
420 0 : }
421 :
422 : static const char *
423 63 : break_loop_prompt(long n)
424 : {
425 63 : const char *s = (n==1)? "break> ": stack_sprintf("break[%ld]> ", n);
426 63 : return gp_format_prompt(s);
427 : }
428 :
429 : static long frame_level=0, dbg_level = 0;
430 :
431 : static int
432 63 : break_loop(int numerr)
433 : {
434 : filtre_t F;
435 : Buffer *b;
436 63 : int sigint = numerr<0, go_on = sigint;
437 : struct gp_context rec1, rec2;
438 : const char *prompt, *msg;
439 63 : long nenv, oldframe_level = frame_level;
440 : pari_sp av;
441 :
442 63 : if (numerr == e_SYNTAX) return 0;
443 63 : if (numerr == e_STACK) { evalstate_clone(); set_avma(pari_mainstack->top); }
444 63 : gp_context_save(&rec1);
445 :
446 63 : b = filtered_buffer(&F);
447 63 : nenv=pari_stack_new(&s_env);
448 63 : prompt = break_loop_prompt(s_env.n-1);
449 63 : iferr_env = NULL;
450 63 : dbg_level = 0;
451 63 : frame_level = closure_context(oldframe_level, dbg_level);
452 63 : pari_infile = newfile(stdin, "stdin", mf_IN)->file;
453 63 : term_color(c_ERR); pari_putc('\n');
454 63 : if (sigint)
455 7 : msg = "Break loop: <Return> to continue; 'break' to go back to GP prompt";
456 : else
457 56 : msg = "Break loop: type 'break' to go back to GP prompt";
458 63 : print_errcontext(pariOut, msg, NULL, NULL);
459 63 : term_color(c_NONE);
460 63 : av = avma;
461 : for(;;)
462 91 : {
463 : GEN x;
464 : long er, br_status;
465 154 : set_avma(av);
466 154 : gp_context_save(&rec2);
467 154 : if ((er=setjmp(env[nenv])))
468 : {
469 35 : if (er < 0)
470 : {
471 7 : s_env.n = 1;
472 7 : frame_level = oldframe_level;
473 7 : longjmp(env[s_env.n-1], er);
474 : }
475 28 : gp_context_restore(&rec2);
476 28 : iferr_env = NULL;
477 28 : closure_err(dbg_level);
478 28 : compilestate_restore(&rec1.eval.comp);
479 28 : (void) closure_context(oldframe_level, dbg_level);
480 28 : pari_infile = newfile(stdin, "stdin", mf_IN)->file;
481 : }
482 182 : term_color(c_NONE);
483 182 : if (!gp_read_line(&F, prompt))
484 0 : br_status = br_BREAK; /* EOF */
485 : else
486 : {
487 : /* Empty input ? Continue if entry on sigint (exit debugger frame) */
488 182 : if (! *(b->buf) && sigint) break;
489 175 : reset_ctrlc();
490 175 : if (gp_meta(b->buf,0)) continue;
491 175 : x = pari_compile_str(b->buf);
492 175 : x = closure_evalbrk(x, &br_status);
493 : }
494 140 : switch (br_status)
495 : {
496 0 : case br_NEXT: case br_MULTINEXT:
497 0 : popinfile(); /* exit frame. Don't exit debugger if s_env.n > 2 */
498 49 : go_on = 0; goto BR_EXIT;
499 49 : case br_BREAK: case br_RETURN:
500 49 : killallfiles(); /* completely exit the debugger */
501 49 : go_on = 0; goto BR_EXIT;
502 : }
503 91 : if (x!=gnil && !is_silent(b->buf)) { term_color(c_OUTPUT); gen_output(x); }
504 : }
505 56 : BR_EXIT:
506 56 : s_env.n=nenv;
507 56 : frame_level = oldframe_level;
508 56 : gp_context_restore(&rec1);
509 56 : pop_buffer(); return go_on;
510 : }
511 :
512 : #ifdef __CYGWIN32__
513 : void
514 : cyg_environment(int argc, char ** argv)
515 : {
516 : char *ti_dirs = getenv("TERMINFO_DIRS");
517 : char *argv0, *p;
518 : char *newdir;
519 : long n;
520 :
521 : if (!argc || !argv) return;
522 : argv0 = *argv;
523 : if (!argv0 || !*argv0) return;
524 : p = strrchr(argv0, '/');
525 : if (!p)
526 : p = argv0 = "";
527 : else
528 : p++;
529 : n = p - argv0;
530 : if (ti_dirs)
531 : {
532 : n += 14 + strlen(ti_dirs) + 1 + 8 + 1;
533 : newdir = malloc(n);
534 : if (!newdir) return;
535 : snprintf(newdir, n-8, "TERMINFO_DIRS=%s:%s", ti_dirs, argv0);
536 : }
537 : else
538 : {
539 : n += 14 + 8 + 1;
540 : newdir = malloc(n);
541 : if (!newdir) return;
542 : snprintf(newdir, n-8, "TERMINFO_DIRS=%s", argv0);
543 : }
544 : strcpy(newdir+n-9,"terminfo");
545 : putenv(newdir);
546 : }
547 : #endif
548 :
549 : int
550 1802 : main(int argc, char **argv)
551 : {
552 : char **A;
553 : pari_stack s_A;
554 :
555 1802 : GP_DATA = default_gp_data();
556 1802 : pari_stack_init(&s_env, sizeof(*env), (void**)&env);
557 1802 : (void)pari_stack_new(&s_env);
558 :
559 1802 : if (setjmp(env[s_env.n-1]))
560 : {
561 2 : puts("### Errors on startup, exiting...\n\n");
562 2 : exit(1);
563 : }
564 : #ifdef __CYGWIN32__
565 : cyg_environment(argc, argv);
566 : #endif
567 1802 : stdin_isatty = pari_stdin_isatty();
568 1802 : pari_init_defaults();
569 1802 : pari_library_path = DL_DFLT_NAME;
570 1802 : pari_stack_init(&s_A,sizeof(*A),(void**)&A);
571 : /* must be defined here in case an error is raised in pari_init_opts, e.g.
572 : * when parsing function prototypes */
573 1802 : cb_pari_err_recover = gp_err_recover;
574 1802 : pari_init_opts(1000000 * sizeof(long), 0, INIT_SIGm | INIT_noPRIMEm | INIT_noIMTm);
575 1802 : cb_pari_pre_recover = gp_pre_recover;
576 1802 : cb_pari_break_loop = break_loop;
577 1802 : cb_pari_is_interactive = is_interactive;
578 :
579 1802 : read_opt(&s_A, argc,argv);
580 1792 : pari_init_primes(GP_DATA->primelimit);
581 : #ifdef SIGALRM
582 1792 : (void)os_signal(SIGALRM,gp_alarm_handler);
583 : #endif
584 1792 : pari_add_module(functions_gp);
585 :
586 1792 : pari_set_plot_engine(gp_get_plot);
587 1792 : cb_pari_quit = gp_quit;
588 1792 : cb_pari_whatnow = whatnow;
589 1792 : cb_pari_sigint = gp_sigint_fun;
590 1792 : cb_pari_handle_exception = gp_handle_exception;
591 1792 : cb_pari_ask_confirm = gp_ask_confirm;
592 1792 : pari_init_paths();
593 1792 : pari_mt_init(); /* MPI: will not return on slaves (pari_MPI_rank = 0) */
594 : #ifdef _WIN32
595 : if (stdin_isatty) win32_set_codepage();
596 : #endif
597 : #ifdef READLINE
598 1792 : init_readline();
599 : #endif
600 1792 : if (GP_DATA->flags & gpd_EMACS) init_emacs();
601 1792 : if (GP_DATA->flags & gpd_TEXMACS) init_texmacs();
602 :
603 1792 : timer_start(GP_DATA->T);
604 1792 : walltimer_start(GP_DATA->Tw);
605 1792 : if (!(GP_DATA->flags & gpd_QUIET)) gp_head();
606 1792 : if (GP_DATA->flags & gpd_TEST) init_test();
607 1792 : if (s_A.n)
608 : {
609 0 : FILE *l = pari_logfile;
610 : long i;
611 0 : pari_logfile = NULL;
612 0 : for (i = 0; i < s_A.n; pari_free(A[i]),i++) read_main(A[i]);
613 : /* Reading one of the input files above can set pari_logfile.
614 : * Don't restore in that case. */
615 0 : if (!pari_logfile) pari_logfile = l;
616 : }
617 1792 : pari_stack_delete(&s_A);
618 1792 : (void)gp_main_loop(1);
619 0 : gp_quit(0);
620 : return 0; /* LCOV_EXCL_LINE */
621 : }
622 :
623 : void
624 7 : pari_breakpoint(void)
625 : {
626 7 : if (!pari_last_was_newline()) pari_putc('\n');
627 7 : closure_err(0);
628 7 : if (cb_pari_break_loop && cb_pari_break_loop(-1)) return;
629 0 : cb_pari_err_recover(e_MISC);
630 : }
631 :
632 : void
633 7 : dbg_down(long k)
634 : {
635 7 : if (k<0) k=0;
636 7 : dbg_level -= k;
637 7 : if (dbg_level<0) dbg_level=0;
638 7 : gp_err_recover(e_NONE);
639 0 : }
640 :
641 : GEN
642 7 : dbg_err(void) { GEN E = pari_err_last(); return E? gcopy(E):gnil; }
643 :
644 : void
645 14 : dbg_up(long k)
646 : {
647 14 : if (k<0) k=0;
648 14 : dbg_level += k;
649 14 : if (dbg_level>frame_level) dbg_level=frame_level;
650 14 : gp_err_recover(e_NONE);
651 0 : }
652 :
653 : void
654 1792 : gp_quit(long code)
655 : {
656 1792 : pari_kill_plot_engine();
657 1792 : pari_close();
658 1792 : kill_buffers_upto(NULL);
659 1792 : if (!(GP_DATA->flags & gpd_QUIET)) pari_puts("Goodbye!\n");
660 1792 : if (cb_pari_end_output) cb_pari_end_output();
661 1792 : exit(code);
662 : }
663 :
664 : void
665 35 : whatnow0(char *s) { whatnow(pariOut, s,0); }
666 :
667 : #include "gp_init.h"
|