Annotation of OpenXM_contrib/pari/src/gp/gp.c, Revision 1.1
1.1 ! maekawa 1: /*******************************************************************/
! 2: /** **/
! 3: /** PARI CALCULATOR **/
! 4: /** **/
! 5: /*******************************************************************/
! 6: /* $Id: gp.c,v 1.1.1.1 1999/09/16 13:47:41 karim Exp $ */
! 7: #include "pari.h"
! 8: #ifdef _WIN32
! 9: # include <windows.h>
! 10: # ifndef WINCE
! 11: # include <process.h>
! 12: # endif
! 13: #endif
! 14: #ifdef HAS_STRFTIME
! 15: # include <time.h>
! 16: #endif
! 17: #include "../language/anal.h"
! 18: #include "gp.h"
! 19:
! 20: #ifdef READLINE
! 21: void init_readline();
! 22: BEGINEXTERN
! 23: # if defined(__cplusplus) && defined(__SUNPRO_CC)
! 24: /* readline.h gives a bad definition of readline() */
! 25: extern char*readline(char*);
! 26: # else
! 27: # ifdef READLINE_LIBRARY
! 28: # include <readline.h>
! 29: # else
! 30: # include <readline/readline.h>
! 31: # endif
! 32: # endif
! 33: extern int isatty(int);
! 34: extern void add_history(char*);
! 35: ENDEXTERN
! 36: #endif
! 37:
! 38: char* _analyseur(void);
! 39: void err_recover(long numerr);
! 40: void free_graph(void);
! 41: void gp_expand_path(char *v);
! 42: int gp_init_entrees(module *modlist, entree **hash, int force);
! 43: long gptimer(void);
! 44: void init80(long n);
! 45: void init_defaults(int force);
! 46: void init_graph(void);
! 47: void init_lim_lines(char *s, long max);
! 48: void pari_sig_init(void (*f)(int));
! 49: int whatnow(char *s, int flag);
! 50:
! 51: #define MAX_PROMPT_LEN 128
! 52: #define DFT_PROMPT "? "
! 53: #define COMMENTPROMPT "comment> "
! 54: #define DFT_INPROMPT ""
! 55: static GEN *hist;
! 56: static jmp_buf local_environnement[MAX_BUFFER];
! 57: static char *help_prg,*path,*buflist[MAX_BUFFER];
! 58: static char prompt[MAX_PROMPT_LEN];
! 59: static char thestring[256];
! 60: static long prettyp, test_mode, quiet_mode, gpsilent, simplifyflag;
! 61: static long secure;
! 62: static long chrono, pariecho, primelimit, parisize, strictmatch;
! 63: static long bufindex, tglobal, histsize, paribufsize, lim_lines;
! 64: static gp_format fmt;
! 65:
! 66: #define LBRACE '{'
! 67: #define RBRACE '}'
! 68: #define pariputs_opt(s) if (!quiet_mode) pariputs(s)
! 69:
! 70: void
! 71: hit_return()
! 72: {
! 73: char tmp[16];
! 74: pariputs("---- (type return to continue) ----");
! 75: do fgets(tmp,16,stdin); while (tmp[strlen(tmp)-1] != '\n');
! 76: /* \n has to be echoed later if we are under emacs (E. Kowalski) */
! 77: pariputc('\n');
! 78: }
! 79:
! 80: static void
! 81: usage(char *s)
! 82: {
! 83: printf("### Usage: %s [options]\n", s);
! 84: printf("Options are:\n");
! 85: printf("\t[-b buffersize]\tDeprecated\n");
! 86: printf("\t[-emacs]\tRun as if in Emacs shell\n");
! 87: printf("\t[-f]\t\tFaststart: do not read .gprc\n");
! 88: printf("\t[--help]\tPrint this message\n");
! 89: printf("\t[-q]\t\tQuiet mode: do not print banner and history numbers\n");
! 90: printf("\t[-p primelimit]\tPrecalculate primes up to the limit\n");
! 91: printf("\t[-s stacksize]\tStart with the PARI stack of given size (in bytes)\n");
! 92: printf("\t[-test]\t\tTest mode. As -q, plus wrap long lines\n");
! 93: printf("\t[--version]\tOutput version info and exit\n\n");
! 94: exit(0);
! 95: }
! 96:
! 97: /* must be called BEFORE pari_init() */
! 98: static void
! 99: gp_preinit(int force)
! 100: {
! 101: static char *dflt;
! 102: char *help;
! 103: long i;
! 104:
! 105: if (force)
! 106: {
! 107: #if !defined(macintosh) || defined(__MWERKS__)
! 108: primelimit = 500000; parisize = 1000000*sizeof(long);
! 109: dflt = DFT_PROMPT;
! 110: #else
! 111: primelimit = 200000; parisize = 1000000;
! 112: dflt = "?\n";
! 113: #endif
! 114: }
! 115: strcpy(prompt, dflt);
! 116:
! 117: #if defined(UNIX) || defined(__EMX__)
! 118: # ifdef __EMX__
! 119: path = pari_strdup(".;C:/;C:/gp");
! 120: # else
! 121: path = pari_strdup(".:~:~/gp");
! 122: # endif
! 123: help = getenv("GPHELP");
! 124: # ifdef GPHELP
! 125: if (!help) help = GPHELP;
! 126: # endif
! 127: #else
! 128: path = pari_strdup(".");
! 129: help = NULL;
! 130: #endif
! 131: help_prg = help? pari_strdup(help): NULL;
! 132: prettyp = f_PRETTYMAT;
! 133: strictmatch = simplifyflag = 1;
! 134: tglobal = 0;
! 135: bufindex = -1;
! 136: secure = test_mode = under_emacs = chrono = pariecho = 0;
! 137: fmt.format = 'g'; fmt.field = 0;
! 138: #ifdef LONG_IS_64BIT
! 139: fmt.nb = 38;
! 140: #else
! 141: fmt.nb = 28;
! 142: #endif
! 143: lim_lines = 0;
! 144: histsize = 5000; paribufsize = 1024;
! 145: i = histsize*sizeof(GEN);
! 146: hist = (GEN *) gpmalloc(i); memset(hist,0,i);
! 147: for (i=0; i<c_LAST; i++) gp_colors[i] = c_NONE;
! 148: }
! 149:
! 150: #define GET_SEP_SIZE 128
! 151: #define separe(c) ((c)==';' || (c)==':')
! 152:
! 153: /* Return all chars, up to next separator */
! 154: static char*
! 155: get_sep(char *t)
! 156: {
! 157: static char buf[GET_SEP_SIZE], *lim = buf + GET_SEP_SIZE-1;
! 158: char *s = buf;
! 159: int outer=1;
! 160:
! 161: for(;;)
! 162: {
! 163: switch(*s++ = *t++)
! 164: {
! 165: case '"':
! 166: if (outer || s[-2] != '\\') outer = !outer;
! 167: break;
! 168: case '\0':
! 169: return buf;
! 170: default:
! 171: if (outer && separe(*t)) { *s=0; return buf; }
! 172: }
! 173: if (s == lim) err(talker,"buffer overflow in get_sep");
! 174: }
! 175: }
! 176:
! 177: /* as above, t must be writeable, return 1 if we modified t */
! 178: static int
! 179: get_sep2(char *t)
! 180: {
! 181: int outer=1;
! 182: char *s = t;
! 183:
! 184: for(;;)
! 185: {
! 186: switch (*s++)
! 187: {
! 188: case '"':
! 189: if (outer || s[-2] != '\\') outer = !outer;
! 190: break;
! 191: case '\0':
! 192: return 0;
! 193: default:
! 194: if (outer && separe(*s)) { *s=0; return 1; }
! 195: }
! 196: }
! 197: }
! 198:
! 199: static long
! 200: get_int(char *s, long dflt)
! 201: {
! 202: char *p=get_sep(s);
! 203: long n=atol(p);
! 204:
! 205: if (*p == '-') p++;
! 206: while(isdigit((int)*p)) { p++; dflt=n; }
! 207: if (*p) err(talker2,"I was expecting an integer here", s, s);
! 208: return dflt;
! 209: }
! 210:
! 211: static void
! 212: gp_output(GEN x)
! 213: {
! 214: long tx=typ(x);
! 215:
! 216: if (fmt.nb >= 0 && is_intreal_t(tx))
! 217: ecrire(x, fmt.format, fmt.nb, fmt.field);
! 218: else
! 219: switch(prettyp)
! 220: {
! 221: case f_PRETTYMAT: matbrute(x, fmt.format, fmt.nb); break;
! 222: case f_PRETTY : sor(x, fmt.format, fmt.nb, fmt.field); break;
! 223: case f_RAW : brute(x, fmt.format, fmt.nb); break;
! 224: case f_TEX : texe(x, fmt.format, fmt.nb); break;
! 225: }
! 226: }
! 227:
! 228: /* print a sequence of (NULL terminated) GEN */
! 229: void
! 230: print0(GEN *g, long flag)
! 231: {
! 232: int old=prettyp;
! 233:
! 234: if (flag < NBFORMATS) added_newline=1;
! 235: else
! 236: { flag -= NBFORMATS; added_newline=0; }
! 237: prettyp=flag;
! 238:
! 239: for( ; *g; g++)
! 240: if (typ(*g)==t_STR)
! 241: pariputs(GSTR(*g)); /* otherwise it's surrounded by "" */
! 242: else
! 243: gp_output(*g);
! 244:
! 245: if (added_newline) pariputc('\n');
! 246: prettyp=old; pariflush();
! 247: }
! 248:
! 249: /* write a sequence of (NULL terminated) GEN, to file s */
! 250: void
! 251: write0(char *s, GEN *g, long flag)
! 252: {
! 253: int i = added_newline;
! 254: s = expand_tilde(s); switchout(s); free(s);
! 255: print0(g,flag); added_newline = i;
! 256: switchout(NULL);
! 257: }
! 258:
! 259: /********************************************************************/
! 260: /* */
! 261: /* DEFAULTS */
! 262: /* */
! 263: /********************************************************************/
! 264: static void
! 265: do_strftime(char *s, char *buf)
! 266: {
! 267: #ifdef HAS_STRFTIME
! 268: time_t t = time(NULL);
! 269: strftime(buf,MAX_PROMPT_LEN-1,s,localtime(&t));
! 270: #else
! 271: strcpy(buf,s);
! 272: #endif
! 273: }
! 274:
! 275: static GEN
! 276: sd_numeric(char *v, int flag, char *s, long *ptn, long Min, long Max,
! 277: char **msg)
! 278: {
! 279: long n;
! 280: if (*v == 0) n = *ptn;
! 281: else
! 282: {
! 283: n = get_int(v,0);
! 284: if (*ptn == n) return gnil;
! 285: if (n > Max || n < Min)
! 286: {
! 287: sprintf(thestring, "default: incorrect value for %s [%ld-%ld]",
! 288: s, Min, Max);
! 289: err(talker2, thestring, v,v);
! 290: }
! 291: *ptn = n;
! 292: }
! 293: switch(flag)
! 294: {
! 295: case d_RETURN: return stoi(n);
! 296: case d_ACKNOWLEDGE:
! 297: if (msg)
! 298: {
! 299: if (!*msg)
! 300: msg++; /* single msg, always printed */
! 301: else
! 302: msg += n; /* one per possible value */
! 303: pariputsf(" %s = %ld %s\n", s, n, *msg);
! 304: }
! 305: else if (Max != 1 || Min != 0)
! 306: pariputsf(" %s = %ld\n", s, n);
! 307: else /* toggle */
! 308: {
! 309: if (n==1) pariputsf(" %s = 1 (on)\n", s);
! 310: else pariputsf(" %s = 0 (off)\n", s);
! 311: } /* fall through */
! 312: default: return gnil;
! 313: }
! 314: }
! 315:
! 316: #define PRECDIGIT (long)((prec-2.)*pariK)
! 317: static GEN
! 318: sd_realprecision(char *v, int flag)
! 319: {
! 320: if (*v)
! 321: {
! 322: long newnb = get_int(v, fmt.nb);
! 323: long newprec = (long) (newnb*pariK1 + 3);
! 324:
! 325: if (fmt.nb == newnb && prec == newprec) return gnil;
! 326: if (newnb < 0) err(talker,"default: negative real precision");
! 327: fmt.nb = newnb; prec = newprec;
! 328: }
! 329: if (flag == d_RETURN) return stoi(fmt.nb);
! 330: if (flag == d_ACKNOWLEDGE)
! 331: {
! 332: long n = PRECDIGIT;
! 333: pariputsf(" realprecision = %ld significant digits", n);
! 334: if (n != fmt.nb) pariputsf(" (%ld digits displayed)", fmt.nb);
! 335: pariputc('\n');
! 336: }
! 337: return gnil;
! 338: }
! 339: #undef PRECDIGIT
! 340:
! 341: static GEN
! 342: sd_seriesprecision(char *v, int flag)
! 343: {
! 344: char *msg[] = {NULL, "significant terms"};
! 345: return sd_numeric(v,flag,"seriesprecision",&precdl, 0,LGBITS,msg);
! 346: }
! 347:
! 348: static GEN
! 349: sd_format(char *v, int flag)
! 350: {
! 351: if (*v)
! 352: {
! 353: char c = *v;
! 354: if (c!='e' && c!='f' && c!='g')
! 355: err(talker2,"default: inexistent format",v,v);
! 356: fmt.format = c; v++;
! 357:
! 358: if (isdigit((int)*v))
! 359: { fmt.field=atol(v); while (isdigit((int)*v)) v++; }
! 360: if (*v++ == '.')
! 361: {
! 362: if (*v == '-') fmt.nb = -1;
! 363: else
! 364: if (isdigit((int)*v)) fmt.nb=atol(v);
! 365: }
! 366: }
! 367: if (flag == d_RETURN)
! 368: {
! 369: sprintf(thestring, "%c%ld.%ld", fmt.format, fmt.field, fmt.nb);
! 370: return strtoGENstr(thestring,0);
! 371: }
! 372: if (flag == d_ACKNOWLEDGE)
! 373: pariputsf(" format = %c%ld.%ld\n", fmt.format, fmt.field, fmt.nb);
! 374: return gnil;
! 375: }
! 376:
! 377: static long
! 378: gp_get_color(char **st)
! 379: {
! 380: char *s, *v = *st;
! 381: int c, trans = 1;
! 382: if (!isdigit((int)*v))
! 383: {
! 384: if (*v == '[')
! 385: {
! 386: char *a[3];
! 387: int i = 0;
! 388: for (a[0] = s = ++v; *s && *s != ']'; s++)
! 389: if (*s == ',') { *s = 0; a[++i] = s+1; }
! 390: if (*s != ']') err(talker2,"expected character: ']'",s, *st);
! 391: *s = 0; for (i++; i<3; i++) a[i] = "";
! 392: /* properties | color | background */
! 393: c = (atoi(a[2])<<8) | atoi(a[0]) | (atoi(a[1])<<4);
! 394: trans = (*(a[1]) == 0);
! 395: v = s + 1;
! 396: }
! 397: else { c = c_NONE; trans = 0; }
! 398: }
! 399: else c = atol(v); /* color on transparent background */
! 400: if (trans) c = -c;
! 401: while (*v && *v++ != ',') /* empty */;
! 402: if (c != c_NONE) disable_color=0;
! 403: *st = v; return c;
! 404: }
! 405:
! 406: static GEN
! 407: sd_colors(char *v, int flag)
! 408: {
! 409: long c,l;
! 410: if (*v && !under_emacs)
! 411: {
! 412: char *tmp;
! 413: disable_color=1;
! 414: l = strlen(v);
! 415: if (l <= 2 && strncmp(v, "no", l) == 0)
! 416: v = "";
! 417: if (l <= 3 && strncmp(v, "yes", l) == 0)
! 418: v = "1, 5, 3, 7, 6, 2, 3"; /* Assume recent ReadLine. */
! 419: tmp = v = pari_strdup(v); filtre(v, f_INIT|f_REG);
! 420: for (c=c_ERR; c < c_LAST; c++)
! 421: gp_colors[c] = gp_get_color(&v);
! 422: free(tmp);
! 423: }
! 424: if (flag == d_ACKNOWLEDGE || flag == d_RETURN)
! 425: {
! 426: char *s = thestring;
! 427: int col[3], n;
! 428: for (*s=0,c=c_ERR; c < c_LAST; c++)
! 429: {
! 430: n = gp_colors[c];
! 431: if (n == c_NONE)
! 432: sprintf(s,"no");
! 433: else
! 434: {
! 435: decode_color(abs(n),col);
! 436: if (n < 0)
! 437: {
! 438: if (col[0])
! 439: sprintf(s,"[%d,,%d]",col[1],col[0]);
! 440: else
! 441: sprintf(s,"%d",col[1]);
! 442: }
! 443: else
! 444: sprintf(s,"[%d,%d,%d]",col[1],col[2],col[0]);
! 445: }
! 446: s += strlen(s);
! 447: if (c < c_LAST - 1) { *s++=','; *s++=' '; }
! 448: }
! 449: if (flag==d_RETURN) return strtoGENstr(thestring,0);
! 450: pariputsf(" colors = \"%s\"\n",thestring);
! 451: }
! 452: return gnil;
! 453: }
! 454:
! 455: static GEN
! 456: sd_compatible(char *v, int flag)
! 457: {
! 458: char *msg[] = {
! 459: "(no backward compatibility)",
! 460: "(warn when using obsolete functions)",
! 461: "(use old functions, don't ignore case)",
! 462: "(use old functions, ignore case)", NULL
! 463: };
! 464: long old = compatible;
! 465: GEN r = sd_numeric(v,flag,"compatible",&compatible, 0,3,msg);
! 466:
! 467: if (old != compatible && flag != d_INITRC)
! 468: {
! 469: int res = gp_init_entrees(new_fun_set? pari_modules: pari_oldmodules,
! 470: functions_hash, 0);
! 471: if (res) err(warner,"user functions re-initialized");
! 472: }
! 473: return r;
! 474: }
! 475:
! 476: static GEN
! 477: sd_secure(char *v, int flag)
! 478: {
! 479: if (secure)
! 480: {
! 481: fprintferr("Do you want to modify the 'secure' flag? (^C if not)\n");
! 482: hit_return();
! 483: }
! 484: return sd_numeric(v,flag,"secure",&secure, 0,1,NULL);
! 485: }
! 486:
! 487: static GEN
! 488: sd_buffersize(char *v, int flag)
! 489: { return sd_numeric(v,flag,"buffersize",&paribufsize, 0,
! 490: (VERYBIGINT / sizeof(long)) - 1,NULL); }
! 491: static GEN
! 492: sd_debug(char *v, int flag)
! 493: { return sd_numeric(v,flag,"debug",&DEBUGLEVEL, 0,20,NULL); }
! 494:
! 495: static GEN
! 496: sd_debugfiles(char *v, int flag)
! 497: { return sd_numeric(v,flag,"debugfiles",&DEBUGFILES, 0,20,NULL); }
! 498:
! 499: static GEN
! 500: sd_debugmem(char *v, int flag)
! 501: { return sd_numeric(v,flag,"debugmem",&DEBUGMEM, 0,20,NULL); }
! 502:
! 503: static GEN
! 504: sd_echo(char *v, int flag)
! 505: { return sd_numeric(v,flag,"echo",&pariecho, 0,1,NULL); }
! 506:
! 507: static GEN
! 508: sd_lines(char *v, int flag)
! 509: { return sd_numeric(v,flag,"lines",&lim_lines, 0,VERYBIGINT,NULL); }
! 510:
! 511: static GEN
! 512: sd_histsize(char *v, int flag)
! 513: {
! 514: long n = histsize;
! 515: GEN r = sd_numeric(v,flag,"histsize",&n, 1,
! 516: (VERYBIGINT / sizeof(long)) - 1,NULL);
! 517: if (n != histsize)
! 518: {
! 519: long i = n*sizeof(GEN);
! 520: GEN *gg = (GEN *) gpmalloc(i); memset(gg,0,i);
! 521:
! 522: if (tglobal)
! 523: {
! 524: long k = (tglobal-1) % n;
! 525: long kmin = k - min(n,histsize), j = k;
! 526:
! 527: i = (tglobal-1) % histsize;
! 528: while (k > kmin)
! 529: {
! 530: gg[j] = hist[i];
! 531: hist[i] = NULL;
! 532: if (!i) i = histsize;
! 533: if (!j) j = n;
! 534: i--; j--; k--;
! 535: }
! 536: while (hist[i])
! 537: {
! 538: gunclone(hist[i]);
! 539: if (!i) i = histsize;
! 540: i--;
! 541: }
! 542: }
! 543: free((void*)hist); hist=gg; histsize=n;
! 544: }
! 545: return r;
! 546: }
! 547:
! 548: static GEN
! 549: sd_log(char *v, int flag)
! 550: {
! 551: long vlog = logfile? 1: 0, old = vlog;
! 552: GEN r = sd_numeric(v,flag,"log",&vlog, 0,1,NULL);
! 553: if (vlog != old)
! 554: {
! 555: if (vlog)
! 556: {
! 557: logfile = fopen(current_logfile, "a");
! 558: if (!logfile) err(openfiler,"logfile",current_logfile);
! 559: #ifndef WINCE
! 560: setbuf(logfile,(char *)NULL);
! 561: #endif
! 562: }
! 563: else
! 564: {
! 565: if (flag == d_ACKNOWLEDGE)
! 566: pariputsf(" [logfile was \"%s\"]\n", current_logfile);
! 567: fclose(logfile); logfile=NULL;
! 568: }
! 569: }
! 570: return r;
! 571: }
! 572:
! 573: static GEN
! 574: sd_output(char *v, int flag)
! 575: {
! 576: char *msg[] = {"(raw)", "(prettymatrix)", "(prettyprint)", NULL};
! 577: return sd_numeric(v,flag,"output",&prettyp, 0,2,msg);
! 578: }
! 579:
! 580: static GEN
! 581: sd_parisize(char *v, int flag)
! 582: {
! 583: long n = parisize;
! 584: GEN r = sd_numeric(v,flag,"parisize",&n, 10000,VERYBIGINT,NULL);
! 585: if (n != parisize)
! 586: {
! 587: if (flag != d_INITRC)
! 588: {
! 589: parisize = allocatemoremem(n);
! 590: longjmp(local_environnement[bufindex], 0);
! 591: }
! 592: parisize = n;
! 593: }
! 594: return r;
! 595: }
! 596:
! 597: static GEN
! 598: sd_primelimit(char *v, int flag)
! 599: {
! 600: long n = primelimit;
! 601: GEN r = sd_numeric(v,flag,"primelimit",&n, 0,VERYBIGINT,NULL);
! 602: if (n != primelimit)
! 603: {
! 604: if (flag != d_INITRC)
! 605: {
! 606: byteptr ptr = initprimes(n);
! 607: free(diffptr); diffptr = ptr;
! 608: }
! 609: primelimit = n;
! 610: }
! 611: return r;
! 612: }
! 613:
! 614: static GEN
! 615: sd_simplify(char *v, int flag)
! 616: { return sd_numeric(v,flag,"simplify",&simplifyflag, 0,1,NULL); }
! 617:
! 618: static GEN
! 619: sd_strictmatch(char *v, int flag)
! 620: { return sd_numeric(v,flag,"strictmatch",&strictmatch, 0,1,NULL); }
! 621:
! 622: static GEN
! 623: sd_timer(char *v, int flag)
! 624: { return sd_numeric(v,flag,"timer",&chrono, 0,1,NULL); }
! 625:
! 626: static GEN
! 627: sd_filename(char *v, int flag, char *s, char **f)
! 628: {
! 629: if (*v)
! 630: {
! 631: char *old = *f;
! 632: v = expand_tilde(v);
! 633: do_strftime(v,thestring); free(v);
! 634: *f = pari_strdup(thestring); free(old);
! 635: }
! 636: if (flag == d_RETURN) return strtoGENstr(*f,0);
! 637: if (flag == d_ACKNOWLEDGE) pariputsf(" %s = \"%s\"\n",s,*f);
! 638: return gnil;
! 639: }
! 640:
! 641: static GEN
! 642: sd_logfile(char *v, int flag)
! 643: {
! 644: GEN r = sd_filename(v, flag, "logfile", ¤t_logfile);
! 645: if (*v && logfile)
! 646: {
! 647: fclose(logfile);
! 648: logfile = fopen(current_logfile, "a");
! 649: if (!logfile) err(openfiler,"logfile",current_logfile);
! 650: #ifndef WINCE
! 651: setbuf(logfile,(char *)NULL);
! 652: #endif
! 653: }
! 654: return r;
! 655: }
! 656:
! 657: static GEN
! 658: sd_psfile(char *v, int flag)
! 659: { return sd_filename(v, flag, "psfile", ¤t_psfile); }
! 660:
! 661: static GEN
! 662: sd_help(char *v, int flag)
! 663: {
! 664: char *str;
! 665: if (*v)
! 666: {
! 667: if (help_prg) free(help_prg);
! 668: help_prg = expand_tilde(v);
! 669: }
! 670: str = help_prg? help_prg: "none";
! 671: if (flag == d_RETURN) return strtoGENstr(str,0);
! 672: if (flag == d_ACKNOWLEDGE)
! 673: pariputsf(" help = \"%s\"\n", str);
! 674: return gnil;
! 675: }
! 676:
! 677: static GEN
! 678: sd_path(char *v, int flag)
! 679: {
! 680: if (*v)
! 681: {
! 682: char *old = path;
! 683: path = pari_strdup(v); free(old);
! 684: if (flag == d_INITRC) return gnil;
! 685: gp_expand_path(path);
! 686: }
! 687: if (flag == d_RETURN) return strtoGENstr(path,0);
! 688: if (flag == d_ACKNOWLEDGE)
! 689: pariputsf(" path = \"%s\"\n",path);
! 690: return gnil;
! 691: }
! 692:
! 693: static GEN
! 694: sd_prompt(char *v, int flag)
! 695: {
! 696: if (*v)
! 697: {
! 698: strncpy(prompt,v,MAX_PROMPT_LEN);
! 699: #ifdef macintosh
! 700: strcat(prompt,"\n");
! 701: #endif
! 702: }
! 703: if (flag == d_RETURN) return strtoGENstr(prompt,0);
! 704: if (flag == d_ACKNOWLEDGE)
! 705: pariputsf(" prompt = \"%s\"\n",prompt);
! 706: return gnil;
! 707: }
! 708:
! 709: default_type gp_default_list[] =
! 710: {
! 711: {"buffersize",(void*)sd_buffersize},
! 712: {"colors",(void*)sd_colors},
! 713: {"compatible",(void*)sd_compatible},
! 714: {"debug",(void*)sd_debug},
! 715: {"debugfiles",(void*)sd_debugfiles},
! 716: {"debugmem",(void*)sd_debugmem},
! 717: {"echo",(void*)sd_echo},
! 718: {"format",(void*)sd_format},
! 719: {"help",(void*)sd_help},
! 720: {"histsize",(void*)sd_histsize},
! 721: {"lines",(void*)sd_lines},
! 722: {"log",(void*)sd_log},
! 723: {"logfile",(void*)sd_logfile},
! 724: {"output",(void*)sd_output},
! 725: {"parisize",(void*)sd_parisize},
! 726: {"path",(void*)sd_path},
! 727: {"primelimit",(void*)sd_primelimit},
! 728: {"prompt",(void*)sd_prompt},
! 729: {"psfile",(void*)sd_psfile},
! 730: {"realprecision",(void*)sd_realprecision},
! 731: {"secure",(void*)sd_secure},
! 732: {"seriesprecision",(void*)sd_seriesprecision},
! 733: {"simplify",(void*)sd_simplify},
! 734: {"strictmatch",(void*)sd_strictmatch},
! 735: {"timer",(void *)sd_timer},
! 736: {NULL,NULL} /* sentinel */
! 737: };
! 738:
! 739: static void
! 740: help_default()
! 741: {
! 742: default_type *dft;
! 743:
! 744: for (dft=gp_default_list; dft->fun; dft++)
! 745: ((void (*)(ANYARG)) dft->fun)("", d_ACKNOWLEDGE);
! 746: }
! 747:
! 748: static GEN
! 749: setdefault(char *s,char *v, int flag)
! 750: {
! 751: default_type *dft;
! 752:
! 753: if (!*s) { help_default(); return gnil; }
! 754: for (dft=gp_default_list; dft->fun; dft++)
! 755: if (!strcmp(s,dft->name))
! 756: {
! 757: if (flag == d_EXISTS) return gun;
! 758: return ((GEN (*)(ANYARG)) dft->fun)(v,flag);
! 759: }
! 760: if (flag == d_EXISTS) return gzero;
! 761: err(talker,"unknown default: %s",s);
! 762: return NULL; /* not reached */
! 763: }
! 764:
! 765: /********************************************************************/
! 766: /** **/
! 767: /** HELP **/
! 768: /** **/
! 769: /********************************************************************/
! 770: static int
! 771: has_ext_help()
! 772: {
! 773: if (help_prg)
! 774: {
! 775: char *buf = pari_strdup(help_prg), *s = buf;
! 776: FILE *file;
! 777:
! 778: while (*s && *s != ' ') s++;
! 779: *s = 0; file = (FILE *) fopen(buf,"r");
! 780: if (file) { fclose(file); return 1; }
! 781: free(buf);
! 782: }
! 783: return 0;
! 784: }
! 785:
! 786: static int
! 787: compare_str(char **s1, char **s2) { return strcmp(*s1, *s2); }
! 788:
! 789: /* Print all elements of list in columns, pausing every nbli lines
! 790: * if nbli is non-zero.
! 791: * list is a NULL terminated list of function names
! 792: */
! 793: void
! 794: print_fun_list(char **list, int nbli)
! 795: {
! 796: long i=0, j=0, maxlen=0, nbcol,len, w = term_width();
! 797: char **l;
! 798:
! 799: while (list[i]) i++;
! 800: qsort (list, i, sizeof(char *), (QSCOMP)compare_str);
! 801:
! 802: for (l=list; *l; l++)
! 803: {
! 804: len = strlen(*l);
! 805: if (len > maxlen) maxlen=len;
! 806: }
! 807: maxlen++; nbcol= w / maxlen;
! 808: if (nbcol * maxlen == w) nbcol--;
! 809: if (!nbcol) nbcol = 1;
! 810:
! 811: pariputc('\n'); i=0;
! 812: for (l=list; *l; l++)
! 813: {
! 814: pariputs(*l); i++;
! 815: if (i >= nbcol)
! 816: {
! 817: i=0; pariputc('\n');
! 818: if (nbli && j++ > nbli) { j = 0; hit_return(); }
! 819: continue;
! 820: }
! 821: len = maxlen - strlen(*l);
! 822: while (len--) pariputc(' ');
! 823: }
! 824: if (i) pariputc('\n');
! 825: }
! 826:
! 827: #define LIST_LEN 1023
! 828: static void
! 829: commands(int n)
! 830: {
! 831: int hashpos, s = 0, olds = LIST_LEN;
! 832: entree *ep;
! 833: char **list = (char **) gpmalloc((olds+1)*sizeof(char *));
! 834:
! 835: for (hashpos = 0; hashpos < functions_tblsz; hashpos++)
! 836: for (ep = functions_hash[hashpos]; ep; ep = ep->next)
! 837: if ((n<0 && ep->menu) || ep->menu == n)
! 838: {
! 839: list[s++] = ep->name;
! 840: if (s >= olds)
! 841: {
! 842: int news = olds + (LIST_LEN + 1)*sizeof(char *);
! 843: list = (char**) gprealloc(list,news,olds);
! 844: olds = news;
! 845: }
! 846: }
! 847: list[s]=NULL; print_fun_list(list,term_height()-4); free(list);
! 848: }
! 849:
! 850: static void
! 851: print_user_fun(entree *ep)
! 852: {
! 853: gp_args *f= (gp_args*)ep->args;
! 854: GEN q = (GEN)ep->value, *arg = f->arg;
! 855: int i, narg;
! 856:
! 857:
! 858: q++; /* skip initial NULL */
! 859: pariputs(ep->name); pariputc('(');
! 860: narg = f->narg;
! 861: for (i=1; i<=narg; i++, arg++)
! 862: {
! 863: entree *ep = varentries[*q++];
! 864: pariputs(ep? ep->name:"#");
! 865: if (!gcmp0(*arg)) { pariputc('='); bruteall(*arg,'g',-1,1); }
! 866: if (i == narg) { arg++; break; }
! 867: pariputs(", ");
! 868: }
! 869: pariputs(") = ");
! 870: narg = f->nloc;
! 871: if (narg)
! 872: {
! 873: pariputs("local(");
! 874: for (i=1; i<=narg; i++, arg++)
! 875: {
! 876: entree *ep = varentries[*q++];
! 877: pariputs(ep? ep->name:"#");
! 878: if (!gcmp0(*arg)) { pariputc('='); bruteall(*arg,'g',-1,1); }
! 879: if (i == narg) break;
! 880: pariputs(", ");
! 881: }
! 882: pariputs("); ");
! 883: }
! 884: pariputs((char*)q);
! 885: }
! 886:
! 887: static void
! 888: print_user_member(entree *ep)
! 889: {
! 890: GEN q = (GEN)ep->value;
! 891: entree *ep2;
! 892:
! 893: q++; /* skip initial NULL */
! 894: ep2 = varentries[*q++];
! 895: pariputs(ep2? ep2->name:"#");
! 896: pariputsf(".%s = ", ep->name);
! 897: pariputs((char*)q);
! 898: }
! 899:
! 900: static void
! 901: user_fun()
! 902: {
! 903: entree *ep;
! 904: int hash;
! 905:
! 906: for (hash = 0; hash < functions_tblsz; hash++)
! 907: for (ep = functions_hash[hash]; ep; ep = ep->next)
! 908: if (EpVALENCE(ep) == EpUSER)
! 909: {
! 910: pariputc(LBRACE); print_user_fun(ep);
! 911: pariputc(RBRACE); pariputs("\n\n");
! 912: }
! 913: }
! 914:
! 915: static void
! 916: user_member()
! 917: {
! 918: entree *ep;
! 919: int hash;
! 920:
! 921: for (hash = 0; hash < functions_tblsz; hash++)
! 922: for (ep = members_hash[hash]; ep; ep = ep->next)
! 923: if (EpVALENCE(ep) == EpMEMBER)
! 924: {
! 925: pariputc(LBRACE); print_user_member(ep);
! 926: pariputc(RBRACE); pariputs("\n\n");
! 927: }
! 928: }
! 929:
! 930: static void
! 931: community()
! 932: {
! 933: pariputs("The standard distribution of GP/PARI includes a reference manual, a tutorial\n\
! 934: and a reference card and you should ask the person who installed PARI on\n\
! 935: your system where they can be found. You can also download them\n\
! 936: from the PARI WWW site http://hasse.mathematik.tu-muenchen.de/ntsw/pari/\n\
! 937: \n\
! 938: Three mailing lists are devoted to PARI:\n\
! 939: - pari-announce (moderated) to announce major version changes.\n\
! 940: - pari-dev for everything related to the development of PARI, including\n\
! 941: suggestions, technical questions, bug reports and patch submissions.\n\
! 942: - pari-users for everything else !\n\
! 943: To subscribe, send an empty message to <list name>-subscribe@list.cr.yp.to\n\
! 944: You can only send messages to these lists if you have subscribed !\n\
! 945: An archive is kept at the address\n\
! 946: http://hasse.mathematik.tu-muenchen.de/ntsw/pari/lists/archive\n\n\
! 947: In case you don't want to subscribe, you can reach the authors directly by\n\
! 948: email: pari@math.u-bordeaux.fr (answer not guaranteed).");
! 949: }
! 950:
! 951: static void
! 952: gentypes(void)
! 953: {
! 954: pariputs("List of the PARI types:\n\
! 955: t_INT : long integers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
! 956: t_REAL : long real numbers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
! 957: t_INTMOD : integermods [ code ] [ mod ] [ integer ]\n\
! 958: t_FRAC : irred. rationals [ code ] [ num. ] [ den. ]\n\
! 959: t_FRACN : rational numbers [ code ] [ num. ] [ den. ]\n\
! 960: t_COMPLEX: complex numbers [ code ] [ real ] [ imag ]\n\
! 961: t_PADIC : p-adic numbers [ cod1 ] [ cod2 ] [ p ] [ p^r ] [ int ]\n\
! 962: t_QUAD : quadratic numbers [ cod1 ] [ mod ] [ real ] [ imag ]\n\
! 963: t_POLMOD : poly mod [ code ] [ mod ] [ polynomial ]\n\
! 964: -------------------------------------------------------------\n\
! 965: t_POL : polynomials [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
! 966: t_SER : power series [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
! 967: t_RFRAC : irred. rat. func. [ code ] [ num. ] [ den. ]\n\
! 968: t_RFRACN : rational function [ code ] [ num. ] [ den. ]\n\
! 969: t_QFR : real qfb [ code ] [ a ] [ b ] [ c ] [ del ]\n\
! 970: t_QFI : imaginary qfb [ code ] [ a ] [ b ] [ c ]\n\
! 971: t_VEC : row vector [ code ] [ x_1 ] ... [ x_k ]\n\
! 972: t_COL : column vector [ code ] [ x_1 ] ... [ x_k ]\n\
! 973: t_MAT : matrix [ code ] [ col_1 ] ... [ col_k ]\n\
! 974: t_LIST : list [ code ] [ cod2 ] [ x_1 ] ... [ x_k ]\n\
! 975: t_STR : string [ code ] [ man_1 ] ... [ man_k ]\n\
! 976: \n");
! 977: }
! 978:
! 979: static void
! 980: menu_commands(void)
! 981: {
! 982: pariputs("Help topics:\n\
! 983: 0: list of user-defined identifiers (variable, alias, function)\n\
! 984: 1: Standard monadic or dyadic OPERATORS\n\
! 985: 2: CONVERSIONS and similar elementary functions\n\
! 986: 3: TRANSCENDENTAL functions\n\
! 987: 4: NUMBER THEORETICAL functions\n\
! 988: 5: Functions related to ELLIPTIC CURVES\n\
! 989: 6: Functions related to general NUMBER FIELDS\n\
! 990: 7: POLYNOMIALS and power series\n\
! 991: 8: Vectors, matrices, LINEAR ALGEBRA and sets\n\
! 992: 9: SUMS, products, integrals and similar functions\n\
! 993: 10: GRAPHIC functions\n\
! 994: 11: PROGRAMMING under GP\n\
! 995: 12: The PARI community\n\
! 996: \n\
! 997: Further help (list of relevant functions): ?n (1<=n<=11).\n\
! 998: Also:\n\
! 999: ? functionname (short on-line help)\n\
! 1000: ?\\ (keyboard shortcuts)\n\
! 1001: ?. (member functions)\n");
! 1002: if (has_ext_help()) pariputs("\
! 1003: Extended help looks available:\n\
! 1004: ?? (opens the full user's manual in a dvi previewer)\n\
! 1005: ?? tutorial (same with the GP tutorial)\n\
! 1006: ?? refcard (same with the GP reference card)\n\
! 1007: \n\
! 1008: ?? keyword (long help text about \"keyword\" from the user's manual)\n\
! 1009: ??? keyword (a propos: list of related functions).");
! 1010: }
! 1011:
! 1012: static void
! 1013: slash_commands(void)
! 1014: {
! 1015: pariputs("# : enable/disable timer\n\
! 1016: ## : print time for last result\n\
! 1017: \\\\ : comment up to end of line\n\
! 1018: \\a {n} : print result in raw format (readable by PARI)\n\
! 1019: \\b {n} : print result in beautified format\n\
! 1020: \\c : list all commands (same effect as ?*)\n\
! 1021: \\d : print all defaults\n\
! 1022: \\e {n} : enable/disable echo (set echo=n)\n\
! 1023: \\g {n} : set debugging level\n\
! 1024: \\gf{n} : set file debugging level\n\
! 1025: \\gm{n} : set memory debugging level\n\
! 1026: \\h {m-n}: hashtable information\n\
! 1027: \\l {f} : enable/disable logfile (set logfile=f)\n\
! 1028: \\m {n} : print result in prettymatrix format\n\
! 1029: \\p {n} : change real precision\n\
! 1030: \\ps{n} : change series precision\n\
! 1031: \\q : quit completely this GP session\n\
! 1032: \\r {f} : read in a file\n\
! 1033: \\s {n} : print stack information\n\
! 1034: \\t : print the list of PARI types\n\
! 1035: \\u : print the list of user-defined functions\n\
! 1036: \\um : print the list of user-defined member functions\n\
! 1037: \\v : print current version of GP\n\
! 1038: \\w {nf} : write to a file\n\
! 1039: \\x {n} : print complete inner structure of result\n\
! 1040: \\y {n} : disable/enable automatic simplification (set simplify=n)\n\
! 1041: \n\
! 1042: {f}=optional filename. {n}=optional integer\n");
! 1043: }
! 1044:
! 1045: static void
! 1046: member_commands(void)
! 1047: {
! 1048: pariputs("Member functions, followed by relevant objects\n\n\
! 1049: a1-a6, b2-b8, c4-c6 : coeff. of the curve. ell\n\
! 1050: area : area ell\n\
! 1051: bnf : big number field bnf, bnr\n\
! 1052: clgp : class group bnf, bnr\n\
! 1053: cyc : cyclic decomposition (SNF) clgp bnf, bnr\n\
! 1054: diff, codiff: different and codifferent nf, bnf, bnr\n\
! 1055: disc : discriminant ell, nf, bnf, bnr\n\
! 1056: e, f : inertia/residues degree prid\n\
! 1057: fu : fundamental units bnf, bnr\n\
! 1058: futu : [u,w] where u=unit group, w=torsion bnf, bnr\n\
! 1059: gen : generators prid, clgp bnf, bnr\n\
! 1060: j : j-invariant ell\n\
! 1061: mod : modulus\n\
! 1062: nf : number field bnf, bnr\n\
! 1063: no : number of elements clgp bnf, bnr\n\
! 1064: omega, eta: [omega1,omega2] and [eta1, eta2] ell\n\
! 1065: p : rational prime contained in prid prid\n\
! 1066: pol : defining polynomial nf, bnf, bnr\n\
! 1067: reg : regulator bnf, bnr\n\
! 1068: roots: roots ell nf, bnf, bnr\n\
! 1069: sign : signature nf, bnf, bnr\n\
! 1070: t2 : t2 matrix nf, bnf, bnr\n\
! 1071: tate : Tate's [u^2,u,q] ell\n\
! 1072: tu : torsion unit and its order bnf, bnr\n\
! 1073: tufu : [w,u] where u=unit group, w=torsion bnf, bnr\n\
! 1074: w : Mestre's w ell\n\
! 1075: zk : integral basis nf, bnf, bnr\n\
! 1076: zkst : structure of (Z_K/m)^* (valid for idealstar also) bnr\n");
! 1077: }
! 1078:
! 1079: #define MAX_LINE_LEN 255
! 1080: static void
! 1081: external_help(char *s, int num)
! 1082: {
! 1083: long nbli = term_height()-3, li = 0;
! 1084: char buf[MAX_LINE_LEN+1], *str, *opt = "", *ar = "";
! 1085: pariFILE *z;
! 1086: FILE *f;
! 1087:
! 1088: if (!help_prg) err(talker,"no external help program");
! 1089: str = gpmalloc(strlen(help_prg) + strlen(s) + 64);
! 1090: if (num < 0)
! 1091: opt = "-k";
! 1092: else if (s[strlen(s)-1] != '@')
! 1093: { ar = thestring; sprintf(ar,"@%d",num); }
! 1094: sprintf(str,"%s -fromgp %s %c%s%s%c",help_prg,opt, SHELL_Q,s,ar,SHELL_Q);
! 1095: z = try_pipe(str,0); f = z->file;
! 1096: free(str);
! 1097: while (fgets(buf,MAX_LINE_LEN,f))
! 1098: {
! 1099: if (!strncmp("ugly_kludge_done",buf,16)) break;
! 1100: buf[MAX_LINE_LEN]=0; pariputs(buf);
! 1101: if (++li > nbli) { hit_return(); li = 0; }
! 1102: }
! 1103: pari_fclose(z);
! 1104: }
! 1105:
! 1106: char *keyword_list[]={
! 1107: "operator",
! 1108: "user",
! 1109: "member",
! 1110: "integer",
! 1111: "real",
! 1112: "readline",
! 1113: "refcard",
! 1114: "tutorial",
! 1115: "nf",
! 1116: "bnf",
! 1117: "bnr",
! 1118: "ell",
! 1119: NULL
! 1120: };
! 1121:
! 1122: static int
! 1123: ok_external_help(char *s)
! 1124: {
! 1125: long n;
! 1126: if (!*s) return 1;
! 1127: if (!isalpha((int)*s)) return 3; /* operator or section number */
! 1128: if (!strncmp(s,"t_",2)) return 2; /* type name */
! 1129:
! 1130: for (n=0; keyword_list[n]; n++)
! 1131: if (!strcmp(s,keyword_list[n])) return 3;
! 1132: return 0;
! 1133: }
! 1134:
! 1135: /* don't mess readline display */
! 1136: static void
! 1137: aide_err(char *s1, char *s2, int flag)
! 1138: {
! 1139: if ((flag & h_RL) == 0) err(talker, "%s: %s", s1, s2);
! 1140: pariputsf("%s: %s\n", s1, s2);
! 1141: }
! 1142:
! 1143: static void
! 1144: aide0(char *s, int flag)
! 1145: {
! 1146: long n, long_help = flag & h_LONG;
! 1147: entree *ep,*ep1;
! 1148:
! 1149: s = get_sep(s);
! 1150: if (isdigit((int)*s))
! 1151: {
! 1152: n=atoi(s);
! 1153: if (n == 12) { community(); return; }
! 1154: if (n<0 || n > 12)
! 1155: err(talker2,"no such section in help: ?",s,s);
! 1156: if (long_help) external_help(s,3); else commands(n);
! 1157: return;
! 1158: }
! 1159: if (flag & h_APROPOS) { external_help(s,-1); return; }
! 1160: if (long_help && (n = ok_external_help(s))) { external_help(s,n); return; }
! 1161: switch (*s)
! 1162: {
! 1163: case '*' : commands(-1); return;
! 1164: case '\0': menu_commands(); return;
! 1165: case '\\': slash_commands(); return;
! 1166: case '.' : member_commands(); return;
! 1167: }
! 1168: ep = is_entry(s);
! 1169: if (!ep)
! 1170: {
! 1171: n = whatnow(s,1);
! 1172: if (n) err(obsoler,s,s, s,n);
! 1173: if (long_help)
! 1174: {
! 1175: n = setdefault(s,"",d_EXISTS) == gun? 2: 3;
! 1176: external_help(s,n);
! 1177: }
! 1178: else
! 1179: aide_err(s,"unknown identifier",flag);
! 1180: return;
! 1181: }
! 1182:
! 1183: ep1 = ep; ep = do_alias(ep);
! 1184: if (ep1 != ep) pariputsf("%s is aliased to:\n\n",s);
! 1185:
! 1186: switch(EpVALENCE(ep))
! 1187: {
! 1188: case EpUSER:
! 1189: print_user_fun(ep); if (!ep->help) return;
! 1190: pariputs("\n\n"); long_help=0; break;
! 1191:
! 1192: case EpGVAR:
! 1193: case EpVAR:
! 1194: if (!ep->help) { aide_err(s, "user defined variable",flag); return; }
! 1195: long_help=0; break;
! 1196:
! 1197: case EpINSTALL:
! 1198: if (!ep->help) { aide_err(s, "installed function",flag); return; }
! 1199: long_help=0; break;
! 1200: }
! 1201: if (long_help) { external_help(ep->name,3); return; }
! 1202: if (ep->help) { print_text(ep->help); return; }
! 1203:
! 1204: err(bugparier,"aide (no help found)");
! 1205: }
! 1206:
! 1207: void
! 1208: aide(char *s, int flag)
! 1209: {
! 1210: if ((flag & h_RL) == 0)
! 1211: {
! 1212: if (*s == '?') { flag |= h_LONG; s++; }
! 1213: if (*s == '?') { flag |= h_APROPOS; s++; }
! 1214: }
! 1215: term_color(c_HELP); aide0(s,flag); term_color(c_NONE);
! 1216: if ((flag & h_RL) == 0) pariputc('\n');
! 1217: }
! 1218:
! 1219: /********************************************************************/
! 1220: /** **/
! 1221: /** METACOMMANDS **/
! 1222: /** **/
! 1223: /********************************************************************/
! 1224:
! 1225: static void
! 1226: print_entree(entree *ep, long hash)
! 1227: {
! 1228: pariputsf(" %s ",ep->name); pariputsf(VOIR_STRING1,(ulong)ep);
! 1229: pariputsf(":\n hash = %3ld, valence = %3ld, menu = %2ld, code = %s\n",
! 1230: hash, ep->valence, ep->menu, ep->code? ep->code: "NULL");
! 1231: if (ep->next)
! 1232: {
! 1233: pariputsf(" next = %s ",(ep->next)->name);
! 1234: pariputsf(VOIR_STRING1,(ulong)(ep->next));
! 1235: }
! 1236: pariputs("\n");
! 1237: }
! 1238:
! 1239: static void
! 1240: print_hash_list(char *s)
! 1241: {
! 1242: long m,n;
! 1243: entree *ep;
! 1244:
! 1245: if (isalpha((int)*s))
! 1246: {
! 1247: ep = is_entry_intern(s,functions_hash,&n);
! 1248: if (!ep) err(talker,"no such function");
! 1249: print_entree(ep,n); return;
! 1250: }
! 1251: if (isdigit((int)*s) || *s == '$')
! 1252: {
! 1253: m = functions_tblsz-1; n = atol(s);
! 1254: if (*s=='$') n = m;
! 1255: if (m<n) err(talker,"invalid range in print_entree");
! 1256: while (isdigit((int)*s)) s++;
! 1257:
! 1258: if (*s++ != '-') m = n;
! 1259: else
! 1260: {
! 1261: if (*s !='$') m = min(atol(s),m);
! 1262: if (m<n) err(talker,"invalid range in print_entree");
! 1263: }
! 1264:
! 1265: for(; n<=m; n++)
! 1266: {
! 1267: pariputsf("*** hashcode = %ld\n",n);
! 1268: for (ep=functions_hash[n]; ep; ep=ep->next)
! 1269: print_entree(ep,n);
! 1270: }
! 1271: return;
! 1272: }
! 1273: if (*s=='-')
! 1274: {
! 1275: for (n=0; n<functions_tblsz; n++)
! 1276: {
! 1277: m=0;
! 1278: for (ep=functions_hash[n]; ep; ep=ep->next) m++;
! 1279: pariputsf("%3ld:%3ld ",n,m);
! 1280: if (n%9 == 8) pariputc('\n');
! 1281: }
! 1282: pariputc('\n'); return;
! 1283: }
! 1284: for (n=0; n<functions_tblsz; n++)
! 1285: for (ep=functions_hash[n]; ep; ep=ep->next)
! 1286: print_entree(ep,n);
! 1287: }
! 1288:
! 1289:
! 1290: static void
! 1291: center(char *s)
! 1292: {
! 1293: long i, pad = term_width() - strlen(s);
! 1294: char *u = thestring;
! 1295:
! 1296: if (pad<0) pad=0; else pad >>= 1;
! 1297: for (i=0; i<pad; i++) *u++ = ' ';
! 1298: while (*s) *u++ = *s++;
! 1299: *u++='\n'; *u=0; pariputs(thestring);
! 1300: }
! 1301:
! 1302: static char *
! 1303: what_readline()
! 1304: {
! 1305: #ifdef READLINE
! 1306: return "v"READLINE" enabled";
! 1307: #else
! 1308: return "disabled";
! 1309: #endif
! 1310: }
! 1311:
! 1312: static void
! 1313: print_version()
! 1314: {
! 1315: char buf[64];
! 1316:
! 1317: center(PARIVERSION); center(PARIINFO);
! 1318: sprintf(buf,"(readline %s, extended help%s available)", what_readline(),
! 1319: has_ext_help()? "": " not");
! 1320: center(buf);
! 1321: }
! 1322:
! 1323: static void
! 1324: gp_head()
! 1325: {
! 1326: print_version(); pariputs("\n");
! 1327: center("Copyright (C) 1989-1999 by");
! 1328: center("C. Batut, K. Belabas, D. Bernardi, H. Cohen and M. Olivier.");
! 1329: pariputs("\n\
! 1330: Type ? for help, \\q to quit.\n\
! 1331: Type ?12 for how to get moral (and possibly technical) support.\n\n");
! 1332: sd_realprecision ("",d_ACKNOWLEDGE);
! 1333: sd_seriesprecision("",d_ACKNOWLEDGE);
! 1334: sd_format ("",d_ACKNOWLEDGE);
! 1335: pariputsf("\nparisize = %ld, primelimit = %ld\n", parisize, primelimit);
! 1336: }
! 1337:
! 1338: void
! 1339: gp_quit()
! 1340: {
! 1341: free_graph(); freeall();
! 1342: while (bufindex) free((void *)buflist[bufindex--]);
! 1343: #ifdef WINCE
! 1344: #else
! 1345: if (INIT_SIG)
! 1346: {
! 1347: #ifdef SIGBUS
! 1348: signal(SIGBUS,SIG_DFL);
! 1349: #endif
! 1350: signal(SIGSEGV,SIG_DFL);
! 1351: signal(SIGINT,SIG_DFL);
! 1352: #ifdef SIGBREAK
! 1353: signal(SIGBREAK,SIG_DFL);
! 1354: #endif
! 1355: }
! 1356: #endif
! 1357: term_color(c_NONE);
! 1358: pariputs_opt("Good bye!\n"); exit(0);
! 1359: }
! 1360:
! 1361: /* history management function:
! 1362: * flag < 0, called from freeall()
! 1363: * flag = 0, called from %num in anal.c:truc()
! 1364: * flag > 0, called from %` in anal.c:truc(), p > 0
! 1365: */
! 1366: static GEN
! 1367: gp_history(long p, long flag, char *old, char *entrypoint)
! 1368: {
! 1369: int er1 = 0;
! 1370: if (flag < 0) { free((void *)hist); return NULL; }
! 1371: if (!tglobal) er1 = 1;
! 1372: if (flag)
! 1373: {
! 1374: p = tglobal - p;
! 1375: if (p <= 0) er1 = 1;
! 1376: }
! 1377: else if (p > tglobal)
! 1378: err(talker2,"I can't see into the future",old,entrypoint);
! 1379: if (!p) p = tglobal;
! 1380: if (tglobal - p >= histsize) er1 = 1;
! 1381: p = (p-1) % histsize;
! 1382: if (er1 || !hist[p])
! 1383: err(talker2,"I can't remember before the big bang",old,entrypoint);
! 1384: return hist[p];
! 1385: }
! 1386:
! 1387: static void
! 1388: escape(char *tch)
! 1389: {
! 1390: char *s, c;
! 1391:
! 1392: if (compatible != NONE)
! 1393: {
! 1394: s = tch;
! 1395: while (*s)
! 1396: if (*s++ == '=')
! 1397: {
! 1398: GEN (*f)(char*, int) = NULL;
! 1399: int len = (s-tch) - 1;
! 1400:
! 1401: if (!strncmp(tch,"precision",len)) f = sd_realprecision;
! 1402: else if (!strncmp(tch,"serieslength",len)) f = sd_seriesprecision;
! 1403: else if (!strncmp(tch,"format",len)) f = sd_format;
! 1404: else if (!strncmp(tch,"prompt",len)) f = sd_prompt;
! 1405: if (f) { f(get_sep(s), d_ACKNOWLEDGE); return; }
! 1406: break;
! 1407: }
! 1408: }
! 1409: s = tch;
! 1410: switch ((c = *s++))
! 1411: {
! 1412: case 'w': case 'x': case 'a': case 'b': case 'm': /* history things */
! 1413: {
! 1414: long d;
! 1415: GEN x;
! 1416: if (c != 'w' && c != 'x') d = get_int(s,0);
! 1417: else
! 1418: {
! 1419: d = atol(s); if (*s == '-') s++;
! 1420: while (isdigit((int)*s)) s++;
! 1421: }
! 1422: x = gp_history(d, 0, tch+1,tch-1);
! 1423: switch (c)
! 1424: {
! 1425: case 'a': brute (x, fmt.format, -1); break;
! 1426: case 'm': matbrute(x, fmt.format, -1); break;
! 1427: case 'b': sor (x, fmt.format, -1, fmt.field); break;
! 1428: case 'x': voir(x, get_int(s, -1)); return;
! 1429: case 'w':
! 1430: {
! 1431: GEN g[2]; g[0] = x; g[1] = NULL;
! 1432: s = get_sep(s); if (!*s) s = current_logfile;
! 1433: write0(s, g, f_RAW); return;
! 1434: }
! 1435: }
! 1436: pariputc('\n'); return;
! 1437: }
! 1438:
! 1439: case 'c': commands(-1); break;
! 1440: case 'd': help_default(); break;
! 1441: case 'e':
! 1442: s = get_sep(s);
! 1443: if (!*s) s = pariecho?"0":"1";
! 1444: sd_echo(s,d_ACKNOWLEDGE); break;
! 1445: case 'g':
! 1446: switch (*s)
! 1447: {
! 1448: case 'm': sd_debugmem(++s,d_ACKNOWLEDGE); break;
! 1449: case 'f': sd_debugfiles(++s,d_ACKNOWLEDGE); break;
! 1450: default : sd_debug(s,d_ACKNOWLEDGE); break;
! 1451: }
! 1452: break;
! 1453: case 'h': print_hash_list(s); break;
! 1454: case 'l':
! 1455: s = get_sep(s);
! 1456: if (*s)
! 1457: {
! 1458: sd_logfile(s,d_ACKNOWLEDGE);
! 1459: if (logfile) break;
! 1460: }
! 1461: sd_log(logfile?"0":"1",d_ACKNOWLEDGE);
! 1462: break;
! 1463: case 'p':
! 1464: switch (*s)
! 1465: {
! 1466: case 's': sd_seriesprecision(++s,d_ACKNOWLEDGE); break;
! 1467: default : sd_realprecision(s,d_ACKNOWLEDGE); break;
! 1468: }
! 1469: break;
! 1470: case 'q': gp_quit(); break;
! 1471: case 'r': switchin(get_sep(s)); break;
! 1472: case 's': etatpile(0); break;
! 1473: case 't': gentypes(); break;
! 1474: case 'u':
! 1475: switch (*s)
! 1476: {
! 1477: case 'm': user_member(); break;
! 1478: default: user_fun();
! 1479: }
! 1480: break;
! 1481: case 'v': print_version(); break;
! 1482: case 'y':
! 1483: s = get_sep(s);
! 1484: if (!*s) s = simplifyflag?"0":"1";
! 1485: sd_simplify(s,d_ACKNOWLEDGE); break;
! 1486: default: err(caracer1,tch-1,tch-2);
! 1487: }
! 1488: }
! 1489:
! 1490: /********************************************************************/
! 1491: /* */
! 1492: /* GPRC */
! 1493: /* */
! 1494: /********************************************************************/
! 1495: #if defined(UNIX) || defined(__EMX__)
! 1496: # include <pwd.h>
! 1497: #endif
! 1498:
! 1499: static int
! 1500: get_preproc_value(char *s)
! 1501: {
! 1502: if (!strncmp(s,"EMACS",5)) return under_emacs;
! 1503: if (!strncmp(s,"READL",5))
! 1504: {
! 1505: #ifdef READLINE
! 1506: return 1;
! 1507: #else
! 1508: return 0;
! 1509: #endif
! 1510: }
! 1511: return -1;
! 1512: }
! 1513:
! 1514: /* return $HOME or the closest we can find */
! 1515: static char *
! 1516: get_home(int *free_it)
! 1517: {
! 1518: #ifdef WINCE
! 1519: return ".";
! 1520: #else
! 1521: #ifndef macintosh /* getenv() for Mac ? */
! 1522: char *drv, *pth = getenv("HOME");
! 1523: if (pth) return pth;
! 1524: if ((drv = getenv("HOMEDRIVE"))
! 1525: && (pth = getenv("HOMEPATH")))
! 1526: { /* looks like WinNT */
! 1527: char *buf = gpmalloc(strlen(pth) + strlen(drv) + 1);
! 1528: sprintf(buf, "%s%s",drv,pth);
! 1529: *free_it = 1; return buf;
! 1530: }
! 1531: #endif
! 1532: #endif
! 1533: #if defined(__EMX__) || defined(UNIX)
! 1534: {
! 1535: struct passwd *p = getpwuid(geteuid());
! 1536: if (p) return p->pw_dir;
! 1537: }
! 1538: #endif
! 1539: return ".";
! 1540: }
! 1541:
! 1542: static FILE *
! 1543: gprc_chk(char *s)
! 1544: {
! 1545: FILE *f = fopen(s, "r");
! 1546: if (f && !quiet_mode) fprintferr("Reading GPRC: %s ...", s);
! 1547: return f;
! 1548: }
! 1549:
! 1550: /* Look for [._]gprc: $GPRC, then in $HOME, /, C:/ */
! 1551: static FILE *
! 1552: gprc_get()
! 1553: {
! 1554: FILE *f = NULL;
! 1555: char *str, *s, c;
! 1556: long l;
! 1557: #ifdef macintosh
! 1558: f = gprc_chk("gprc");
! 1559: #else
! 1560: #ifdef WINCE
! 1561: s = NULL;
! 1562: #else
! 1563: s = getenv("GPRC");
! 1564: #endif
! 1565: if (s) f = gprc_chk(s);
! 1566: if (!f)
! 1567: {
! 1568: int free_it = 0;
! 1569: s = get_home(&free_it); l = strlen(s); c = s[l-1];
! 1570: str = strcpy(gpmalloc(l+7), s);
! 1571: if (free_it) free(s);
! 1572: s = str + l;
! 1573: if (c != '/' && c != '\\') *s++ = '/';
! 1574: #ifdef UNIX
! 1575: *s = '.'; /* .gprc */
! 1576: #else
! 1577: *s = '_'; /* _gprc */
! 1578: #endif
! 1579: strcpy(s+1, "gprc");
! 1580: f = gprc_chk(str); /* in $HOME */
! 1581: if (!f) f = gprc_chk(s); /* in . */
! 1582: if (!f) f = gprc_chk("/etc/gprc");
! 1583: if (!f) f = gprc_chk("C:/_gprc");
! 1584: free(str);
! 1585: }
! 1586: #endif
! 1587: return f;
! 1588: }
! 1589:
! 1590: static int
! 1591: init_brace(char *s)
! 1592: {
! 1593: while (isspace((int)*s)) s++;
! 1594: if (*s == LBRACE) { *s=' '; return 1; }
! 1595: return 0;
! 1596: }
! 1597:
! 1598: /* return 1 if we deleted a '{' */
! 1599: static int
! 1600: init_filtre(char *s)
! 1601: {
! 1602: if (filtre(s, f_INIT)) return 0; /* in comment */
! 1603: return init_brace(s);
! 1604: }
! 1605:
! 1606: static void
! 1607: fix_buffer(long newlbuf, char **ptbuf, long *ptlbuf)
! 1608: {
! 1609: buflist[bufindex] = *ptbuf = gprealloc(*ptbuf,newlbuf,*ptlbuf);
! 1610: *ptlbuf = paribufsize = newlbuf;
! 1611: }
! 1612:
! 1613: /* prompt = NULL --> from gprc */
! 1614: static int
! 1615: get_line_from_file(FILE *file, char **ptbuf, long *ptlbuf, char *prompt)
! 1616: {
! 1617: int f_flag = prompt? f_REG | f_KEEPCASE: f_REG;
! 1618: int wait_for_brace;
! 1619: long len = *ptlbuf;
! 1620: char *s = *ptbuf;
! 1621:
! 1622: if (!fgets(s, len, file)) return 0;
! 1623: wait_for_brace = init_filtre(s);
! 1624: for(;;)
! 1625: {
! 1626: int read_more = (s[strlen(s)-1] != '\n');
! 1627: char *end = filtre(s, f_flag);
! 1628: if (*s)
! 1629: {
! 1630: if (read_more) s = end;
! 1631: else if (end[-1] == '\\')
! 1632: {
! 1633: if (*s=='?') break;
! 1634: s = end-1;
! 1635: }
! 1636: else if (end[-1] == '='&& *s != '?')
! 1637: {
! 1638: s = end;
! 1639: }
! 1640: else
! 1641: {
! 1642: if (!wait_for_brace) break;
! 1643: if (end[-1] == RBRACE) {end[-1]=0; break;}
! 1644: s = end;
! 1645: }
! 1646: len = *ptlbuf - (s - *ptbuf);
! 1647: if (len < 512)
! 1648: {
! 1649: long n = *ptlbuf << 1, l = s - *ptbuf;
! 1650: len += *ptlbuf;
! 1651: fix_buffer(n, ptbuf, ptlbuf);
! 1652: s = *ptbuf + l;
! 1653: }
! 1654: }
! 1655: if (!fgets(s, len, file)) break;
! 1656: if (!read_more && !wait_for_brace)
! 1657: wait_for_brace = init_filtre(s);
! 1658: }
! 1659: if (prompt && *ptbuf)
! 1660: {
! 1661: if (pariecho) { pariputs(prompt); pariputs(*ptbuf); pariputc('\n'); }
! 1662: else if (logfile) fprintf(logfile, "%s%s\n",prompt,*ptbuf);
! 1663: pariflush();
! 1664: }
! 1665: return 1;
! 1666: }
! 1667:
! 1668: #define err_gprc(s,t,u) { fprintferr("\n"); err(talker2,s,t,u); }
! 1669:
! 1670: static char **
! 1671: gp_initrc()
! 1672: {
! 1673: char **flist, *buf, *s,*s1,*s2;
! 1674: FILE *file = gprc_get();
! 1675: long fnum = 4, find = 0, *ptlbuf = &paribufsize;
! 1676:
! 1677: if (!file) return NULL;
! 1678: flist = (char **) gpmalloc(fnum * sizeof(char*));
! 1679: buflist[++bufindex] = buf = gpmalloc(*ptlbuf);
! 1680: for(;;)
! 1681: {
! 1682: if (! get_line_from_file(file, &buf, ptlbuf, NULL))
! 1683: {
! 1684: if (!quiet_mode) fprintferr("Done.\n\n");
! 1685: fclose(file); free(buflist[bufindex--]);
! 1686: flist[find] = NULL; return flist;
! 1687: }
! 1688: for (s = buf; *s; )
! 1689: {
! 1690: s1 = s; if (get_sep2(s)) s++;
! 1691: s += strlen(s1); /* point to next expr */
! 1692: if (*s1 == '#')
! 1693: { /* preprocessor directive */
! 1694: int z, NOT = 0;
! 1695: s1++;
! 1696: if (strncmp(s1,"if",2)) err_gprc("unknown directive",s1,buf);
! 1697: s1 += 2;
! 1698: if (!strncmp(s1,"not",3)) { NOT = !NOT; s1 += 3; }
! 1699: if (*s1 == '!') { NOT = !NOT; s1++; }
! 1700: z = get_preproc_value(s1);
! 1701: if (z < 0) err_gprc("unknown preprocessor variable",s1,buf);
! 1702: if (NOT) z = !z;
! 1703: if (!z) continue;
! 1704: s1 += 5;
! 1705: }
! 1706: if (!strncmp(s1,"read",4))
! 1707: { /* read file */
! 1708: s1 += 4;
! 1709: if (find == fnum-1)
! 1710: {
! 1711: long n = fnum << 1;
! 1712: flist = (char**)gprealloc(flist, n*sizeof(char*),
! 1713: fnum*sizeof(char*));
! 1714: fnum = n;
! 1715: }
! 1716: flist[find++] = s2 = gpmalloc(strlen(s1) + 1);
! 1717: if (*s1 == '"') (void)readstring(s1, s2);
! 1718: else strcpy(s2,s1);
! 1719: }
! 1720: else
! 1721: { /* set default */
! 1722: s2 = s1; while (*s2 && *s2 != '=') s2++;
! 1723: if (*s2 != '=') err_gprc("missing '='",s2,buf);
! 1724: *s2++ = 0;
! 1725: if (*s2 == '"') (void)readstring(s2, s2);
! 1726: setdefault(s1,s2,d_INITRC);
! 1727: }
! 1728: }
! 1729: }
! 1730: }
! 1731:
! 1732: /********************************************************************/
! 1733: /* */
! 1734: /* GP MAIN LOOP */
! 1735: /* */
! 1736: /********************************************************************/
! 1737: /* flag:
! 1738: * ti_NOPRINT don't print
! 1739: * ti_REGULAR print elapsed time (chrono = 1)
! 1740: * ti_LAST print last elapsed time (##)
! 1741: * ti_INTERRUPT received a SIGINT
! 1742: */
! 1743: static char *
! 1744: do_time(long flag)
! 1745: {
! 1746: static long last = 0;
! 1747: long delay = (flag == ti_LAST)? last: gptimer();
! 1748: char *s;
! 1749:
! 1750: last = delay;
! 1751: switch(flag)
! 1752: {
! 1753: case ti_NOPRINT: return NULL;
! 1754: case ti_REGULAR: s = "time = "; break;
! 1755: case ti_INTERRUPT: s = "user interrupt after "; break;
! 1756: case ti_LAST: s = " *** last result computed in "; break;
! 1757: }
! 1758: strcpy(thestring,s); s=thestring+strlen(s);
! 1759: strcpy(s, term_get_color(c_TIME)); s+=strlen(s);
! 1760: if (delay >= 3600000)
! 1761: {
! 1762: sprintf(s, "%ldh, ", delay / 3600000); s+=strlen(s);
! 1763: delay %= 3600000;
! 1764: }
! 1765: if (delay >= 60000)
! 1766: {
! 1767: sprintf(s, "%ldmn, ", delay / 60000); s+=strlen(s);
! 1768: delay %= 60000;
! 1769: }
! 1770: if (delay >= 1000)
! 1771: {
! 1772: sprintf(s, "%ld,", delay / 1000); s+=strlen(s);
! 1773: delay %= 1000;
! 1774: if (delay < 100)
! 1775: {
! 1776: sprintf(s, "%s", (delay<10)? "00": "0");
! 1777: s+=strlen(s);
! 1778: }
! 1779: }
! 1780: sprintf(s, "%ld ms", delay); s+=strlen(s);
! 1781: strcpy(s, term_get_color(c_NONE));
! 1782: if (flag != ti_INTERRUPT) { s+=strlen(s); *s++='.'; *s++='\n'; *s=0; }
! 1783: return thestring;
! 1784: }
! 1785:
! 1786: #ifndef WINCE
! 1787: static void
! 1788: gp_sighandler(int sig)
! 1789: {
! 1790: char *msg;
! 1791: switch(sig)
! 1792: {
! 1793: case SIGINT:
! 1794: #ifdef _WIN32
! 1795: # ifdef SIGBREAK
! 1796: case SIGBREAK:
! 1797: # endif
! 1798: if (++win32ctrlc >= 5) _exit(3);
! 1799: signal(sig,gp_sighandler);
! 1800: return;
! 1801: #endif
! 1802: msg = do_time(ti_INTERRUPT);
! 1803: break;
! 1804:
! 1805: case SIGSEGV:
! 1806: msg="segmentation fault: bug in GP (please report)";
! 1807: break;
! 1808:
! 1809: #ifdef SIGBUS
! 1810: case SIGBUS:
! 1811: msg="bus error: bug in GP (please report)";
! 1812: break;
! 1813: #endif
! 1814: default:
! 1815: msg="bug in signal handling (please report)";
! 1816: }
! 1817: signal(sig,gp_sighandler);
! 1818: err(talker,msg);
! 1819: }
! 1820: #endif
! 1821: static void
! 1822: brace_color(char *s, int c)
! 1823: {
! 1824: if (gp_colors[c] == c_NONE) return;
! 1825: #ifdef RL_PROMPT_START_IGNORE
! 1826: *s++ = RL_PROMPT_START_IGNORE;
! 1827: #endif
! 1828: strcpy(s, term_get_color(c));
! 1829: #ifdef RL_PROMPT_START_IGNORE
! 1830: s+=strlen(s);
! 1831: *s++ = RL_PROMPT_END_IGNORE; *s = 0;
! 1832: #endif
! 1833: }
! 1834:
! 1835: static char *
! 1836: do_prompt()
! 1837: {
! 1838: static char buf[MAX_PROMPT_LEN + 24]; /* + room for color codes */
! 1839: char *s = buf;
! 1840:
! 1841: *s = 0;
! 1842: /* escape sequences bug readline, so use special bracing (if available) */
! 1843: brace_color(s, c_PROMPT);
! 1844: s += strlen(s);
! 1845: if (filtre(s, f_COMMENT))
! 1846: strcpy(s, COMMENTPROMPT);
! 1847: else
! 1848: do_strftime(prompt,s);
! 1849: s += strlen(s);
! 1850: brace_color(s, c_INPUT); return buf;
! 1851: }
! 1852:
! 1853: static int
! 1854: read_line(char *promptbuf, char **ptbuf, long *ptlbuf)
! 1855: {
! 1856: if (infile == stdin /* interactive use */
! 1857: #if defined(UNIX) || defined(__EMX__)
! 1858: && (under_emacs || isatty(fileno(stdin)))
! 1859: #endif
! 1860: )
! 1861: {
! 1862: #ifdef READLINE
! 1863: static char *previous_hist = NULL;
! 1864: char *rlbuffer = readline(promptbuf), *s = *ptbuf;
! 1865: int wait_for_brace, wait_for_input;
! 1866:
! 1867: if (!rlbuffer) { pariputs("\n"); return 0; } /* EOF */
! 1868: wait_for_input = wait_for_brace = init_filtre(rlbuffer);
! 1869: for(;;)
! 1870: {
! 1871: long len = s - *ptbuf;
! 1872: char *end = filtre(rlbuffer, f_READL);
! 1873: long l = end - rlbuffer;
! 1874:
! 1875: if (len + l > *ptlbuf)
! 1876: {
! 1877: fix_buffer(len+l+1, ptbuf, ptlbuf);
! 1878: s = *ptbuf + len;
! 1879: }
! 1880: strcpy(s,rlbuffer); free(rlbuffer);
! 1881: if (!*s) { if (!wait_for_input) break; }
! 1882: else
! 1883: {
! 1884: s += l-1; /* *s = last input char */
! 1885: if (wait_for_brace && *s == RBRACE) {*s=0; break;}
! 1886: if (*s == '\\')
! 1887: {
! 1888: if (*rlbuffer == '?') break;
! 1889: }
! 1890: else if (*s == '=' && s[1-l] != '?')
! 1891: {
! 1892: wait_for_input = 1; s++;
! 1893: }
! 1894: else
! 1895: {
! 1896: if (!wait_for_brace) break;
! 1897: s++;
! 1898: }
! 1899: }
! 1900: /* read continuation line */
! 1901: if (!(rlbuffer = readline(""))) break;
! 1902: if (wait_for_input && !wait_for_brace)
! 1903: wait_for_brace = init_brace(rlbuffer);
! 1904: }
! 1905: /* bug in readline 2.0: need to unblock ^C */
! 1906: # ifdef USE_SIGRELSE
! 1907: sigrelse(SIGINT);
! 1908: # elif USE_SIGSETMASK
! 1909: sigsetmask(0);
! 1910: # endif
! 1911: s = *ptbuf;
! 1912: if (*s)
! 1913: {
! 1914: /* update history (don't add the same entry twice) */
! 1915: if (!previous_hist || strcmp(s,previous_hist))
! 1916: {
! 1917: if (previous_hist) free(previous_hist);
! 1918: previous_hist = pari_strdup(s); add_history(s);
! 1919: }
! 1920: /* update logfile */
! 1921: if (logfile) fprintf(logfile, "%s%s\n",promptbuf,s);
! 1922: }
! 1923: return 1;
! 1924: #else
! 1925: pariputs(promptbuf);
! 1926: #endif /* defined(READLINE) */
! 1927: }
! 1928: else promptbuf = DFT_PROMPT;
! 1929: return get_line_from_file(infile, ptbuf, ptlbuf, promptbuf);
! 1930: }
! 1931:
! 1932: static void
! 1933: chron(char *s)
! 1934: {
! 1935: if (*s)
! 1936: {
! 1937: char *old = s-1;
! 1938: if (*s == '#') { pariputs(do_time(ti_LAST)); s++; }
! 1939: if (*s) err(caracer1,s,old);
! 1940: }
! 1941: else { chrono = 1-chrono; sd_timer("",d_ACKNOWLEDGE); }
! 1942: }
! 1943:
! 1944: /* bufindex != 0: we are doing an immediate read (with read, extern...) */
! 1945: static GEN
! 1946: gp_main_loop()
! 1947: {
! 1948: long av, i,j, lbuf = paribufsize;
! 1949: char *buf, *promptbuf = prompt;
! 1950: GEN z = gnil;
! 1951:
! 1952: if (bufindex == MAX_BUFFER) err(talker,"too many nested files");
! 1953: buflist[++bufindex] = buf = (char *) gpmalloc(lbuf);
! 1954: for(;;)
! 1955: {
! 1956: if (! bufindex)
! 1957: {
! 1958: static long tloc, outtyp;
! 1959: tloc = tglobal; outtyp = prettyp; recover(0);
! 1960: if (setjmp(environnement))
! 1961: {
! 1962: avma = top; parisize = top - bot;
! 1963: j = tglobal - tloc; i = (tglobal-1)%histsize;
! 1964: while (j)
! 1965: {
! 1966: gunclone(hist[i]); hist[i]=NULL;
! 1967: if (!i) i = histsize;
! 1968: i--; j--;
! 1969: }
! 1970: tglobal = tloc; prettyp = outtyp;
! 1971: while (bufindex) free((void *)buflist[bufindex--]);
! 1972: killallfiles(0);
! 1973: }
! 1974: }
! 1975: setjmp(local_environnement[bufindex]);
! 1976: added_newline = 1;
! 1977: if (paribufsize != lbuf)
! 1978: fix_buffer(paribufsize, &buf, &lbuf);
! 1979:
! 1980: for(;;)
! 1981: {
! 1982: if (! test_mode) promptbuf = do_prompt();
! 1983: if (! read_line(promptbuf, &buf, &lbuf))
! 1984: {
! 1985: #ifdef _WIN32
! 1986: Sleep(10); if (win32ctrlc) dowin32ctrlc();
! 1987: #endif
! 1988: if (popinfile()) gp_quit();
! 1989: if (bufindex) { free(buflist[bufindex--]); return z; }
! 1990: }
! 1991: else switch(*buf)
! 1992: {
! 1993: case '?': aide(buf+1, h_REGULAR); break;
! 1994: case '#': chron(buf+1); break;
! 1995: case '\\': escape(buf+1); break;
! 1996: case '\0': break;
! 1997: default: goto WORK;
! 1998: }
! 1999: }
! 2000: WORK:
! 2001: if (! bufindex)
! 2002: {
! 2003: char c = buf[strlen(buf) - 1];
! 2004: gpsilent = separe(c);
! 2005: }
! 2006: if (bufindex == 0) (void)gptimer();
! 2007: av = avma;
! 2008: z = readseq(buf, strictmatch);
! 2009: if (!added_newline) pariputc('\n'); /* last output was print1() */
! 2010: if (bufindex) continue;
! 2011: if (chrono) pariputs(do_time(ti_REGULAR)); else do_time(ti_NOPRINT);
! 2012: if (z == gnil) continue;
! 2013:
! 2014: if (simplifyflag) z = simplify(z);
! 2015: i = tglobal % histsize; tglobal++;
! 2016: if (hist[i]) gunclone(hist[i]);
! 2017: hist[i] = z = gclone(z); avma = av;
! 2018: if (gpsilent) continue;
! 2019:
! 2020: if (test_mode) { init80(0); gp_output(z); }
! 2021: else
! 2022: {
! 2023: PariOUT *old = pariOut;
! 2024: if (DEBUGLEVEL > 4) fprintferr("prec = [%ld, %ld]\n", prec,precdl);
! 2025: term_color(c_HIST);
! 2026: sprintf(thestring, "%%%ld = ",tglobal);
! 2027: pariputs_opt(thestring);
! 2028: term_color(c_OUTPUT);
! 2029: init_lim_lines(thestring,lim_lines);
! 2030: gp_output(z); pariOut=old;
! 2031: term_color(c_NONE);
! 2032: }
! 2033: pariputc('\n'); pariflush();
! 2034: }
! 2035: }
! 2036:
! 2037: GEN
! 2038: read0(char *s)
! 2039: {
! 2040: switchin(s);
! 2041: return gp_main_loop();
! 2042: }
! 2043:
! 2044: static void
! 2045: check_secure(char *s)
! 2046: {
! 2047: if (secure)
! 2048: err(talker, "secure mode: system commands not allowed\nTried to run '%s'",s);
! 2049: }
! 2050:
! 2051: GEN
! 2052: extern0(char *s)
! 2053: {
! 2054: check_secure(s);
! 2055: infile = try_pipe(s, mf_IN)->file;
! 2056: return gp_main_loop();
! 2057: }
! 2058:
! 2059: static int
! 2060: silent()
! 2061: {
! 2062: if (gpsilent) return 1;
! 2063: { char c = _analyseur()[1]; return separe(c); }
! 2064: }
! 2065:
! 2066: GEN
! 2067: default0(char *a, char *b, long flag)
! 2068: {
! 2069: if (flag) flag=d_RETURN;
! 2070: else
! 2071: flag = silent()? d_SILENT: d_ACKNOWLEDGE;
! 2072: return setdefault(a,b,flag);
! 2073: }
! 2074:
! 2075: void
! 2076: allocatemem0(unsigned long newsize)
! 2077: {
! 2078: parisize = allocatemoremem(newsize);
! 2079: longjmp(local_environnement[bufindex], 0);
! 2080: }
! 2081:
! 2082: GEN
! 2083: input0()
! 2084: {
! 2085: long *ptlbuf = &paribufsize;
! 2086: char *buf;
! 2087: GEN x;
! 2088:
! 2089: if (bufindex == MAX_BUFFER) err(talker,"too many nested files");
! 2090: buflist[++bufindex] = buf = gpmalloc(*ptlbuf);
! 2091: while (! get_line_from_file(infile, &buf, ptlbuf, DFT_INPROMPT))
! 2092: if (popinfile()) { fprintferr("no input ???"); gp_quit(); }
! 2093: x = lisseq(buf);
! 2094: free(buflist[bufindex--]);
! 2095: return x;
! 2096: }
! 2097:
! 2098: void
! 2099: system0(char *s)
! 2100: {
! 2101: #if defined(UNIX) || defined(__EMX__)
! 2102: check_secure(s);
! 2103: system(s);
! 2104: #else
! 2105: err(archer);
! 2106: #endif
! 2107: }
! 2108:
! 2109: void
! 2110: error0(GEN *g)
! 2111: {
! 2112: term_color(c_ERR);
! 2113: if (!added_newline) pariputc('\n');
! 2114: pariputs("### User error:\n\n ");
! 2115: print0(g,f_RAW); term_color(c_NONE);
! 2116: err_recover(talker);
! 2117: }
! 2118:
! 2119: long
! 2120: setprecr(long n)
! 2121: {
! 2122: long m = fmt.nb;
! 2123:
! 2124: if (n>0) {fmt.nb = n; prec = (long)(n*pariK1 + 3);}
! 2125: return m;
! 2126: }
! 2127:
! 2128: static void
! 2129: testint(char *s, long *d)
! 2130: {
! 2131: if (!s) return;
! 2132: *d = atol(s);
! 2133: if (*d <= 0) err(talker,"arguments must be positive integers");
! 2134: }
! 2135:
! 2136: static char *
! 2137: read_arg(int *nread, char *t, long argc, char **argv)
! 2138: {
! 2139: int i = *nread;
! 2140: if (isdigit((int)*t)) return t;
! 2141: if (*t || i==argc) usage(argv[0]);
! 2142: *nread = i+1; return argv[i];
! 2143: }
! 2144:
! 2145: static char**
! 2146: read_opt(long argc, char **argv)
! 2147: {
! 2148: char *b=NULL, *p=NULL, *s=NULL, **pre=(char**)1;
! 2149: int i=1;
! 2150:
! 2151: pari_outfile=stderr;
! 2152: while (i<argc)
! 2153: {
! 2154: char *t = argv[i++];
! 2155:
! 2156: if (*t++ != '-') usage(argv[0]);
! 2157: switch(*t++)
! 2158: {
! 2159: case 'b': b = read_arg(&i,t,argc,argv); break;
! 2160: case 'p': p = read_arg(&i,t,argc,argv); break;
! 2161: case 's': s = read_arg(&i,t,argc,argv); break;
! 2162:
! 2163: case 'e':
! 2164: if (strncmp(t,"macs",4)) usage(argv[0]);
! 2165: under_emacs = 1; break;
! 2166: case 'q':
! 2167: quiet_mode = 1; break;
! 2168: case 't':
! 2169: if (strncmp(t,"est",3)) usage(argv[0]);
! 2170: disable_color = 1; test_mode = 1; /* fall through */
! 2171: case 'f':
! 2172: pre = NULL; break;
! 2173: case '-':
! 2174: if (strcmp(t, "version") == 0) {
! 2175: print_version();
! 2176: exit(0);
! 2177: }
! 2178: /* fall through */
! 2179: default:
! 2180: usage(argv[0]);
! 2181: }
! 2182: }
! 2183: if (pre) pre = gp_initrc();
! 2184:
! 2185: /* override the values from gprc */
! 2186: testint(b, &paribufsize); if (paribufsize < 10) paribufsize = 10;
! 2187: testint(p, &primelimit);
! 2188: testint(s, &parisize);
! 2189: if (under_emacs) disable_color=1;
! 2190: pari_outfile=stdout; return pre;
! 2191: }
! 2192:
! 2193: #ifdef WINCE
! 2194: int
! 2195: WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
! 2196: LPWSTR lpCmdLine, int nShowCmd)
! 2197: {
! 2198: char **argv = NULL;
! 2199: int argc = 1;
! 2200: #else
! 2201: int
! 2202: main(int argc, char **argv)
! 2203: {
! 2204: #endif
! 2205: char **flist;
! 2206:
! 2207: init_defaults(1); gp_preinit(1);
! 2208: if (setjmp(environnement))
! 2209: {
! 2210: pariputs("### Errors on startup, exiting...\n\n");
! 2211: exit(1);
! 2212: }
! 2213: #ifdef __MWERKS__
! 2214: argc = ccommand(&argv);
! 2215: #endif
! 2216: flist = read_opt(argc,argv);
! 2217: pari_addfunctions(&pari_modules, functions_gp,helpmessages_gp);
! 2218: pari_addfunctions(&pari_modules, functions_highlevel,helpmessages_highlevel);
! 2219: pari_addfunctions(&pari_oldmodules, functions_oldgp,helpmessages_oldgp);
! 2220:
! 2221: init_graph(); INIT_SIG_off;
! 2222: pari_init(parisize, primelimit);
! 2223: #ifndef WINCE
! 2224: pari_sig_init(gp_sighandler);
! 2225: #endif
! 2226: #ifdef READLINE
! 2227: init_readline();
! 2228: #endif
! 2229: gp_history_fun = gp_history;
! 2230: whatnow_fun = whatnow;
! 2231: gp_expand_path(path);
! 2232:
! 2233: if (!quiet_mode) gp_head();
! 2234: if (flist)
! 2235: {
! 2236: long c=chrono, b=bufindex, e=pariecho;
! 2237: FILE *l=logfile;
! 2238: char **s = flist;
! 2239: bufindex = 0; chrono=0; pariecho=0; logfile=NULL;
! 2240: for ( ; *s; s++) { read0(*s); free(*s); }
! 2241: bufindex = b; chrono=c; pariecho=e; logfile=l; free(flist);
! 2242: }
! 2243: gptimer(); timer2();
! 2244: (void)gp_main_loop();
! 2245: gp_quit(); return 0; /* not reached */
! 2246: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>