Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2000 The PARI group.12This file is part of the PARI/GP package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1314/*******************************************************************/15/** **/16/** PARI CALCULATOR **/17/** **/18/*******************************************************************/19#ifdef _WIN3220# include "../systems/mingw/pwinver.h"21# include <windows.h>22# include "../systems/mingw/mingw.h"23#endif24#include "pari.h"25#include "paripriv.h"26#include "gp.h"2728static jmp_buf *env;29static pari_stack s_env;30void (*cb_gp_output)(GEN z) = NULL;31void (*cb_pari_end_output)(void) = NULL;3233static void34gp_ask_confirm(const char *s)35{36err_printf(s);37err_printf(". OK ? (^C if not)\n");38pari_hit_return();39}4041/* numerr < 0: after changing PARI stack size42* numerr > 0: normal error, including SIGINT */43static void44gp_err_recover(long numerr)45{46longjmp(env[s_env.n-1], numerr);47}4849/* numerr >= 0 */50static void51gp_pre_recover(long numerr)52{53out_puts(pariErr, "\n"); pariErr->flush();54gp_err_recover(numerr);55}5657static void58reset_ctrlc(void)59{60#if defined(_WIN32) || defined(__CYGWIN32__)61win32ctrlc = 0;62#endif63}6465static int66is_silent(char *s) { return s[strlen(s) - 1] == ';'; }6768static int stdin_isatty = 0;69static int70is_interactive(void)71{ return pari_infile == stdin && stdin_isatty; }7273/*******************************************************************/74/** **/75/** INITIALIZATION **/76/** **/77/*******************************************************************/78static void79print_shortversion(void)80{81const ulong mask = (1UL<<PARI_VERSION_SHIFT) - 1;82ulong n = paricfg_version_code, major, minor, patch;8384patch = n & mask; n >>= PARI_VERSION_SHIFT;85minor = n & mask; n >>= PARI_VERSION_SHIFT;86major = n;87printf("%lu.%lu.%lu\n", major,minor,patch); exit(0);88}8990static void91usage(char *s)92{93printf("### Usage: %s [options] [GP files]\n", s);94printf("Available options:\n");95printf(" [-f,--fast]\t\tFast start: do not read .gprc\n");96printf(" [-q,--quiet]\t\tQuiet mode: do not print banner and history numbers\n");97printf(" [-s stacksize]\tStart with the PARI stack of given size (in bytes)\n");98printf(" [--default key=val]\tExecute default(key,val) on startup\n");99printf(" [--emacs]\t\tRun as if in Emacs shell\n");100printf(" [--help]\t\tPrint this message\n");101printf(" [--test]\t\tTest mode. No history, wrap long lines (bench only)\n");102printf(" [--texmacs]\t\tRun as if using TeXmacs frontend\n");103printf(" [--version]\t\tOutput version info and exit\n");104printf(" [--version-short]\tOutput version number and exit\n\n");105exit(0);106}107108static void109gp_head(void)110{111pari_print_version();112pari_putc('\n');113pari_center("Copyright (C) 2000-2021 The PARI Group");114pari_putc('\n');115print_text("PARI/GP is free software, covered by the GNU General Public \116License, and comes WITHOUT ANY WARRANTY WHATSOEVER.");117pari_puts("\nType ? for help, \\q to quit.\n");118pari_printf("Type ?%d for how to get moral"119" (and possibly technical) support.\n", pari_community());120if (pari_mainstack->vsize)121pari_printf("\nparisizemax = %lu, primelimit = %lu",122pari_mainstack->vsize,GP_DATA->primelimit);123else124pari_printf("\nparisize = %lu, primelimit = %lu",125pari_mainstack->rsize,GP_DATA->primelimit);126if (pari_mt_nbthreads > 1)127pari_printf(", nbthreads = %lu", pari_mt_nbthreads);128pari_putc('\n');129}130131static char *132read_arg(long *nread, char *t, long argc, char **argv)133{134long i = *nread;135if (isdigit((int)*t)) return t;136if (*t || i==argc) usage(argv[0]);137*nread = i+1; return argv[i];138}139140static char *141read_arg_equal(long *nread, char *t, long argc, char **argv)142{143long i = *nread;144if (*t=='=' && isdigit((int)t[1])) return t+1;145if (*t || i==argc) usage(argv[0]);146*nread = i+1; return argv[i];147}148149static void150init_trivial_stack(void)151{152const size_t s = 2048;153pari_mainstack->size = s;154pari_mainstack->bot = (pari_sp)pari_malloc(s);155avma = pari_mainstack->top = pari_mainstack->bot + s;156}157158static void159free_trivial_stack(void)160{161free((void*)pari_mainstack->bot);162}163164typedef struct { char *key, *val; } pair_t;165/* If ab of the form key=val, record pair in new stack entry166* P[n].key must be freed by caller to avoid memory leak */167static void168record_default(pari_stack *s_P, char *ab)169{170pair_t *P = (pair_t*)*pari_stack_base(s_P);171char *k, *v;172long n;173ab = pari_strdup(ab);174parse_key_val(ab, &k, &v);175n = pari_stack_new(s_P);176P[n].key = k;177P[n].val = v;178}179static void180read_opt(pari_stack *p_A, long argc, char **argv)181{182pair_t *P;183pari_stack s_P; /* key / value to record default() settings */184char *b = NULL, *p = NULL, *s = NULL;185ulong f = GP_DATA->flags;186long i = 1, initrc = 1;187188(void)&p; (void)&b; (void)&s; /* -Wall gcc-2.95 */189190pari_stack_init(&s_P,sizeof(*P),(void**)&P);191pari_stack_alloc(&s_P, 64);192pari_outfile = stderr;193while (i < argc)194{195char *t = argv[i];196197if (*t++ != '-') break;198i++;199START:200switch(*t++)201{202case 'p': p = read_arg(&i,t,argc,argv); break;203case 's': s = read_arg(&i,t,argc,argv); break;204case 'e':205f |= gpd_EMACS; if (*t) goto START;206break;207case 'q':208f |= gpd_QUIET; if (*t) goto START;209break;210case 't':211f |= gpd_TEST; if (*t) goto START;212break;213case 'f':214initrc = 0; if (*t) goto START;215break;216case 'D':217if (*t || i == argc) usage(argv[0]);218record_default(&s_P, argv[i++]);219break;220case '-':221if (strcmp(t, "version-short") == 0) { print_shortversion(); exit(0); }222if (strcmp(t, "version") == 0) {223init_trivial_stack(); pari_print_version();224free_trivial_stack(); exit(0);225}226if (strcmp(t, "default") == 0) {227if (i == argc) usage(argv[0]);228record_default(&s_P, argv[i++]);229break;230}231if (strcmp(t, "texmacs") == 0) { f |= gpd_TEXMACS; break; }232if (strcmp(t, "emacs") == 0) { f |= gpd_EMACS; break; }233if (strcmp(t, "test") == 0) { f |= gpd_TEST; initrc = 0; break; }234if (strcmp(t, "quiet") == 0) { f |= gpd_QUIET; break; }235if (strcmp(t, "fast") == 0) { initrc = 0; break; }236if (strncmp(t, "primelimit",10) == 0) {p = read_arg_equal(&i,t+10,argc,argv); break; }237if (strncmp(t, "stacksize",9) == 0) {s = read_arg_equal(&i,t+9,argc,argv); break; }238/* fall through */239default:240usage(argv[0]);241}242}243if (f & gpd_TEST) stdin_isatty = 0;244GP_DATA->flags = f;245#ifdef READLINE246GP_DATA->use_readline = stdin_isatty;247#endif248if (!is_interactive()) GP_DATA->breakloop = 0;249if (initrc) gp_initrc(p_A);250for ( ; i < argc; i++) pari_stack_pushp(p_A, pari_strdup(argv[i]));251252/* override the values from gprc */253if (p) (void)sd_primelimit(p, d_INITRC);254if (s) (void)sd_parisize(s, d_INITRC);255for (i = 0; i < s_P.n; i++) {256setdefault(P[i].key, P[i].val, d_INITRC);257free((void*)P[i].key);258}259pari_stack_delete(&s_P);260pari_outfile = stdout;261}262263/*******************************************************************/264/** **/265/** TEST MODE **/266/** **/267/*******************************************************************/268static int269test_is_interactive(void) { return 0; }270271static void272test_output(GEN z) { init_linewrap(76); gen_output(z); }273void274init_test(void)275{276disable_color = 1;277init_linewrap(76);278pari_errfile = stdout;279cb_gp_output = test_output;280cb_pari_is_interactive = test_is_interactive;281}282283/*******************************************************************/284/** **/285/** FORMAT GP OUTPUT **/286/** **/287/*******************************************************************/288/* REGULAR */289static void290normal_output(GEN z, long n)291{292long l = 0;293char *s;294/* history number */295if (n)296{297char buf[64];298if (!(GP_DATA->flags & gpd_QUIET))299{300term_color(c_HIST);301sprintf(buf, "%%%ld = ", n);302pari_puts(buf);303l = strlen(buf);304}305}306/* output */307term_color(c_OUTPUT);308s = GENtostr(z);309if (GP_DATA->lim_lines)310lim_lines_output(s, l, GP_DATA->lim_lines);311else312pari_puts(s);313pari_free(s);314term_color(c_NONE); pari_putc('\n');315}316317static void318gp_output(GEN z)319{320if (cb_gp_output) { cb_gp_output(z); return; }321if (GP_DATA->fmt->prettyp == f_PRETTY)322{ if (tex2mail_output(z, GP_DATA->hist->total)) return; }323normal_output(z, GP_DATA->hist->total);324pari_flush();325}326327static GEN328gp_main_loop(long ismain)329{330VOLATILE GEN z = gnil;331VOLATILE long t = 0, r = 0;332VOLATILE pari_sp av = avma;333filtre_t F;334Buffer *b = filtered_buffer(&F);335struct gp_context rec;336long er;337if ((er = setjmp(env[s_env.n-1])))338{ /* recover: jump from error [ > 0 ] or allocatemem [ -1 ] */339if (er > 0) { /* true error */340if (!(GP_DATA->recover)) exit(1);341gp_context_restore(&rec);342/* true error not from main instance, let caller sort it out */343if (!ismain) { kill_buffers_upto_including(b); return NULL; }344} else { /* allocatemem */345tmp_restore(rec.file.file);346gp_context_save(&rec);347}348set_avma(av = pari_mainstack->top);349parivstack_reset();350kill_buffers_upto(b);351pari_alarm(0);352}353for(;;)354{355gp_context_save(&rec);356if (! gp_read_line(&F, NULL))357{358if (popinfile()) gp_quit(0);359if (ismain) continue;360pop_buffer(); return z;361}362if (ismain)363{364reset_ctrlc();365timer_start(GP_DATA->T);366walltimer_start(GP_DATA->Tw);367pari_set_last_newline(1);368}369if (gp_meta(b->buf,ismain)) continue;370z = pari_compile_str(b->buf);371z = closure_evalres(z);372if (!ismain) continue;373374t = timer_delay(GP_DATA->T);375r = walltimer_delay(GP_DATA->Tw);376if (!pari_last_was_newline()) pari_putc('\n');377pari_alarm(0);378if (t && GP_DATA->chrono)379{380if (pari_mt_nbthreads==1)381{382pari_puts("time = ");383pari_puts(gp_format_time(t));384}385else386{387pari_puts("cpu time = ");388pari_puts(gp_format_time(t));389pari_puts(", real time = ");390pari_puts(gp_format_time(r));391}392pari_puts(".\n");393}394if (GP_DATA->simplify) z = simplify_shallow(z);395pari_add_hist(z, t, r);396if (z != gnil && ! is_silent(b->buf) ) gp_output(z);397set_avma(av);398parivstack_reset();399}400}401402/* as gp_read_file, before running the main gp instance */403static void404read_main(const char *s)405{406GEN z;407if (setjmp(env[s_env.n-1]))408z = NULL;409else {410FILE *f = switchin(s);411if (file_is_binary(f)) {412z = readbin(s,f, NULL);413popinfile();414}415else z = gp_main_loop(0);416}417if (!z) err_printf("... skipping file '%s'\n", s);418set_avma(pari_mainstack->top);419}420421static const char *422break_loop_prompt(long n)423{424const char *s = (n==1)? "break> ": stack_sprintf("break[%ld]> ", n);425return gp_format_prompt(s);426}427428static long frame_level=0, dbg_level = 0;429430static int431break_loop(int numerr)432{433filtre_t F;434Buffer *b;435int sigint = numerr<0, go_on = sigint;436struct gp_context rec1, rec2;437const char *prompt, *msg;438long nenv, oldframe_level = frame_level;439pari_sp av;440441if (numerr == e_SYNTAX) return 0;442if (numerr == e_STACK) { evalstate_clone(); set_avma(pari_mainstack->top); }443gp_context_save(&rec1);444445b = filtered_buffer(&F);446nenv=pari_stack_new(&s_env);447prompt = break_loop_prompt(s_env.n-1);448iferr_env = NULL;449dbg_level = 0;450frame_level = closure_context(oldframe_level, dbg_level);451pari_infile = newfile(stdin, "stdin", mf_IN)->file;452term_color(c_ERR); pari_putc('\n');453if (sigint)454msg = "Break loop: <Return> to continue; 'break' to go back to GP prompt";455else456msg = "Break loop: type 'break' to go back to GP prompt";457print_errcontext(pariOut, msg, NULL, NULL);458term_color(c_NONE);459av = avma;460for(;;)461{462GEN x;463long er, br_status;464set_avma(av);465gp_context_save(&rec2);466if ((er=setjmp(env[nenv])))467{468if (er < 0)469{470s_env.n = 1;471frame_level = oldframe_level;472longjmp(env[s_env.n-1], er);473}474gp_context_restore(&rec2);475iferr_env = NULL;476closure_err(dbg_level);477compilestate_restore(&rec1.eval.comp);478(void) closure_context(oldframe_level, dbg_level);479pari_infile = newfile(stdin, "stdin", mf_IN)->file;480}481term_color(c_NONE);482if (!gp_read_line(&F, prompt))483br_status = br_BREAK; /* EOF */484else485{486/* Empty input ? Continue if entry on sigint (exit debugger frame) */487if (! *(b->buf) && sigint) break;488reset_ctrlc();489if (gp_meta(b->buf,0)) continue;490x = pari_compile_str(b->buf);491x = closure_evalbrk(x, &br_status);492}493switch (br_status)494{495case br_NEXT: case br_MULTINEXT:496popinfile(); /* exit frame. Don't exit debugger if s_env.n > 2 */497go_on = 0; goto BR_EXIT;498case br_BREAK: case br_RETURN:499killallfiles(); /* completely exit the debugger */500go_on = 0; goto BR_EXIT;501}502if (x!=gnil && !is_silent(b->buf)) { term_color(c_OUTPUT); gen_output(x); }503}504BR_EXIT:505s_env.n=nenv;506frame_level = oldframe_level;507gp_context_restore(&rec1);508pop_buffer(); return go_on;509}510511#ifdef __CYGWIN32__512void513cyg_environment(int argc, char ** argv)514{515char *ti_dirs = getenv("TERMINFO_DIRS");516char *argv0, *p;517char *newdir;518long n;519520if (!argc || !argv) return;521argv0 = *argv;522if (!argv0 || !*argv0) return;523p = strrchr(argv0, '/');524if (!p)525p = argv0 = "";526else527p++;528n = p - argv0;529if (ti_dirs)530{531n += 14 + strlen(ti_dirs) + 1 + 8 + 1;532newdir = malloc(n);533if (!newdir) return;534snprintf(newdir, n-8, "TERMINFO_DIRS=%s:%s", ti_dirs, argv0);535}536else537{538n += 14 + 8 + 1;539newdir = malloc(n);540if (!newdir) return;541snprintf(newdir, n-8, "TERMINFO_DIRS=%s", argv0);542}543strcpy(newdir+n-9,"terminfo");544putenv(newdir);545}546#endif547548int549main(int argc, char **argv)550{551char **A;552pari_stack s_A;553554GP_DATA = default_gp_data();555pari_stack_init(&s_env, sizeof(*env), (void**)&env);556(void)pari_stack_new(&s_env);557558if (setjmp(env[s_env.n-1]))559{560puts("### Errors on startup, exiting...\n\n");561exit(1);562}563#ifdef __CYGWIN32__564cyg_environment(argc, argv);565#endif566stdin_isatty = pari_stdin_isatty();567pari_init_defaults();568pari_library_path = DL_DFLT_NAME;569pari_stack_init(&s_A,sizeof(*A),(void**)&A);570/* must be defined here in case an error is raised in pari_init_opts, e.g.571* when parsing function prototypes */572cb_pari_err_recover = gp_err_recover;573pari_init_opts(1000000 * sizeof(long), 0, INIT_SIGm | INIT_noPRIMEm | INIT_noIMTm);574cb_pari_pre_recover = gp_pre_recover;575cb_pari_break_loop = break_loop;576cb_pari_is_interactive = is_interactive;577578read_opt(&s_A, argc,argv);579pari_init_primes(GP_DATA->primelimit);580#ifdef SIGALRM581(void)os_signal(SIGALRM,gp_alarm_handler);582#endif583pari_add_module(functions_gp);584585pari_set_plot_engine(gp_get_plot);586cb_pari_quit = gp_quit;587cb_pari_whatnow = whatnow;588cb_pari_sigint = gp_sigint_fun;589cb_pari_handle_exception = gp_handle_exception;590cb_pari_ask_confirm = gp_ask_confirm;591pari_init_paths();592pari_mt_init(); /* MPI: will not return on slaves (pari_MPI_rank = 0) */593#ifdef _WIN32594if (stdin_isatty) win32_set_codepage();595#endif596#ifdef READLINE597init_readline();598#endif599if (GP_DATA->flags & gpd_EMACS) init_emacs();600if (GP_DATA->flags & gpd_TEXMACS) init_texmacs();601602timer_start(GP_DATA->T);603walltimer_start(GP_DATA->Tw);604if (!(GP_DATA->flags & gpd_QUIET)) gp_head();605if (GP_DATA->flags & gpd_TEST) init_test();606if (s_A.n)607{608FILE *l = pari_logfile;609long i;610pari_logfile = NULL;611for (i = 0; i < s_A.n; pari_free(A[i]),i++) read_main(A[i]);612/* Reading one of the input files above can set pari_logfile.613* Don't restore in that case. */614if (!pari_logfile) pari_logfile = l;615}616pari_stack_delete(&s_A);617(void)gp_main_loop(1);618gp_quit(0);619return 0; /* LCOV_EXCL_LINE */620}621622void623pari_breakpoint(void)624{625if (!pari_last_was_newline()) pari_putc('\n');626closure_err(0);627if (cb_pari_break_loop && cb_pari_break_loop(-1)) return;628cb_pari_err_recover(e_MISC);629}630631void632dbg_down(long k)633{634if (k<0) k=0;635dbg_level -= k;636if (dbg_level<0) dbg_level=0;637gp_err_recover(e_NONE);638}639640GEN641dbg_err(void) { GEN E = pari_err_last(); return E? gcopy(E):gnil; }642643void644dbg_up(long k)645{646if (k<0) k=0;647dbg_level += k;648if (dbg_level>frame_level) dbg_level=frame_level;649gp_err_recover(e_NONE);650}651652void653gp_quit(long code)654{655pari_kill_plot_engine();656pari_close();657kill_buffers_upto(NULL);658if (!(GP_DATA->flags & gpd_QUIET)) pari_puts("Goodbye!\n");659if (cb_pari_end_output) cb_pari_end_output();660exit(code);661}662663void664whatnow0(char *s) { whatnow(pariOut, s,0); }665666#include "gp_init.h"667668669