[BACK]Return to gp.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / gp

Annotation of OpenXM_contrib/pari-2.2/src/gp/gp.c, Revision 1.1.1.1

1.1       noro        1: /* $Id: gp.c,v 1.83 2001/09/29 18:32:02 karim Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /**                                                               **/
                     18: /**                        PARI CALCULATOR                        **/
                     19: /**                                                               **/
                     20: /*******************************************************************/
                     21: #include "pari.h"
                     22: #ifdef _WIN32
                     23: #  include <windows.h>
                     24: #  ifndef WINCE
                     25: #    include <process.h>
                     26: #  endif
                     27: #endif
                     28: #ifdef HAS_STRFTIME
                     29: #  include <time.h>
                     30: #endif
                     31: #include "../language/anal.h"
                     32: #include "gp.h"
                     33:
                     34: #ifdef READLINE
                     35:   extern void init_readline();
                     36:   long use_readline = 1;
                     37:   int readline_init = 1;
                     38: BEGINEXTERN
                     39: #  if defined(__cplusplus) && defined(__SUNPRO_CC)
                     40:   /* readline.h gives a bad definition of readline() */
                     41:   extern char*readline(char*);
                     42: #  else
                     43: #   ifdef READLINE_LIBRARY
                     44: #     include <readline.h>
                     45: #   else
                     46: #     include <readline/readline.h>
                     47: #   endif
                     48: #  endif
                     49:   extern int isatty(int);
                     50:   extern void add_history(char*);
                     51: ENDEXTERN
                     52: #endif
                     53:
                     54: char*  _analyseur(void);
                     55: void   _set_analyseur(char *s);
                     56: void   err_recover(long numerr);
                     57: void   free_graph(void);
                     58: void   gp_expand_path(char *v);
                     59: int    gp_init_entrees(module *modlist, entree **hash, int force);
                     60: long   gptimer(void);
                     61: void   init80(long n);
                     62: void   init_defaults(int force);
                     63: void   initout(int initerr);
                     64: void   init_graph(void);
                     65: void   init_lim_lines(char *s, long max);
                     66: extern void   install0(char *name, char *code, char *gpname, char *lib);
                     67: void   pari_sig_init(void (*f)(int));
                     68: int    whatnow(char *s, int flag);
                     69:
                     70: #if 0 /* to debug TeXmacs interface */
                     71: #define DATA_BEGIN  ((char) 'B')
                     72: #define DATA_END    ((char) 'E')
                     73: #else
                     74: #define DATA_BEGIN  ((char) 2)
                     75: #define DATA_END    ((char) 5)
                     76: #endif
                     77: #define DATA_ESCAPE ((char) 27)
                     78:
                     79: #define MAX_PROMPT_LEN 128
                     80: #define DFT_PROMPT "? "
                     81: #define COMMENTPROMPT "comment> "
                     82: #define DFT_INPROMPT ""
                     83: static GEN *hist;
                     84: static char *help_prg,*path;
                     85: static char prompt[MAX_PROMPT_LEN];
                     86: static char thestring[256];
                     87: static char *prettyprinter;
                     88: static char *prettyprinter_dft = "tex2mail -TeX -noindent -ragged -by_par";
                     89: static pariFILE *prettyprinter_file;
                     90: static long prettyp, test_mode, quiet_mode, gpsilent, simplifyflag;
                     91: static long chrono, pariecho, primelimit, parisize, strictmatch;
                     92: static long tglobal, histsize, paribufsize, lim_lines;
                     93: static int tm_is_waiting = 0, handle_C_C = 0;
                     94: static gp_format fmt;
                     95:
                     96: typedef struct Buffer {
                     97:   char *buf;
                     98:   long len;
                     99:   jmp_buf env;
                    100:   int flenv;
                    101: } Buffer;
                    102:
                    103: #define current_buffer (bufstack?((Buffer*)(bufstack->value)):NULL)
                    104: static stack *bufstack = NULL;
                    105:
                    106: #define LBRACE '{'
                    107: #define RBRACE '}'
                    108: #define pariputs_opt(s) if (!quiet_mode) pariputs(s)
                    109: #define skip_space(s) while (isspace((int)*s)) s++
                    110: #define skip_alpha(s) while (isalpha((int)*s)) s++
                    111: #define ask_filtre(t) filtre("",NULL,t)
                    112:
                    113: static void
                    114: usage(char *s)
                    115: {
                    116:   printf("### Usage: %s [options]\n", s);
                    117:   printf("Options are:\n");
                    118:   printf("\t[-b buffersize]\tDeprecated\n");
                    119:   printf("\t[-emacs]\tRun as if in Emacs shell\n");
                    120:   printf("\t[-f]\t\tFaststart: do not read .gprc\n");
                    121:   printf("\t[--help]\tPrint this message\n");
                    122:   printf("\t[-q]\t\tQuiet mode: do not print banner and history numbers\n");
                    123:   printf("\t[-p primelimit]\tPrecalculate primes up to the limit\n");
                    124:   printf("\t[-s stacksize]\tStart with the PARI stack of given size (in bytes)\n");
                    125:   printf("\t[-test]\t\tTest mode.  As -q, plus wrap long lines\n");
                    126:   printf("\t[--version]\tOutput version info and exit\n\n");
                    127:   exit(0);
                    128: }
                    129:
                    130: /* must be called BEFORE pari_init() */
                    131: static void
                    132: gp_preinit(int force)
                    133: {
                    134:   static char *dflt;
                    135:   char *help;
                    136:   long i;
                    137:
                    138:   if (force)
                    139:   {
                    140: #if !defined(macintosh) || defined(__MWERKS__)
                    141:     primelimit = 500000; parisize = 1000000*sizeof(long);
                    142:     dflt = DFT_PROMPT;
                    143: #else
                    144:     primelimit = 200000; parisize = 1000000;
                    145:     dflt = "?\n";
                    146: #endif
                    147:   }
                    148:   strcpy(prompt, dflt);
                    149:
                    150: #if defined(UNIX) || defined(__EMX__)
                    151: #  if defined(__EMX__) || defined(__CYGWIN32__)
                    152:   path = pari_strdup(".;C:;C:/gp");
                    153: #  else
                    154:   path = pari_strdup(".:~:~/gp");
                    155: #  endif
                    156:   help = getenv("GPHELP");
                    157: # ifdef GPHELP
                    158:     if (!help) help = GPHELP;
                    159: # endif
                    160: #else
                    161:   path = pari_strdup(".");
                    162:   help = NULL;
                    163: #endif
                    164:   help_prg = help? pari_strdup(help): NULL;
                    165:   prettyp = f_PRETTYMAT;
                    166:   strictmatch = simplifyflag = 1;
                    167:   tglobal = 0;
                    168:   bufstack = NULL;
                    169:   secure = test_mode = under_emacs = under_texmacs = chrono = pariecho = 0;
                    170:   prettyprinter = prettyprinter_dft;
                    171:   prettyprinter_file = NULL;
                    172:   fmt.format = 'g'; fmt.field = 0;
                    173: #ifdef LONG_IS_64BIT
                    174:   fmt.nb = 38;
                    175: #else
                    176:   fmt.nb = 28;
                    177: #endif
                    178:   lim_lines = 0;
                    179:   histsize = 5000; paribufsize = 1024;
                    180:   i = histsize*sizeof(GEN);
                    181:   hist = (GEN *) gpmalloc(i); memset(hist,0,i);
                    182:   for (i=0; i<c_LAST; i++) gp_colors[i] = c_NONE;
                    183: }
                    184:
                    185: #ifdef MAXPATHLEN
                    186: #  define GET_SEP_SIZE MAXPATHLEN
                    187: #else
                    188: #  define GET_SEP_SIZE 128
                    189: #endif
                    190: #define separe(c)  ((c)==';' || (c)==':')
                    191:
                    192: /* Return all chars, up to next separator */
                    193: static char*
                    194: get_sep0(char *t, int colon)
                    195: {
                    196:   static char buf[GET_SEP_SIZE], *lim = buf + GET_SEP_SIZE-1;
                    197:   char *s = buf;
                    198:   int outer=1;
                    199:
                    200:   for(;;)
                    201:   {
                    202:     switch(*s++ = *t++)
                    203:     {
                    204:       case '"':
                    205:         if (outer || (s >= buf+2 && s[-2] != '\\')) outer = !outer;
                    206:         break;
                    207:       case '\0':
                    208:         return buf;
                    209:       case ';':
                    210:        if (outer) { s[-1]=0; return buf; } break;
                    211:       case ':':
                    212:         if (outer && colon) { s[-1]=0; return buf; } break;
                    213:     }
                    214:     if (s == lim) err(talker,"buffer overflow in get_sep");
                    215:   }
                    216: }
                    217:
                    218: static char*
                    219: get_sep(char *t)
                    220: {
                    221:   return get_sep0(t,1);
                    222: }
                    223:
                    224: static char*
                    225: get_sep_colon_ok(char *t)
                    226: {
                    227:   return get_sep0(t,0);
                    228: }
                    229:
                    230: /* as above, t must be writeable, return 1 if we modified t */
                    231: static int
                    232: get_sep2(char *t)
                    233: {
                    234:   int outer=1;
                    235:   char *s = t;
                    236:
                    237:   for(;;)
                    238:   {
                    239:     switch (*s++)
                    240:     {
                    241:       case '"':
                    242:         if (outer || s[-2] != '\\') outer = !outer;
                    243:         break;
                    244:       case '\0':
                    245:         return 0;
                    246:       default:
                    247:         if (outer && separe(*s)) { *s=0; return 1; }
                    248:     }
                    249:   }
                    250: }
                    251:
                    252: static long
                    253: get_int(char *s, long dflt)
                    254: {
                    255:   char *p=get_sep(s);
                    256:   long n=atol(p);
                    257:
                    258:   if (*p == '-') p++;
                    259:   while(isdigit((int)*p)) { p++; dflt=n; }
                    260:   switch(*p)
                    261:   {
                    262:     case 'k': case 'K': dflt *= 1000;    p++; break;
                    263:     case 'm': case 'M': dflt *= 1000000; p++; break;
                    264:   }
                    265:   if (*p) err(talker2,"I was expecting an integer here", s, s);
                    266:   return dflt;
                    267: }
                    268:
                    269: /* tell TeXmacs GP will start outputing data */
                    270: static void
                    271: tm_start_output()
                    272: {
                    273:   if (!tm_is_waiting) { printf("%cverbatim:",DATA_BEGIN); fflush(stdout); }
                    274:   tm_is_waiting = 1;
                    275: }
                    276:
                    277: /* tell TeXmacs GP is done and is waiting for new data */
                    278: static void
                    279: tm_end_output()
                    280: {
                    281:   if (tm_is_waiting) { printf("%c", DATA_END); fflush(stdout); }
                    282:   tm_is_waiting = 0;
                    283: }
                    284:
                    285: static void
                    286: gp_output(GEN x)
                    287: {
                    288:   long tx=typ(x);
                    289:
                    290:   if (fmt.nb >= 0 && is_intreal_t(tx))
                    291:     ecrire(x, fmt.format, fmt.nb, fmt.field);
                    292:   else
                    293:     switch(prettyp)
                    294:     {
                    295:       case f_PRETTYMAT: matbrute(x, fmt.format, fmt.nb); break;
                    296:       case f_PRETTY:
                    297:       case f_PRETTYOLD: sor(x, fmt.format, fmt.nb, fmt.field); break;
                    298:       case f_RAW      : brute(x, fmt.format, fmt.nb); break;
                    299:       case f_TEX      : texe(x, fmt.format, fmt.nb); break;
                    300:     }
                    301: }
                    302:
                    303: /* print a sequence of (NULL terminated) GEN */
                    304: void
                    305: print0(GEN *g, long flag)
                    306: {
                    307:   int old=prettyp;
                    308:
                    309:   if (flag < NBFORMATS) added_newline=1;
                    310:   else
                    311:     { flag -= NBFORMATS; added_newline=0; }
                    312:   prettyp=flag;
                    313:
                    314:   for( ; *g; g++)
                    315:     if (typ(*g)==t_STR)
                    316:       pariputs(GSTR(*g)); /* otherwise it's surrounded by "" */
                    317:     else
                    318:       gp_output(*g);
                    319:
                    320:   if (added_newline) pariputc('\n');
                    321:   prettyp=old; pariflush();
                    322: }
                    323:
                    324: /* write a sequence of (NULL terminated) GEN, to file s */
                    325: void
                    326: write0(char *s, GEN *g, long flag)
                    327: {
                    328:   int i = added_newline;
                    329:   s = expand_tilde(s);
                    330:   if (secure)
                    331:   {
                    332:     fprintferr("[secure mode]: about to write to '%s'. OK ? (^C if not)\n",s);
                    333:     hit_return();
                    334:   }
                    335:   switchout(s); free(s);
                    336:   print0(g,flag); added_newline = i;
                    337:   switchout(NULL);
                    338: }
                    339:
                    340: void
                    341: gpwritebin(char *s, GEN x)
                    342: {
                    343:   s = expand_tilde(s);
                    344:   if (secure)
                    345:   {
                    346:     fprintferr("[secure mode]: about to write to '%s'. OK ? (^C if not)\n",s);
                    347:     hit_return();
                    348:   }
                    349:   writebin(s,x); free(s);
                    350: }
                    351:
                    352: Buffer *
                    353: new_buffer()
                    354: {
                    355:   Buffer *b = (Buffer*) gpmalloc(sizeof(Buffer));
                    356:   b->len = paribufsize;
                    357:   b->buf = gpmalloc(b->len);
                    358:   b->flenv = 0; return b;
                    359: }
                    360:
                    361: void
                    362: del_buffer(Buffer *b)
                    363: {
                    364:   if (!b) return;
                    365:   free(b->buf); free((void*)b);
                    366: }
                    367:
                    368: static void
                    369: pop_buffer()
                    370: {
                    371:   Buffer *b = (Buffer*) pop_stack(&bufstack);
                    372:   del_buffer(b);
                    373: }
                    374:
                    375: /* kill all buffers until B is met or nothing is left */
                    376: static void
                    377: kill_all_buffers(Buffer *B)
                    378: {
                    379:   for(;;) {
                    380:     Buffer *b = current_buffer;
                    381:     if (b == B || !b) break;
                    382:     pop_buffer();
                    383:   }
                    384: }
                    385:
                    386: static void
                    387: jump_to_buffer()
                    388: {
                    389:   Buffer *b;
                    390:   while ( (b = current_buffer) )
                    391:   {
                    392:     if (b->flenv) break;
                    393:     pop_buffer();
                    394:   }
                    395:   if (!b) longjmp(environnement, 0);
                    396:   longjmp(b->env, 0);
                    397: }
                    398:
                    399: static void
                    400: jump_to_given_buffer(Buffer *buf)
                    401: {
                    402:   Buffer *b;
                    403:   while ( (b = current_buffer) )
                    404:   {
                    405:     if (b == buf) break;
                    406:     pop_buffer();
                    407:   }
                    408:   if (!b->env) { b = NULL; err(warner,"no environmnent tied to buffer"); }
                    409:   if (!b) longjmp(environnement, 0);
                    410:   longjmp(b->env, 0);
                    411: }
                    412:
                    413: /********************************************************************/
                    414: /*                                                                  */
                    415: /*                            DEFAULTS                              */
                    416: /*                                                                  */
                    417: /********************************************************************/
                    418: static void
                    419: do_strftime(char *s, char *buf)
                    420: {
                    421: #ifdef HAS_STRFTIME
                    422:   time_t t = time(NULL);
                    423:   strftime(buf,MAX_PROMPT_LEN-1,s,localtime(&t));
                    424: #else
                    425:   strcpy(buf,s);
                    426: #endif
                    427: }
                    428:
                    429: static GEN
                    430: sd_numeric(char *v, int flag, char *s, long *ptn, long Min, long Max,
                    431:            char **msg)
                    432: {
                    433:   long n;
                    434:   if (*v == 0) n = *ptn;
                    435:   else
                    436:   {
                    437:     n = get_int(v,0);
                    438:     if (*ptn == n) return gnil;
                    439:     if (n > Max || n < Min)
                    440:     {
                    441:       sprintf(thestring, "default: incorrect value for %s [%ld-%ld]",
                    442:              s, Min, Max);
                    443:       err(talker2, thestring, v,v);
                    444:     }
                    445:     *ptn = n;
                    446:   }
                    447:   switch(flag)
                    448:   {
                    449:     case d_RETURN: return stoi(n);
                    450:     case d_ACKNOWLEDGE:
                    451:       if (msg)
                    452:       {
                    453:        if (!*msg)
                    454:          msg++; /* single msg, always printed */
                    455:        else
                    456:          msg += n; /* one per possible value */
                    457:        pariputsf("   %s = %ld %s\n", s, n, *msg);
                    458:       }
                    459:       else if (Max != 1 || Min != 0)
                    460:        pariputsf("   %s = %ld\n", s, n);
                    461:       else /* toggle */
                    462:       {
                    463:        if (n==1) pariputsf("   %s = 1 (on)\n", s);
                    464:        else      pariputsf("   %s = 0 (off)\n", s);
                    465:       } /* fall through */
                    466:     default: return gnil;
                    467:   }
                    468: }
                    469:
                    470: #define PRECDIGIT (long)((prec-2.)*pariK)
                    471: static GEN
                    472: sd_realprecision(char *v, int flag)
                    473: {
                    474:   if (*v)
                    475:   {
                    476:     long newnb = get_int(v, fmt.nb);
                    477:     long newprec = (long) (newnb*pariK1 + 3);
                    478:
                    479:     if (fmt.nb == newnb && prec == newprec) return gnil;
                    480:     if (newnb < 0) err(talker,"default: negative real precision");
                    481:     fmt.nb = newnb; prec = newprec;
                    482:   }
                    483:   if (flag == d_RETURN) return stoi(fmt.nb);
                    484:   if (flag == d_ACKNOWLEDGE)
                    485:   {
                    486:     long n = PRECDIGIT;
                    487:     pariputsf("   realprecision = %ld significant digits", n);
                    488:     if (n != fmt.nb) pariputsf(" (%ld digits displayed)", fmt.nb);
                    489:     pariputc('\n');
                    490:   }
                    491:   return gnil;
                    492: }
                    493: #undef PRECDIGIT
                    494:
                    495: static GEN
                    496: sd_seriesprecision(char *v, int flag)
                    497: {
                    498:   char *msg[] = {NULL, "significant terms"};
                    499:   return sd_numeric(v,flag,"seriesprecision",&precdl, 0,LGBITS,msg);
                    500: }
                    501:
                    502: static GEN
                    503: sd_format(char *v, int flag)
                    504: {
                    505:   if (*v)
                    506:   {
                    507:     char c = *v;
                    508:     if (c!='e' && c!='f' && c!='g')
                    509:       err(talker2,"default: inexistent format",v,v);
                    510:     fmt.format = c; v++;
                    511:
                    512:     if (isdigit((int)*v))
                    513:       { fmt.field=atol(v); while (isdigit((int)*v)) v++; }
                    514:     if (*v++ == '.')
                    515:     {
                    516:       if (*v == '-') fmt.nb = -1;
                    517:       else
                    518:        if (isdigit((int)*v)) fmt.nb=atol(v);
                    519:     }
                    520:   }
                    521:   if (flag == d_RETURN)
                    522:   {
                    523:     sprintf(thestring, "%c%ld.%ld", fmt.format, fmt.field, fmt.nb);
                    524:     return strtoGENstr(thestring,0);
                    525:   }
                    526:   if (flag == d_ACKNOWLEDGE)
                    527:     pariputsf("   format = %c%ld.%ld\n", fmt.format, fmt.field, fmt.nb);
                    528:   return gnil;
                    529: }
                    530:
                    531: static long
                    532: gp_get_color(char **st)
                    533: {
                    534:   char *s, *v = *st;
                    535:   int c, trans;
                    536:   if (isdigit((int)*v))
                    537:     { c = atol(v); trans = 1; } /* color on transparent background */
                    538:   else
                    539:   {
                    540:     if (*v == '[')
                    541:     {
                    542:       char *a[3];
                    543:       int i = 0;
                    544:       for (a[0] = s = ++v; *s && *s != ']'; s++)
                    545:         if (*s == ',') { *s = 0; a[++i] = s+1; }
                    546:       if (*s != ']') err(talker2,"expected character: ']'",s, *st);
                    547:       *s = 0; for (i++; i<3; i++) a[i] = "";
                    548:       /*    properties    |   color    | background */
                    549:       c = (atoi(a[2])<<8) | atoi(a[0]) | (atoi(a[1])<<4);
                    550:       trans = (*(a[1]) == 0);
                    551:       v = s + 1;
                    552:     }
                    553:     else { c = c_NONE; trans = 0; }
                    554:   }
                    555:   if (trans) c = c | (1<<12);
                    556:   while (*v && *v++ != ',') /* empty */;
                    557:   if (c != c_NONE) disable_color=0;
                    558:   *st = v; return c;
                    559: }
                    560:
                    561: static GEN
                    562: sd_colors(char *v, int flag)
                    563: {
                    564:   long c,l;
                    565:   if (*v && !under_emacs && !under_texmacs)
                    566:   {
                    567:     disable_color=1;
                    568:     l = strlen(v);
                    569:     if (l <= 2 && strncmp(v, "no", l) == 0)
                    570:       v = "";
                    571:     if (l <= 6 && strncmp(v, "darkbg", l) == 0)
                    572:       v = "1, 5, 3, 7, 6, 2, 3";       /* Assume recent ReadLine. */
                    573:     if (l <= 7 && strncmp(v, "lightbg", l) == 0)
                    574:       v = "1, 6, 3, 4, 5, 2, 3";       /* Assume recent ReadLine. */
                    575:     if (l <= 6 && strncmp(v, "boldfg", l) == 0)        /* Good for darkbg consoles */
                    576:       v = "[1,,1], [5,,1], [3,,1], [7,,1], [6,,1], [2,,1], [3,,1]";
                    577:     v = filtre(v,NULL, f_INIT|f_REG);
                    578:     for (c=c_ERR; c < c_LAST; c++)
                    579:       gp_colors[c] = gp_get_color(&v);
                    580:   }
                    581:   if (flag == d_ACKNOWLEDGE || flag == d_RETURN)
                    582:   {
                    583:     char *s = thestring;
                    584:     int col[3], n;
                    585:     for (*s=0,c=c_ERR; c < c_LAST; c++)
                    586:     {
                    587:       n = gp_colors[c];
                    588:       if (n == c_NONE)
                    589:         sprintf(s,"no");
                    590:       else
                    591:       {
                    592:         decode_color(n,col);
                    593:         if (n & (1<<12))
                    594:         {
                    595:           if (col[0])
                    596:             sprintf(s,"[%d,,%d]",col[1],col[0]);
                    597:           else
                    598:             sprintf(s,"%d",col[1]);
                    599:         }
                    600:         else
                    601:           sprintf(s,"[%d,%d,%d]",col[1],col[2],col[0]);
                    602:       }
                    603:       s += strlen(s);
                    604:       if (c < c_LAST - 1) { *s++=','; *s++=' '; }
                    605:     }
                    606:     if (flag==d_RETURN) return strtoGENstr(thestring,0);
                    607:     pariputsf("   colors = \"%s\"\n",thestring);
                    608:   }
                    609:   return gnil;
                    610: }
                    611:
                    612: static GEN
                    613: sd_compatible(char *v, int flag)
                    614: {
                    615:   char *msg[] = {
                    616:     "(no backward compatibility)",
                    617:     "(warn when using obsolete functions)",
                    618:     "(use old functions, don't ignore case)",
                    619:     "(use old functions, ignore case)", NULL
                    620:   };
                    621:   long old = compatible;
                    622:   GEN r = sd_numeric(v,flag,"compatible",&compatible, 0,3,msg);
                    623:
                    624:   if (old != compatible && flag != d_INITRC)
                    625:   {
                    626:     int res = gp_init_entrees(new_fun_set? pari_modules: pari_oldmodules,
                    627:                              functions_hash, 0);
                    628:     if (res) err(warner,"user functions re-initialized");
                    629:   }
                    630:   return r;
                    631: }
                    632:
                    633: static GEN
                    634: sd_secure(char *v, int flag)
                    635: {
                    636:   if (*v && secure)
                    637:   {
                    638:     fprintferr("[secure mode]: Do you want to modify the 'secure' flag? (^C if not)\n");
                    639:     hit_return();
                    640:   }
                    641:   return sd_numeric(v,flag,"secure",&secure, 0,1,NULL);
                    642: }
                    643:
                    644: static GEN
                    645: sd_buffersize(char *v, int flag)
                    646: { return sd_numeric(v,flag,"buffersize",&paribufsize, 1,
                    647:                     (VERYBIGINT / sizeof(long)) - 1,NULL); }
                    648: static GEN
                    649: sd_debug(char *v, int flag)
                    650: { return sd_numeric(v,flag,"debug",&DEBUGLEVEL, 0,20,NULL); }
                    651:
                    652: static GEN
                    653: sd_rl(char *v, int flag)
                    654: {
                    655: #ifdef READLINE
                    656: #  if 0                        /* Works - even when init_readline() was called */
                    657:     if (readline_init && *v == '0')
                    658:        err(talker, "Too late to switch off readline mode");
                    659: #  endif
                    660:     if (!readline_init && *v && *v != '0') {
                    661:        init_readline();
                    662:        readline_init = 1;
                    663:     }
                    664:     return sd_numeric(v,flag,"readline",&use_readline, 0,20,NULL);
                    665: #else  /* !( defined READLINE ) */
                    666:     long dummy;
                    667:     return sd_numeric(v,flag,"readline",&dummy, 0,20,NULL);
                    668: #endif
                    669: }
                    670:
                    671: static GEN
                    672: sd_debugfiles(char *v, int flag)
                    673: { return sd_numeric(v,flag,"debugfiles",&DEBUGFILES, 0,20,NULL); }
                    674:
                    675: static GEN
                    676: sd_debugmem(char *v, int flag)
                    677: { return sd_numeric(v,flag,"debugmem",&DEBUGMEM, 0,20,NULL); }
                    678:
                    679: static GEN
                    680: sd_echo(char *v, int flag)
                    681: { return sd_numeric(v,flag,"echo",&pariecho, 0,1,NULL); }
                    682:
                    683: static GEN
                    684: sd_lines(char *v, int flag)
                    685: { return sd_numeric(v,flag,"lines",&lim_lines, 0,VERYBIGINT,NULL); }
                    686:
                    687: static GEN
                    688: sd_histsize(char *v, int flag)
                    689: {
                    690:   long n = histsize;
                    691:   GEN r = sd_numeric(v,flag,"histsize",&n, 1,
                    692:                      (VERYBIGINT / sizeof(long)) - 1,NULL);
                    693:   if (n != histsize)
                    694:   {
                    695:     long i = n*sizeof(GEN);
                    696:     GEN *gg = (GEN *) gpmalloc(i); memset(gg,0,i);
                    697:
                    698:     if (tglobal)
                    699:     {
                    700:       long k = (tglobal-1) % n;
                    701:       long kmin = k - min(n,histsize), j = k;
                    702:
                    703:       i = (tglobal-1) % histsize;
                    704:       while (k > kmin)
                    705:       {
                    706:        gg[j] = hist[i];
                    707:        hist[i] = NULL;
                    708:        if (!i) i = histsize;
                    709:        if (!j) j = n;
                    710:        i--; j--; k--;
                    711:       }
                    712:       while (hist[i])
                    713:       {
                    714:        gunclone(hist[i]);
                    715:        if (!i) i = histsize;
                    716:        i--;
                    717:       }
                    718:     }
                    719:     free((void*)hist); hist=gg; histsize=n;
                    720:   }
                    721:   return r;
                    722: }
                    723:
                    724: static GEN
                    725: sd_log(char *v, int flag)
                    726: {
                    727:   long vlog = logfile? 1: 0, old = vlog;
                    728:   GEN r = sd_numeric(v,flag,"log",&vlog, 0,1,NULL);
                    729:   if (vlog != old)
                    730:   {
                    731:     if (vlog)
                    732:     {
                    733:       logfile = fopen(current_logfile, "a");
                    734:       if (!logfile) err(openfiler,"logfile",current_logfile);
                    735: #ifndef WINCE
                    736:       setbuf(logfile,(char *)NULL);
                    737: #endif
                    738:     }
                    739:     else
                    740:     {
                    741:       if (flag == d_ACKNOWLEDGE)
                    742:         pariputsf("   [logfile was \"%s\"]\n", current_logfile);
                    743:       fclose(logfile); logfile=NULL;
                    744:     }
                    745:   }
                    746:   return r;
                    747: }
                    748:
                    749: static GEN
                    750: sd_output(char *v, int flag)
                    751: {
                    752:   char *msg[] = {"(raw)", "(prettymatrix)", "(prettyprint)", "(external prettyprint)", NULL};
                    753:   return sd_numeric(v,flag,"output",&prettyp, 0,3,msg);
                    754: }
                    755:
                    756: extern void err_clean();
                    757:
                    758: void
                    759: allocatemem0(unsigned long newsize)
                    760: {
                    761:   parisize = allocatemoremem(newsize);
                    762:   err_clean();
                    763:   jump_to_buffer();
                    764: }
                    765:
                    766: static GEN
                    767: sd_parisize(char *v, int flag)
                    768: {
                    769:   long n = parisize;
                    770:   GEN r = sd_numeric(v,flag,"parisize",&n, 10000,VERYBIGINT,NULL);
                    771:   if (n != parisize)
                    772:   {
                    773:     if (flag != d_INITRC) allocatemem0(n);
                    774:     parisize = n;
                    775:   }
                    776:   return r;
                    777: }
                    778:
                    779: static GEN
                    780: sd_primelimit(char *v, int flag)
                    781: {
                    782:   long n = primelimit;
                    783:   GEN r = sd_numeric(v,flag,"primelimit",&n, 0,VERYBIGINT,NULL);
                    784:   if (n != primelimit)
                    785:   {
                    786:     if (flag != d_INITRC)
                    787:     {
                    788:       byteptr ptr = initprimes(n);
                    789:       free(diffptr); diffptr = ptr;
                    790:     }
                    791:     primelimit = n;
                    792:   }
                    793:   return r;
                    794: }
                    795:
                    796: static GEN
                    797: sd_simplify(char *v, int flag)
                    798: { return sd_numeric(v,flag,"simplify",&simplifyflag, 0,1,NULL); }
                    799:
                    800: static GEN
                    801: sd_strictmatch(char *v, int flag)
                    802: { return sd_numeric(v,flag,"strictmatch",&strictmatch, 0,1,NULL); }
                    803:
                    804: static GEN
                    805: sd_timer(char *v, int flag)
                    806: { return sd_numeric(v,flag,"timer",&chrono, 0,1,NULL); }
                    807:
                    808: static GEN
                    809: sd_filename(char *v, int flag, char *s, char **f)
                    810: {
                    811:   if (*v)
                    812:   {
                    813:     char *old = *f;
                    814:     v = expand_tilde(v);
                    815:     do_strftime(v,thestring); free(v);
                    816:     *f = pari_strdup(thestring); free(old);
                    817:   }
                    818:   if (flag == d_RETURN) return strtoGENstr(*f,0);
                    819:   if (flag == d_ACKNOWLEDGE) pariputsf("   %s = \"%s\"\n",s,*f);
                    820:   return gnil;
                    821: }
                    822:
                    823: static GEN
                    824: sd_logfile(char *v, int flag)
                    825: {
                    826:   GEN r = sd_filename(v, flag, "logfile", &current_logfile);
                    827:   if (*v && logfile)
                    828:   {
                    829:     fclose(logfile);
                    830:     logfile = fopen(current_logfile, "a");
                    831:     if (!logfile) err(openfiler,"logfile",current_logfile);
                    832: #ifndef WINCE
                    833:     setbuf(logfile,(char *)NULL);
                    834: #endif
                    835:   }
                    836:   return r;
                    837: }
                    838:
                    839: static GEN
                    840: sd_psfile(char *v, int flag)
                    841: { return sd_filename(v, flag, "psfile", &current_psfile); }
                    842:
                    843: static void
                    844: err_secure(char *d, char *v)
                    845: { err(talker,"[secure mode]: can't modify '%s' default (to %s)",d,v); }
                    846:
                    847: static GEN
                    848: sd_help(char *v, int flag)
                    849: {
                    850:   char *str;
                    851:   if (*v)
                    852:   {
                    853:     if (secure) err_secure("help",v);
                    854:     if (help_prg) free(help_prg);
                    855:     help_prg = expand_tilde(v);
                    856:   }
                    857:   str = help_prg? help_prg: "none";
                    858:   if (flag == d_RETURN) return strtoGENstr(str,0);
                    859:   if (flag == d_ACKNOWLEDGE)
                    860:     pariputsf("   help = \"%s\"\n", str);
                    861:   return gnil;
                    862: }
                    863:
                    864: static GEN
                    865: sd_path(char *v, int flag)
                    866: {
                    867:   if (*v)
                    868:   {
                    869:     char *old = path;
                    870:     path = pari_strdup(v); free(old);
                    871:     if (flag == d_INITRC) return gnil;
                    872:     gp_expand_path(path);
                    873:   }
                    874:   if (flag == d_RETURN) return strtoGENstr(path,0);
                    875:   if (flag == d_ACKNOWLEDGE)
                    876:     pariputsf("   path = \"%s\"\n",path);
                    877:   return gnil;
                    878: }
                    879:
                    880: static GEN
                    881: sd_prettyprinter(char *v, int flag)
                    882: {
                    883:   if (*v && !under_texmacs)
                    884:   {
                    885:     char *old = prettyprinter;
                    886:     int cancel = (!strcmp(v,"no"));
                    887:
                    888:     if (secure) err_secure("prettyprinter",v);
                    889:     if (!strcmp(v,"yes")) v = prettyprinter_dft;
                    890:     if (old && strcmp(old,v) && prettyprinter_file)
                    891:     {
                    892:       pariFILE *f;
                    893:       if (cancel) f = NULL;
                    894:       else
                    895:       {
                    896:         f = try_pipe(v, mf_OUT | mf_TEST);
                    897:         if (!f)
                    898:         {
                    899:           err(warner,"broken prettyprinter: '%s'",v);
                    900:           return gnil;
                    901:         }
                    902:       }
                    903:       pari_fclose(prettyprinter_file);
                    904:       prettyprinter_file = f;
                    905:     }
                    906:     prettyprinter = cancel? NULL: pari_strdup(v);
                    907:     if (old && old != prettyprinter_dft) free(old);
                    908:     if (flag == d_INITRC) return gnil;
                    909:   }
                    910:   if (flag == d_RETURN) return strtoGEN(prettyprinter? prettyprinter: "");
                    911:   if (flag == d_ACKNOWLEDGE)
                    912:     pariputsf("   prettyprinter = \"%s\"\n",prettyprinter? prettyprinter: "");
                    913:   return gnil;
                    914: }
                    915:
                    916: static GEN
                    917: sd_prompt(char *v, int flag)
                    918: {
                    919:   if (*v)
                    920:   {
                    921:     strncpy(prompt,v,MAX_PROMPT_LEN);
                    922: #ifdef macintosh
                    923:     strcat(prompt,"\n");
                    924: #endif
                    925:   }
                    926:   if (flag == d_RETURN) return strtoGENstr(prompt,0);
                    927:   if (flag == d_ACKNOWLEDGE)
                    928:     pariputsf("   prompt = \"%s\"\n",prompt);
                    929:   return gnil;
                    930: }
                    931:
                    932: default_type gp_default_list[] =
                    933: {
                    934:   {"buffersize",(void*)sd_buffersize},
                    935:   {"colors",(void*)sd_colors},
                    936:   {"compatible",(void*)sd_compatible},
                    937:   {"debug",(void*)sd_debug},
                    938:   {"debugfiles",(void*)sd_debugfiles},
                    939:   {"debugmem",(void*)sd_debugmem},
                    940:   {"echo",(void*)sd_echo},
                    941:   {"format",(void*)sd_format},
                    942:   {"help",(void*)sd_help},
                    943:   {"histsize",(void*)sd_histsize},
                    944:   {"lines",(void*)sd_lines},
                    945:   {"log",(void*)sd_log},
                    946:   {"logfile",(void*)sd_logfile},
                    947:   {"output",(void*)sd_output},
                    948:   {"parisize",(void*)sd_parisize},
                    949:   {"path",(void*)sd_path},
                    950:   {"primelimit",(void*)sd_primelimit},
                    951:   {"prettyprinter",(void*)sd_prettyprinter},
                    952:   {"prompt",(void*)sd_prompt},
                    953:   {"psfile",(void*)sd_psfile},
                    954:   {"realprecision",(void*)sd_realprecision},
                    955:   {"readline",(void*)sd_rl},
                    956:   {"secure",(void*)sd_secure},
                    957:   {"seriesprecision",(void*)sd_seriesprecision},
                    958:   {"simplify",(void*)sd_simplify},
                    959:   {"strictmatch",(void*)sd_strictmatch},
                    960:   {"timer",(void *)sd_timer},
                    961:   {NULL,NULL} /* sentinel */
                    962: };
                    963:
                    964: static void
                    965: help_default()
                    966: {
                    967:   default_type *dft;
                    968:
                    969:   for (dft=gp_default_list; dft->fun; dft++)
                    970:     ((void (*)(ANYARG)) dft->fun)("", d_ACKNOWLEDGE);
                    971: }
                    972:
                    973: static GEN
                    974: setdefault(char *s,char *v, int flag)
                    975: {
                    976:   default_type *dft;
                    977:
                    978:   if (!*s) { help_default(); return gnil; }
                    979:   for (dft=gp_default_list; dft->fun; dft++)
                    980:     if (!strcmp(s,dft->name))
                    981:     {
                    982:       if (flag == d_EXISTS) return gun;
                    983:       return ((GEN (*)(ANYARG)) dft->fun)(v,flag);
                    984:     }
                    985:   if (flag == d_EXISTS) return gzero;
                    986:   err(talker,"unknown default: %s",s);
                    987:   return NULL; /* not reached */
                    988: }
                    989:
                    990: /********************************************************************/
                    991: /**                                                                **/
                    992: /**                             HELP                               **/
                    993: /**                                                                **/
                    994: /********************************************************************/
                    995: static int
                    996: has_ext_help()
                    997: {
                    998:   if (help_prg)
                    999:   {
                   1000:     char *buf = pari_strdup(help_prg), *s = buf;
                   1001:     FILE *file;
                   1002:
                   1003:     while (*s && *s != ' ') s++;
                   1004:     *s = 0; file = fopen(buf,"r");
                   1005:     if (file) { fclose(file); return 1; }
                   1006:     free(buf);
                   1007:   }
                   1008:   return 0;
                   1009: }
                   1010:
                   1011: static int
                   1012: compare_str(char **s1, char **s2) { return strcmp(*s1, *s2); }
                   1013:
                   1014: /* Print all elements of list in columns, pausing every nbli lines
                   1015:  * if nbli is non-zero.
                   1016:  * list is a NULL terminated list of function names
                   1017:  */
                   1018: void
                   1019: print_fun_list(char **list, int nbli)
                   1020: {
                   1021:   long i=0, j=0, maxlen=0, nbcol,len, w = term_width();
                   1022:   char **l;
                   1023:
                   1024:   while (list[i]) i++;
                   1025:   qsort (list, i, sizeof(char *), (QSCOMP)compare_str);
                   1026:
                   1027:   for (l=list; *l; l++)
                   1028:   {
                   1029:     len = strlen(*l);
                   1030:     if (len > maxlen) maxlen=len;
                   1031:   }
                   1032:   maxlen++; nbcol= w / maxlen;
                   1033:   if (nbcol * maxlen == w) nbcol--;
                   1034:   if (!nbcol) nbcol = 1;
                   1035:
                   1036:   pariputc('\n'); i=0;
                   1037:   for (l=list; *l; l++)
                   1038:   {
                   1039:     pariputs(*l); i++;
                   1040:     if (i >= nbcol)
                   1041:     {
                   1042:       i=0; pariputc('\n');
                   1043:       if (nbli && j++ > nbli) { j = 0; hit_return(); }
                   1044:       continue;
                   1045:     }
                   1046:     len = maxlen - strlen(*l);
                   1047:     while (len--) pariputc(' ');
                   1048:   }
                   1049:   if (i) pariputc('\n');
                   1050: }
                   1051:
                   1052: #define LIST_LEN 1023
                   1053: static void
                   1054: commands(int n)
                   1055: {
                   1056:   int hashpos, s = 0, olds = LIST_LEN;
                   1057:   entree *ep;
                   1058:   char **list = (char **) gpmalloc((olds+1)*sizeof(char *));
                   1059:
                   1060:   for (hashpos = 0; hashpos < functions_tblsz; hashpos++)
                   1061:     for (ep = functions_hash[hashpos]; ep; ep = ep->next)
                   1062:       if ((n<0 && ep->menu) || ep->menu == n)
                   1063:       {
                   1064:         list[s++] = ep->name;
                   1065:         if (s >= olds)
                   1066:         {
                   1067:          int news = olds + (LIST_LEN + 1)*sizeof(char *);
                   1068:           list = (char**) gprealloc(list,news,olds);
                   1069:          olds = news;
                   1070:         }
                   1071:       }
                   1072:   list[s]=NULL; print_fun_list(list,term_height()-4); free(list);
                   1073: }
                   1074:
                   1075: static void
                   1076: print_def_arg(GEN x)
                   1077: {
                   1078:   if (x == gzero) return;
                   1079:   pariputc('=');
                   1080:   if (typ(x)==t_STR)
                   1081:     pariputs(GSTR(x)); /* otherwise it's surrounded by "" */
                   1082:   else
                   1083:     bruteall(x,'g',-1,1);
                   1084: }
                   1085:
                   1086: static void
                   1087: print_user_fun(entree *ep)
                   1088: {
                   1089:   gp_args *f= (gp_args*)ep->args;
                   1090:   GEN q = (GEN)ep->value, *arg = f->arg;
                   1091:   int i, narg;
                   1092:
                   1093:   q++; /* skip initial NULL */
                   1094:   pariputs(ep->name); pariputc('(');
                   1095:   narg = f->narg;
                   1096:   for (i=1; i<=narg; i++, arg++)
                   1097:   {
                   1098:     entree *ep = varentries[*q++];
                   1099:     pariputs(ep? ep->name:"#");
                   1100:     print_def_arg(*arg);
                   1101:     if (i == narg) { arg++; break; }
                   1102:     pariputs(", ");
                   1103:   }
                   1104:   pariputs(") = ");
                   1105:   narg = f->nloc;
                   1106:   if (narg)
                   1107:   {
                   1108:     pariputs("local(");
                   1109:     for (i=1; i<=narg; i++, arg++)
                   1110:     {
                   1111:       entree *ep = varentries[*q++];
                   1112:       pariputs(ep? ep->name:"#");
                   1113:       print_def_arg(*arg);
                   1114:       if (i == narg) break;
                   1115:       pariputs(", ");
                   1116:     }
                   1117:     pariputs("); ");
                   1118:   }
                   1119:   pariputs((char*)q);
                   1120: }
                   1121:
                   1122: static void
                   1123: print_user_member(entree *ep)
                   1124: {
                   1125:   GEN q = (GEN)ep->value;
                   1126:   entree *ep2;
                   1127:
                   1128:   q++; /* skip initial NULL */
                   1129:   ep2 = varentries[*q++];
                   1130:   pariputs(ep2? ep2->name:"#");
                   1131:   pariputsf(".%s = ", ep->name);
                   1132:   pariputs((char*)q);
                   1133: }
                   1134:
                   1135: static void
                   1136: user_fun()
                   1137: {
                   1138:   entree *ep;
                   1139:   int hash;
                   1140:
                   1141:   for (hash = 0; hash < functions_tblsz; hash++)
                   1142:     for (ep = functions_hash[hash]; ep; ep = ep->next)
                   1143:       if (EpVALENCE(ep) == EpUSER)
                   1144:       {
                   1145:        pariputc(LBRACE); print_user_fun(ep);
                   1146:        pariputc(RBRACE); pariputs("\n\n");
                   1147:       }
                   1148: }
                   1149:
                   1150: static void
                   1151: user_member()
                   1152: {
                   1153:   entree *ep;
                   1154:   int hash;
                   1155:
                   1156:   for (hash = 0; hash < functions_tblsz; hash++)
                   1157:     for (ep = members_hash[hash]; ep; ep = ep->next)
                   1158:       if (EpVALENCE(ep) == EpMEMBER)
                   1159:       {
                   1160:        pariputc(LBRACE); print_user_member(ep);
                   1161:        pariputc(RBRACE); pariputs("\n\n");
                   1162:       }
                   1163: }
                   1164:
                   1165: static void
                   1166: center(char *s)
                   1167: {
                   1168:   long i, pad = term_width() - strlen(s);
                   1169:   char *u = thestring;
                   1170:
                   1171:   if (pad<0) pad=0; else pad >>= 1;
                   1172:   for (i=0; i<pad; i++) *u++ = ' ';
                   1173:   while (*s) *u++ = *s++;
                   1174:   *u++='\n'; *u=0; pariputs(thestring);
                   1175: }
                   1176:
                   1177: static void
                   1178: community()
                   1179: {
                   1180:   long len = strlen(GPMISCDIR) + 1024;
                   1181:   char *s = gpmalloc(len);
                   1182:
                   1183:   sprintf(s, "The standard distribution of GP/PARI includes a reference \
                   1184: manual, a tutorial, a reference card and quite a few examples. They should \
                   1185: have been installed in the directory '%s'. If not you should ask the person \
                   1186: who installed PARI on your system where they can be found. You can also \
                   1187: download them from the PARI WWW site 'http://www.parigp-home.de/'",
                   1188: GPMISCDIR);
                   1189:   print_text(s); free(s);
                   1190:
                   1191:   pariputs("\nThree mailing lists are devoted to PARI:\n\
                   1192:   - pari-announce (moderated) to announce major version changes.\n\
                   1193:   - pari-dev for everything related to the development of PARI, including\n\
                   1194:     suggestions, technical questions, bug reports and patch submissions.\n\
                   1195:   - pari-users for everything else!\n");
                   1196:   print_text("\
                   1197: To subscribe, send an empty message to <listname>-subscribe@list.cr.yp.to. You \
                   1198: can only send messages to the lists you have subscribed to! An archive is kept \
                   1199: at the WWW site mentioned above. You can also reach the authors directly by \
                   1200: email: pari@math.u-bordeaux.fr (answer not guaranteed)."); }
                   1201:
                   1202: static void
                   1203: gentypes(void)
                   1204: {
                   1205:   pariputs("List of the PARI types:\n\
                   1206:   t_INT    : long integers     [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
                   1207:   t_REAL   : long real numbers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
                   1208:   t_INTMOD : integermods       [ code ] [ mod  ] [ integer ]\n\
                   1209:   t_FRAC   : irred. rationals  [ code ] [ num. ] [ den. ]\n\
                   1210:   t_FRACN  : rational numbers  [ code ] [ num. ] [ den. ]\n\
                   1211:   t_COMPLEX: complex numbers   [ code ] [ real ] [ imag ]\n\
                   1212:   t_PADIC  : p-adic numbers    [ cod1 ] [ cod2 ] [ p ] [ p^r ] [ int ]\n\
                   1213:   t_QUAD   : quadratic numbers [ cod1 ] [ mod  ] [ real ] [ imag ]\n\
                   1214:   t_POLMOD : poly mod          [ code ] [ mod  ] [ polynomial ]\n\
                   1215:   -------------------------------------------------------------\n\
                   1216:   t_POL    : polynomials       [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
                   1217:   t_SER    : power series      [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
                   1218:   t_RFRAC  : irred. rat. func. [ code ] [ num. ] [ den. ]\n\
                   1219:   t_RFRACN : rational function [ code ] [ num. ] [ den. ]\n\
                   1220:   t_QFR    : real qfb          [ code ] [ a ] [ b ] [ c ] [ del ]\n\
                   1221:   t_QFI    : imaginary qfb     [ code ] [ a ] [ b ] [ c ]\n\
                   1222:   t_VEC    : row vector        [ code ] [  x_1  ] ... [  x_k  ]\n\
                   1223:   t_COL    : column vector     [ code ] [  x_1  ] ... [  x_k  ]\n\
                   1224:   t_MAT    : matrix            [ code ] [ col_1 ] ... [ col_k ]\n\
                   1225:   t_LIST   : list              [ code ] [ cod2 ] [ x_1 ] ... [ x_k ]\n\
                   1226:   t_STR    : string            [ code ] [ man_1 ] ... [ man_k ]\n\
                   1227: \n");
                   1228: }
                   1229:
                   1230: static void
                   1231: menu_commands(void)
                   1232: {
                   1233:   pariputs("Help topics:\n\
                   1234:   0: list of user-defined identifiers (variable, alias, function)\n\
                   1235:   1: Standard monadic or dyadic OPERATORS\n\
                   1236:   2: CONVERSIONS and similar elementary functions\n\
                   1237:   3: TRANSCENDENTAL functions\n\
                   1238:   4: NUMBER THEORETICAL functions\n\
                   1239:   5: Functions related to ELLIPTIC CURVES\n\
                   1240:   6: Functions related to general NUMBER FIELDS\n\
                   1241:   7: POLYNOMIALS and power series\n\
                   1242:   8: Vectors, matrices, LINEAR ALGEBRA and sets\n\
                   1243:   9: SUMS, products, integrals and similar functions\n\
                   1244:  10: GRAPHIC functions\n\
                   1245:  11: PROGRAMMING under GP\n\
                   1246:  12: The PARI community\n\
                   1247: \n\
                   1248: Further help (list of relevant functions): ?n (1<=n<=11).\n\
                   1249: Also:\n\
                   1250:   ? functionname (short on-line help)\n\
                   1251:   ?\\             (keyboard shortcuts)\n\
                   1252:   ?.             (member functions)\n");
                   1253:   if (has_ext_help()) pariputs("\
                   1254: Extended help looks available:\n\
                   1255:   ??             (opens the full user's manual in a dvi previewer)\n\
                   1256:   ??  tutorial   (same with the GP tutorial)\n\
                   1257:   ??  refcard    (same with the GP reference card)\n\
                   1258: \n\
                   1259:   ??  keyword    (long help text about \"keyword\" from the user's manual)\n\
                   1260:   ??? keyword    (a propos: list of related functions).");
                   1261: }
                   1262:
                   1263: static void
                   1264: slash_commands(void)
                   1265: {
                   1266:   pariputs("#       : enable/disable timer\n\
                   1267: ##      : print time for last result\n\
                   1268: \\\\      : comment up to end of line\n\
                   1269: \\a {n}  : print result in raw format (readable by PARI)\n\
                   1270: \\b {n}  : print result in beautified format\n\
                   1271: \\c      : list all commands (same effect as ?*)\n\
                   1272: \\d      : print all defaults\n\
                   1273: \\e {n}  : enable/disable echo (set echo=n)\n\
                   1274: \\g {n}  : set debugging level\n\
                   1275: \\gf{n}  : set file debugging level\n\
                   1276: \\gm{n}  : set memory debugging level\n\
                   1277: \\h {m-n}: hashtable information\n\
                   1278: \\l {f}  : enable/disable logfile (set logfile=f)\n\
                   1279: \\m {n}  : print result in prettymatrix format\n\
                   1280: \\o {n}  : change output method (0=raw, 1=prettymatrix, 2=prettyprint)\n\
                   1281: \\p {n}  : change real precision\n\
                   1282: \\ps{n}  : change series precision\n\
                   1283: \\q      : quit completely this GP session\n\
                   1284: \\r {f}  : read in a file\n\
                   1285: \\s {n}  : print stack information\n\
                   1286: \\t      : print the list of PARI types\n\
                   1287: \\u      : print the list of user-defined functions\n\
                   1288: \\um     : print the list of user-defined member functions\n\
                   1289: \\v      : print current version of GP\n\
                   1290: \\w {nf} : write to a file\n\
                   1291: \\x {n}  : print complete inner structure of result\n\
                   1292: \\y {n}  : disable/enable automatic simplification (set simplify=n)\n\
                   1293: \n\
                   1294: {f}=optional filename. {n}=optional integer\n");
                   1295: }
                   1296:
                   1297: static void
                   1298: member_commands(void)
                   1299: {
                   1300:   pariputs("Member functions, followed by relevant objects\n\n\
                   1301: a1-a6, b2-b8, c4-c6 : coeff. of the curve.            ell\n\
                   1302: area : area                                           ell\n\
                   1303: bnf  : big number field                                        bnf, bnr\n\
                   1304: clgp : class group                                             bnf, bnr\n\
                   1305: cyc  : cyclic decomposition (SNF)               clgp           bnf, bnr\n\
                   1306: diff, codiff: different and codifferent                    nf, bnf, bnr\n\
                   1307: disc : discriminant                                   ell, nf, bnf, bnr\n\
                   1308: e, f : inertia/residues degree            prid\n\
                   1309: fu   : fundamental units                                       bnf, bnr\n\
                   1310: futu : [u,w] where u=unit group, w=torsion                     bnf, bnr\n\
                   1311: gen  : generators                         prid, clgp           bnf, bnr\n\
                   1312: j    : j-invariant                                    ell\n\
                   1313: mod  : modulus\n\
                   1314: nf   : number field                                            bnf, bnr\n\
                   1315: no   : number of elements                       clgp           bnf, bnr\n\
                   1316: omega, eta: [omega1,omega2] and [eta1, eta2]          ell\n\
                   1317: p    : rational prime contained in prid   prid\n\
                   1318: pol  : defining polynomial                                 nf, bnf, bnr\n\
                   1319: reg  : regulator                                               bnf, bnr\n\
                   1320: roots: roots                                          ell  nf, bnf, bnr\n\
                   1321: sign : signature                                           nf, bnf, bnr\n\
                   1322: t2   : t2 matrix                                           nf, bnf, bnr\n\
                   1323: tate : Tate's [u^2,u,q]                               ell\n\
                   1324: tu   : torsion unit and its order                              bnf, bnr\n\
                   1325: tufu : [w,u] where u=unit group, w=torsion                     bnf, bnr\n\
                   1326: w    : Mestre's w                                     ell\n\
                   1327: zk   : integral basis                                      nf, bnf, bnr\n\
                   1328: zkst : structure of (Z_K/m)^* (valid for idealstar also)            bnr\n");
                   1329: }
                   1330:
                   1331: #define QUOTE "_QUOTE"
                   1332: #define DOUBQUOTE "_DOUBQUOTE"
                   1333: #define BACKQUOTE "_BACKQUOTE"
                   1334:
                   1335: static char *
                   1336: _cat(char *s, char *t)
                   1337: {
                   1338:   *s = 0; strcat(s,t); return s + strlen(t);
                   1339: }
                   1340:
                   1341: static char *
                   1342: filter_quotes(char *s)
                   1343: {
                   1344:   int i, l = strlen(s);
                   1345:   int quote = 0;
                   1346:   int backquote = 0;
                   1347:   int doubquote = 0;
                   1348:   char *str, *t;
                   1349:
                   1350:   for (i=0; i < l; i++)
                   1351:     switch(s[i])
                   1352:     {
                   1353:       case '\'': quote++; break;
                   1354:       case '`' : backquote++; break;
                   1355:       case '"' : doubquote++;
                   1356:     }
                   1357:   str = (char*)gpmalloc(l + quote * (strlen(QUOTE)-1)
                   1358:                           + doubquote * (strlen(DOUBQUOTE)-1)
                   1359:                           + backquote * (strlen(BACKQUOTE)-1) + 1);
                   1360:   t = str;
                   1361:   for (i=0; i < l; i++)
                   1362:     switch(s[i])
                   1363:     {
                   1364:       case '\'': t = _cat(t, QUOTE); break;
                   1365:       case '`' : t = _cat(t, BACKQUOTE); break;
                   1366:       case '"' : t = _cat(t, DOUBQUOTE); break;
                   1367:       default: *t++ = s[i];
                   1368:     }
                   1369:   *t = 0; return str;
                   1370: }
                   1371:
                   1372: #define MAX_LINE_LEN 255
                   1373: static void
                   1374: external_help(char *s, int num)
                   1375: {
                   1376:   long nbli = term_height()-3, li = 0;
                   1377:   char buf[MAX_LINE_LEN+1], *str, *opt = "", *ar = "";
                   1378:   pariFILE *z;
                   1379:   FILE *f;
                   1380:
                   1381:   if (!help_prg) err(talker,"no external help program");
                   1382:   s = filter_quotes(s);
                   1383:   str = gpmalloc(strlen(help_prg) + strlen(s) + 64);
                   1384:   if (num < 0)
                   1385:     opt = "-k";
                   1386:   else if (s[strlen(s)-1] != '@')
                   1387:     { ar = thestring; sprintf(ar,"@%d",num); }
                   1388:   sprintf(str,"%s -fromgp %s %c%s%s%c",help_prg,opt, SHELL_Q,s,ar,SHELL_Q);
                   1389:   z = try_pipe(str,0); f = z->file;
                   1390:   free(str); free(s);
                   1391:   while (fgets(buf,MAX_LINE_LEN,f))
                   1392:   {
                   1393:     if (!strncmp("ugly_kludge_done",buf,16)) break;
                   1394:     buf[MAX_LINE_LEN]=0; pariputs(buf);
                   1395:     if (++li > nbli) { hit_return(); li = 0; }
                   1396:   }
                   1397:   pari_fclose(z);
                   1398: }
                   1399:
                   1400: char *keyword_list[]={
                   1401:   "operator",
                   1402:   "user",
                   1403:   "member",
                   1404:   "integer",
                   1405:   "real",
                   1406:   "readline",
                   1407:   "refcard",
                   1408:   "tutorial",
                   1409:   "nf",
                   1410:   "bnf",
                   1411:   "bnr",
                   1412:   "ell",
                   1413:   NULL
                   1414: };
                   1415:
                   1416: static int
                   1417: ok_external_help(char *s)
                   1418: {
                   1419:   long n;
                   1420:   if (!*s) return 1;
                   1421:   if (!isalpha((int)*s)) return 3; /* operator or section number */
                   1422:   if (!strncmp(s,"t_",2)) return 2; /* type name */
                   1423:
                   1424:   for (n=0; keyword_list[n]; n++)
                   1425:     if (!strcmp(s,keyword_list[n])) return 3;
                   1426:   return 0;
                   1427: }
                   1428:
                   1429: /* don't mess readline display */
                   1430: static void
                   1431: aide_print(char *s1, char *s2, int flag)
                   1432: {
                   1433:   if ((flag & h_RL) == 0) err(talker, "%s: %s", s1, s2);
                   1434:   pariputsf("%s: %s\n", s1, s2);
                   1435: }
                   1436:
                   1437: static void
                   1438: aide0(char *s, int flag)
                   1439: {
                   1440:   long n, long_help = flag & h_LONG;
                   1441:   entree *ep,*ep1;
                   1442:   char *s1;
                   1443:
                   1444:   s = get_sep(s);
                   1445:   if (isdigit((int)*s))
                   1446:   {
                   1447:     n=atoi(s);
                   1448:     if (n == 12) { community(); return; }
                   1449:     if (n<0 || n > 12)
                   1450:       err(talker2,"no such section in help: ?",s,s);
                   1451:     if (long_help) external_help(s,3); else commands(n);
                   1452:     return;
                   1453:   }
                   1454:   /* Get meaningful entry on \ps 5 */
                   1455:   if (*s == '\\') { s1 = s+1; skip_alpha(s1); *s1 = '\0';}
                   1456:
                   1457:   if (flag & h_APROPOS) { external_help(s,-1); return; }
                   1458:   if (long_help && (n = ok_external_help(s))) { external_help(s,n); return; }
                   1459:   switch (*s)
                   1460:   {
                   1461:     case '*' : commands(-1); return;
                   1462:     case '\0': menu_commands(); return;
                   1463:     case '\\': slash_commands(); return;
                   1464:     case '.' : member_commands(); return;
                   1465:   }
                   1466:   ep = is_entry(s);
                   1467:   if (ep && long_help)
                   1468:   {
                   1469:     if (!strcmp(ep->name, "default"))
                   1470:     {
                   1471:       char *t = s+7, *e;
                   1472:       skip_space(t);
                   1473:       if (*t == '(') {
                   1474:        t++; skip_space(t);
                   1475:         e = t; skip_alpha(e); *e = '\0'; /* safe: get_sep() made it a copy */
                   1476:        if (is_default(t)) { external_help(t, 2); return; }
                   1477:       }
                   1478:     }
                   1479:   }
                   1480:   if (!ep)
                   1481:   {
                   1482:     n = is_default(s)? 2: 3;
                   1483:     if (long_help)
                   1484:       external_help(s,n);
                   1485:     else
                   1486:     {
                   1487:       if (n == 2) { aide_print(s,"default",h_RL); return; }
                   1488:       n = whatnow(s,1);
                   1489:       if (n) err(obsoler,s,s, s,n);
                   1490:       aide_print(s,"unknown identifier",flag);
                   1491:     }
                   1492:     return;
                   1493:   }
                   1494:
                   1495:   ep1 = ep;  ep = do_alias(ep);
                   1496:   if (ep1 != ep) pariputsf("%s is aliased to:\n\n",s);
                   1497:
                   1498:   switch(EpVALENCE(ep))
                   1499:   {
                   1500:     case EpUSER:
                   1501:       if (!ep->help || long_help) print_user_fun(ep);
                   1502:       if (!ep->help) return;
                   1503:       if (long_help) { pariputs("\n\n"); long_help=0; }
                   1504:       break;
                   1505:
                   1506:     case EpGVAR:
                   1507:     case EpVAR:
                   1508:       if (!ep->help) { aide_print(s, "user defined variable",h_RL); return; }
                   1509:       long_help=0; break;
                   1510:
                   1511:     case EpINSTALL:
                   1512:       if (!ep->help) { aide_print(s, "installed function",h_RL); return; }
                   1513:       long_help=0; break;
                   1514:   }
                   1515:   if (long_help) { external_help(ep->name,3); return; }
                   1516:   if (ep->help) { print_text(ep->help); return; }
                   1517:
                   1518:   err(bugparier,"aide (no help found)");
                   1519: }
                   1520:
                   1521: void
                   1522: aide(char *s, int flag)
                   1523: {
                   1524:   if ((flag & h_RL) == 0)
                   1525:   {
                   1526:     if (*s == '?') { flag |= h_LONG; s++; }
                   1527:     if (*s == '?') { flag |= h_APROPOS; s++; }
                   1528:   }
                   1529:   term_color(c_HELP); aide0(s,flag); term_color(c_NONE);
                   1530:   if ((flag & h_RL) == 0) pariputc('\n');
                   1531: }
                   1532:
                   1533: /********************************************************************/
                   1534: /**                                                                **/
                   1535: /**                         METACOMMANDS                           **/
                   1536: /**                                                                **/
                   1537: /********************************************************************/
                   1538:
                   1539: static void
                   1540: print_entree(entree *ep, long hash)
                   1541: {
                   1542:   pariputsf(" %s ",ep->name); pariputsf(VOIR_STRING1,(ulong)ep);
                   1543:   pariputsf(":\n   hash = %3ld, valence = %3ld, menu = %2ld, code = %s\n",
                   1544:             hash, ep->valence, ep->menu, ep->code? ep->code: "NULL");
                   1545:   if (ep->next)
                   1546:   {
                   1547:     pariputsf("   next = %s ",(ep->next)->name);
                   1548:     pariputsf(VOIR_STRING1,(ulong)(ep->next));
                   1549:   }
                   1550:   pariputs("\n");
                   1551: }
                   1552:
                   1553: static void
                   1554: print_hash_list(char *s)
                   1555: {
                   1556:   long m,n;
                   1557:   entree *ep;
                   1558:
                   1559:   if (isalpha((int)*s))
                   1560:   {
                   1561:     ep = is_entry_intern(s,functions_hash,&n);
                   1562:     if (!ep) err(talker,"no such function");
                   1563:     print_entree(ep,n); return;
                   1564:   }
                   1565:   if (isdigit((int)*s) || *s == '$')
                   1566:   {
                   1567:     m = functions_tblsz-1; n = atol(s);
                   1568:     if (*s=='$') n = m;
                   1569:     if (m<n) err(talker,"invalid range in print_entree");
                   1570:     while (isdigit((int)*s)) s++;
                   1571:
                   1572:     if (*s++ != '-') m = n;
                   1573:     else
                   1574:     {
                   1575:       if (*s !='$') m = min(atol(s),m);
                   1576:       if (m<n) err(talker,"invalid range in print_entree");
                   1577:     }
                   1578:
                   1579:     for(; n<=m; n++)
                   1580:     {
                   1581:       pariputsf("*** hashcode = %ld\n",n);
                   1582:       for (ep=functions_hash[n]; ep; ep=ep->next)
                   1583:        print_entree(ep,n);
                   1584:     }
                   1585:     return;
                   1586:   }
                   1587:   if (*s=='-')
                   1588:   {
                   1589:     for (n=0; n<functions_tblsz; n++)
                   1590:     {
                   1591:       m=0;
                   1592:       for (ep=functions_hash[n]; ep; ep=ep->next) m++;
                   1593:       pariputsf("%3ld:%3ld ",n,m);
                   1594:       if (n%9 == 8) pariputc('\n');
                   1595:     }
                   1596:     pariputc('\n'); return;
                   1597:   }
                   1598:   for (n=0; n<functions_tblsz; n++)
                   1599:     for (ep=functions_hash[n]; ep; ep=ep->next)
                   1600:       print_entree(ep,n);
                   1601: }
                   1602:
                   1603: static char *
                   1604: what_readline()
                   1605: {
                   1606: #ifdef READLINE
                   1607:   if (use_readline)
                   1608:     return "v"READLINE" enabled";
                   1609:   else
                   1610: #endif
                   1611:   return "disabled";
                   1612: }
                   1613:
                   1614: static void
                   1615: print_version()
                   1616: {
                   1617:   char buf[64];
                   1618:
                   1619:   center(PARIVERSION); center(PARIINFO);
                   1620:   sprintf(buf,"(readline %s, extended help%s available)", what_readline(),
                   1621:           has_ext_help()? "": " not");
                   1622:   center(buf);
                   1623: }
                   1624:
                   1625: static void
                   1626: gp_head()
                   1627: {
                   1628:   print_version(); pariputs("\n");
                   1629:   center("Copyright (C) 2000 The PARI Group");
                   1630:   print_text("\nPARI/GP is free software, covered by the GNU General Public \
                   1631: License, and comes WITHOUT ANY WARRANTY WHATSOEVER");
                   1632:   pariputs("\n\
                   1633: Type ? for help, \\q to quit.\n\
                   1634: Type ?12 for how to get moral (and possibly technical) support.\n\n");
                   1635:   sd_realprecision  ("",d_ACKNOWLEDGE);
                   1636:   sd_seriesprecision("",d_ACKNOWLEDGE);
                   1637:   sd_format         ("",d_ACKNOWLEDGE);
                   1638:   pariputsf("\nparisize = %ld, primelimit = %ld\n", parisize, primelimit);
                   1639: }
                   1640:
                   1641: static void
                   1642: fix_buffer(Buffer *b, long newlbuf)
                   1643: {
                   1644:   b->buf = gprealloc(b->buf, newlbuf, b->len);
                   1645:   b->len = paribufsize = newlbuf;
                   1646: }
                   1647:
                   1648: void
                   1649: gp_quit()
                   1650: {
                   1651:   free_graph(); freeall();
                   1652:   kill_all_buffers(NULL);
                   1653:   if (INIT_SIG) pari_sig_init(SIG_DFL);
                   1654:   term_color(c_NONE);
                   1655:   pariputs_opt("Goodbye!\n");
                   1656:   if (under_texmacs) tm_end_output();
                   1657:   exit(0);
                   1658: }
                   1659:
                   1660: /* history management function:
                   1661:  *   flag < 0, called from freeall()
                   1662:  *   flag = 0, called from %num in anal.c:truc()
                   1663:  *   flag > 0, called from %` in anal.c:truc(), p > 0
                   1664:  */
                   1665: static GEN
                   1666: gp_history(long p, long flag, char *old, char *entrypoint)
                   1667: {
                   1668:   int er1 = 0;
                   1669:   if (flag < 0) { free((void *)hist); return NULL; }
                   1670:   if (!tglobal) er1 = 1;
                   1671:   if (flag)
                   1672:   {
                   1673:     p = tglobal - p;
                   1674:     if (p <= 0) er1 = 1;
                   1675:   }
                   1676:   else if (p > tglobal)
                   1677:     err(talker2,"I can't see into the future",old,entrypoint);
                   1678:   if (!p) p = tglobal;
                   1679:   if (tglobal - p >= histsize) er1 = 1;
                   1680:   p = (p-1) % histsize;
                   1681:   if (er1 || !hist[p])
                   1682:     err(talker2,"I can't remember before the big bang",old,entrypoint);
                   1683:   return hist[p];
                   1684: }
                   1685:
                   1686: extern char *GENtostr0(GEN x, void(*do_out)(GEN));
                   1687:
                   1688: static void
                   1689: texmacs_output(GEN z, long n)
                   1690: {
                   1691:   char *sz = GENtostr0(z, &outtex);
                   1692:   printf("%clatex:", DATA_BEGIN);
                   1693:   printf("\\magenta\\%%%ld = $\\blue ", n);
                   1694:   printf("%s$%c", sz,DATA_END); free(sz);
                   1695:   fflush(stdout);
                   1696: }
                   1697:
                   1698: /* Wait for prettyprinter for finish, to prevent new prompt from overwriting
                   1699:  * the output.  Fill the output buffer, wait until it is read.
                   1700:  * Better than sleep(2): give possibility to print */
                   1701: static void
                   1702: prettyp_wait()
                   1703: {
                   1704:   char *s = "                                                     \n";
                   1705:   int i = 400;
                   1706:
                   1707:   pariputs("\n\n"); pariflush(); /* start translation */
                   1708:   while (--i) pariputs(s);
                   1709:   pariputs("\n"); pariflush();
                   1710: }
                   1711:
                   1712: /* initialise external prettyprinter (tex2mail) */
                   1713: static int
                   1714: prettyp_init()
                   1715: {
                   1716:   if (!prettyprinter_file)
                   1717:     prettyprinter_file = try_pipe(prettyprinter, mf_OUT | mf_TEST);
                   1718:   if (prettyprinter_file) return 1;
                   1719:
                   1720:   err(warner,"broken prettyprinter: '%s'",prettyprinter);
                   1721:   if (prettyprinter != prettyprinter_dft) free(prettyprinter);
                   1722:   prettyprinter = NULL; return 0;
                   1723: }
                   1724:
                   1725: /* n = history number. if n = 0 no history */
                   1726: static int
                   1727: tex2mail_output(GEN z, long n)
                   1728: {
                   1729:   FILE *o_out;
                   1730:   int o_prettyp;
                   1731:
                   1732:   if (!(prettyprinter && prettyp_init())) return 0;
                   1733:   o_out = pari_outfile; /* save state */
                   1734:   o_prettyp = prettyp;
                   1735:
                   1736:   /* Emit first: there may be lines before the prompt */
                   1737:   if (n) term_color(c_OUTPUT);
                   1738:   pariflush();
                   1739:   pari_outfile = prettyprinter_file->file;
                   1740:   prettyp = f_TEX;
                   1741:
                   1742:   /* history number */
                   1743:   if (n)
                   1744:   {
                   1745:     if (*term_get_color(c_HIST) || *term_get_color(c_OUTPUT))
                   1746:     {
                   1747:       char col1[80];
                   1748:       strcpy(col1, term_get_color(c_HIST));
                   1749:       sprintf(thestring, "\\LITERALnoLENGTH{%s}\\%%%ld = \\LITERALnoLENGTH{%s}",
                   1750:               col1, n, term_get_color(c_OUTPUT));
                   1751:     }
                   1752:     else
                   1753:       sprintf(thestring, "\\%%%ld = ", n);
                   1754:     pariputs_opt(thestring);
                   1755:   }
                   1756:   /* output */
                   1757:   gp_output(z);
                   1758:
                   1759:   /* flush and restore */
                   1760:   prettyp_wait();
                   1761:   prettyp = o_prettyp;
                   1762:   pari_outfile = o_out;
                   1763:   if (n) term_color(c_NONE);
                   1764:   return 1;
                   1765: }
                   1766:
                   1767: static void
                   1768: normal_output(GEN z, long n)
                   1769: {
                   1770:   /* history number */
                   1771:   term_color(c_HIST);
                   1772:   sprintf(thestring, "%%%ld = ", n);
                   1773:   pariputs_opt(thestring);
                   1774:   /* output */
                   1775:   term_color(c_OUTPUT);
                   1776:   init_lim_lines(thestring,lim_lines);
                   1777:   gp_output(z);
                   1778:   init_lim_lines(NULL,lim_lines);
                   1779:   term_color(c_NONE); pariputc('\n');
                   1780: }
                   1781:
                   1782: static GEN
                   1783: gpreadbin(char *s)
                   1784: {
                   1785:   GEN x = readbin(s,infile);
                   1786:   popinfile(); return x;
                   1787: }
                   1788:
                   1789: static void
                   1790: escape0(char *tch)
                   1791: {
                   1792:   char *s, c;
                   1793:
                   1794:   if (compatible != NONE)
                   1795:   {
                   1796:     s = tch;
                   1797:     while (*s)
                   1798:       if (*s++ == '=')
                   1799:       {
                   1800:        GEN (*f)(char*, int) = NULL;
                   1801:        int len = (s-tch) - 1;
                   1802:
                   1803:        if (!strncmp(tch,"precision",len))         f = sd_realprecision;
                   1804:        else if (!strncmp(tch,"serieslength",len)) f = sd_seriesprecision;
                   1805:        else if (!strncmp(tch,"format",len))       f = sd_format;
                   1806:        else if (!strncmp(tch,"prompt",len))       f = sd_prompt;
                   1807:        if (f) { f(get_sep(s), d_ACKNOWLEDGE); return; }
                   1808:        break;
                   1809:       }
                   1810:   }
                   1811:   s = tch;
                   1812:   switch ((c = *s++))
                   1813:   {
                   1814:     case 'w': case 'x': case 'a': case 'b': case 'B': case 'm':
                   1815:     { /* history things */
                   1816:       long d;
                   1817:       GEN x;
                   1818:       if (c != 'w' && c != 'x') d = get_int(s,0);
                   1819:       else
                   1820:       {
                   1821:        d = atol(s); if (*s == '-') s++;
                   1822:        while (isdigit((int)*s)) s++;
                   1823:       }
                   1824:       x = gp_history(d, 0, tch+1,tch-1);
                   1825:       switch (c)
                   1826:       {
                   1827:        case 'a': brute   (x, fmt.format, -1); break;
                   1828:        case 'm': matbrute(x, fmt.format, -1); break;
                   1829:        case 'B': if (tex2mail_output(x,0)) return;  /* fall through */
                   1830:        case 'b': sor     (x, fmt.format, -1, fmt.field); break;
                   1831:        case 'x': voir(x, get_int(s, -1));
                   1832:         case 'w':
                   1833:        {
                   1834:          GEN g[2]; g[0] = x; g[1] = NULL;
                   1835:          s = get_sep_colon_ok(s); if (!*s) s = current_logfile;
                   1836:          write0(s, g, f_RAW); return;
                   1837:        }
                   1838:       }
                   1839:       pariputc('\n'); return;
                   1840:     }
                   1841:
                   1842:     case 'c': commands(-1); break;
                   1843:     case 'd': help_default(); break;
                   1844:     case 'e':
                   1845:       s = get_sep(s);
                   1846:       if (!*s) s = pariecho?"0":"1";
                   1847:       sd_echo(s,d_ACKNOWLEDGE); break;
                   1848:     case 'g':
                   1849:       switch (*s)
                   1850:       {
                   1851:         case 'm': sd_debugmem(++s,d_ACKNOWLEDGE); break;
                   1852:         case 'f': sd_debugfiles(++s,d_ACKNOWLEDGE); break;
                   1853:         default : sd_debug(s,d_ACKNOWLEDGE); break;
                   1854:       }
                   1855:       break;
                   1856:     case 'h': print_hash_list(s); break;
                   1857:     case 'l':
                   1858:       s = get_sep_colon_ok(s);
                   1859:       if (*s)
                   1860:       {
                   1861:         sd_logfile(s,d_ACKNOWLEDGE);
                   1862:         if (logfile) break;
                   1863:       }
                   1864:       sd_log(logfile?"0":"1",d_ACKNOWLEDGE);
                   1865:       break;
                   1866:     case 'o': sd_output(s,d_ACKNOWLEDGE); break;
                   1867:     case 'p':
                   1868:       switch (*s)
                   1869:       {
                   1870:         case 's': sd_seriesprecision(++s,d_ACKNOWLEDGE); break;
                   1871:         default : sd_realprecision(s,d_ACKNOWLEDGE); break;
                   1872:       }
                   1873:       break;
                   1874:     case 'q': gp_quit(); break;
                   1875:     case 'r':
                   1876:       s = get_sep_colon_ok(s);
                   1877:       switchin(s);
                   1878:       if (file_is_binary(infile)) gpreadbin(s);
                   1879:       break;
                   1880:     case 's': etatpile(0); break;
                   1881:     case 't': gentypes(); break;
                   1882:     case 'u':
                   1883:       switch (*s)
                   1884:       {
                   1885:         case 'm': user_member(); break;
                   1886:         default: user_fun();
                   1887:       }
                   1888:       break;
                   1889:     case 'v': print_version(); break;
                   1890:     case 'y':
                   1891:       s = get_sep(s);
                   1892:       if (!*s) s = simplifyflag?"0":"1";
                   1893:       sd_simplify(s,d_ACKNOWLEDGE); break;
                   1894:     default: err(caracer1,tch-1,tch-2);
                   1895:   }
                   1896: }
                   1897:
                   1898: static void
                   1899: escape(char *tch)
                   1900: {
                   1901:   char *old = _analyseur();
                   1902:   _set_analyseur(tch); /* for error messages */
                   1903:   escape0(tch);
                   1904:   _set_analyseur(old);
                   1905: }
                   1906: /********************************************************************/
                   1907: /*                                                                  */
                   1908: /*                              GPRC                                */
                   1909: /*                                                                  */
                   1910: /********************************************************************/
                   1911: #if defined(UNIX) || defined(__EMX__)
                   1912: #  include <pwd.h>
                   1913: #endif
                   1914:
                   1915: static int
                   1916: get_preproc_value(char *s)
                   1917: {
                   1918:   if (!strncmp(s,"EMACS",5)) return under_emacs || under_texmacs;
                   1919:   if (!strncmp(s,"READL",5))
                   1920:   {
                   1921: #ifdef READLINE
                   1922:   if (use_readline)
                   1923:     return 1;
                   1924:   else
                   1925: #endif
                   1926:   return 0;
                   1927:   }
                   1928:   return -1;
                   1929: }
                   1930:
                   1931: /* return $HOME or the closest we can find */
                   1932: static char *
                   1933: get_home(int *free_it)
                   1934: {
                   1935:   char *drv, *pth = os_getenv("HOME");
                   1936:   if (pth) return pth;
                   1937:   if ((drv = os_getenv("HOMEDRIVE"))
                   1938:    && (pth = os_getenv("HOMEPATH")))
                   1939:   { /* looks like WinNT */
                   1940:     char *buf = gpmalloc(strlen(pth) + strlen(drv) + 1);
                   1941:     sprintf(buf, "%s%s",drv,pth);
                   1942:     *free_it = 1; return buf;
                   1943:   }
                   1944: #if defined(__EMX__) || defined(UNIX)
                   1945:   {
                   1946:     struct passwd *p = getpwuid(geteuid());
                   1947:     if (p) return p->pw_dir;
                   1948:   }
                   1949: #endif
                   1950:   return ".";
                   1951: }
                   1952:
                   1953: static FILE *
                   1954: gprc_chk(char *s)
                   1955: {
                   1956:   FILE *f = fopen(s, "r");
                   1957:   if (f && !quiet_mode)
                   1958:   {
                   1959:     fprintferr("Reading GPRC: %s ...", s);
                   1960:     added_newline = 0;
                   1961:   }
                   1962:   return f;
                   1963: }
                   1964:
                   1965: /* Look for [._]gprc: $GPRC, then in $HOME, /, C:/ */
                   1966: static FILE *
                   1967: gprc_get()
                   1968: {
                   1969:   FILE *f = NULL;
                   1970:   char *str, *s, c;
                   1971:   long l;
                   1972: #ifdef macintosh
                   1973:   f = gprc_chk("gprc");
                   1974: #else
                   1975:   s = os_getenv("GPRC");
                   1976:   if (s) f = gprc_chk(s);
                   1977:   if (!f)
                   1978:   {
                   1979:     int free_it = 0;
                   1980:     s = get_home(&free_it); l = strlen(s); c = s[l-1];
                   1981:     str = strcpy(gpmalloc(l+7), s);
                   1982:     if (free_it) free(s);
                   1983:     s = str + l;
                   1984:     if (c != '/' && c != '\\') *s++ = '/';
                   1985: #ifdef UNIX
                   1986:     *s = '.'; /* .gprc */
                   1987: #else
                   1988:     *s = '_'; /* _gprc */
                   1989: #endif
                   1990:     strcpy(s+1, "gprc");
                   1991:     f = gprc_chk(str); /* in $HOME */
                   1992:     if (!f) f = gprc_chk(s); /* in . */
                   1993:     if (!f) f = gprc_chk("/etc/gprc");
                   1994:     if (!f) f = gprc_chk("C:/_gprc");
                   1995:     free(str);
                   1996:   }
                   1997: #endif
                   1998:   return f;
                   1999: }
                   2000:
                   2001: static int get_line_from_file(char *prompt, Buffer *b, FILE *file);
                   2002: #define err_gprc(s,t,u) { fprintferr("\n"); err(talker2,s,t,u); }
                   2003:
                   2004: static char **
                   2005: gp_initrc()
                   2006: {
                   2007:   char **flist, *s,*s1,*s2;
                   2008:   FILE *file = gprc_get();
                   2009:   long fnum = 4, find = 0;
                   2010:   Buffer *b;
                   2011:
                   2012:   if (!file) return NULL;
                   2013:   flist = (char **) gpmalloc(fnum * sizeof(char*));
                   2014:   b = new_buffer();
                   2015:   for(;;)
                   2016:   {
                   2017:     if (!get_line_from_file(NULL,b,file))
                   2018:     {
                   2019:       del_buffer(b);
                   2020:       if (!quiet_mode) fprintferr("Done.\n\n");
                   2021:       fclose(file); flist[find] = NULL;
                   2022:       return flist;
                   2023:     }
                   2024:     for (s = b->buf; *s; )
                   2025:     {
                   2026:       s1 = s; if (get_sep2(s)) s++;
                   2027:       s += strlen(s1); /* point to next expr */
                   2028:       if (*s1 == '#')
                   2029:       { /* preprocessor directive */
                   2030:         int z, NOT = 0;
                   2031:         s1++;
                   2032:         if (strncmp(s1,"if",2)) err_gprc("unknown directive",s1,b->buf);
                   2033:         s1 += 2;
                   2034:         if (!strncmp(s1,"not",3)) { NOT = !NOT; s1 += 3; }
                   2035:         if (*s1 == '!')           { NOT = !NOT; s1++; }
                   2036:         z = get_preproc_value(s1);
                   2037:        if (z < 0) err_gprc("unknown preprocessor variable",s1,b->buf);
                   2038:        if (NOT) z = !z;
                   2039:         if (!z) continue;
                   2040:         s1 += 5;
                   2041:       }
                   2042:       if (!strncmp(s1,"read",4))
                   2043:       { /* read file */
                   2044:        s1 += 4;
                   2045:        if (find == fnum-1)
                   2046:        {
                   2047:          long n = fnum << 1;
                   2048:          flist = (char**)gprealloc(flist, n*sizeof(char*),
                   2049:                                           fnum*sizeof(char*));
                   2050:          fnum = n;
                   2051:        }
                   2052:        flist[find++] = s2 = gpmalloc(strlen(s1) + 1);
                   2053:        if (*s1 == '"') (void)readstring(s1, s2);
                   2054:        else strcpy(s2,s1);
                   2055:       }
                   2056:       else
                   2057:       { /* set default */
                   2058:        s2 = s1; while (*s2 && *s2 != '=') s2++;
                   2059:        if (*s2 != '=') err_gprc("missing '='",s2,b->buf);
                   2060:        *s2++ = 0;
                   2061:        if (*s2 == '"') (void)readstring(s2, s2);
                   2062:        setdefault(s1,s2,d_INITRC);
                   2063:       }
                   2064:     }
                   2065:   }
                   2066: }
                   2067:
                   2068: /********************************************************************/
                   2069: /*                                                                  */
                   2070: /*                           GP MAIN LOOP                           */
                   2071: /*                                                                  */
                   2072: /********************************************************************/
                   2073: /* flag:
                   2074:  *   ti_NOPRINT   don't print
                   2075:  *   ti_REGULAR   print elapsed time (chrono = 1)
                   2076:  *   ti_LAST      print last elapsed time (##)
                   2077:  *   ti_INTERRUPT received a SIGINT
                   2078:  */
                   2079: static char *
                   2080: do_time(long flag)
                   2081: {
                   2082:   static long last = 0;
                   2083:   long delay = (flag == ti_LAST)? last: gptimer();
                   2084:   char *s;
                   2085:
                   2086:   last = delay;
                   2087:   switch(flag)
                   2088:   {
                   2089:     case ti_REGULAR:   s = "time = "; break;
                   2090:     case ti_INTERRUPT: s = "user interrupt after "; break;
                   2091:     case ti_LAST:      s = "  ***   last result computed in "; break;
                   2092:     default: return NULL;
                   2093:   }
                   2094:   strcpy(thestring,s); s=thestring+strlen(s);
                   2095:   strcpy(s, term_get_color(c_TIME)); s+=strlen(s);
                   2096:   if (delay >= 3600000)
                   2097:   {
                   2098:     sprintf(s, "%ldh, ", delay / 3600000); s+=strlen(s);
                   2099:     delay %= 3600000;
                   2100:   }
                   2101:   if (delay >= 60000)
                   2102:   {
                   2103:     sprintf(s, "%ldmn, ", delay / 60000); s+=strlen(s);
                   2104:     delay %= 60000;
                   2105:   }
                   2106:   if (delay >= 1000)
                   2107:   {
                   2108:     sprintf(s, "%ld,", delay / 1000); s+=strlen(s);
                   2109:     delay %= 1000;
                   2110:     if (delay < 100)
                   2111:     {
                   2112:       sprintf(s, "%s", (delay<10)? "00": "0");
                   2113:       s+=strlen(s);
                   2114:     }
                   2115:   }
                   2116:   sprintf(s, "%ld ms", delay); s+=strlen(s);
                   2117:   strcpy(s, term_get_color(c_NONE));
                   2118:   if (flag != ti_INTERRUPT) { s+=strlen(s); *s++='.'; *s++='\n'; *s=0; }
                   2119:   return thestring;
                   2120: }
                   2121:
                   2122: static void
                   2123: gp_handle_SIGINT()
                   2124: {
                   2125: #ifdef _WIN32
                   2126:   if (++win32ctrlc >= 5) _exit(3);
                   2127: #else
                   2128:   if (under_texmacs) tm_start_output();
                   2129:   err(siginter, do_time(ti_INTERRUPT));
                   2130: #endif
                   2131: }
                   2132:
                   2133: static void
                   2134: gp_sighandler(int sig)
                   2135: {
                   2136:   char *msg;
                   2137:   os_signal(sig,gp_sighandler);
                   2138:   switch(sig)
                   2139:   {
                   2140: #ifdef SIGBREAK
                   2141:     case SIGBREAK: gp_handle_SIGINT(); return;
                   2142: #endif
                   2143: #ifdef SIGINT
                   2144:     case SIGINT: gp_handle_SIGINT(); return;
                   2145: #endif
                   2146:
                   2147: #ifdef SIGSEGV
                   2148:     case SIGSEGV:
                   2149:       msg="GP (Segmentation Fault)";
                   2150:       break;
                   2151: #endif
                   2152:
                   2153: #ifdef SIGBUS
                   2154:     case SIGBUS:
                   2155:       msg="GP (Bus Error)";
                   2156:       break;
                   2157: #endif
                   2158:
                   2159: #ifdef SIGFPE
                   2160:     case SIGFPE:
                   2161:       msg="GP (Floating Point Exception)";
                   2162:       break;
                   2163: #endif
                   2164:
                   2165: #ifdef SIGPIPE
                   2166:     case SIGPIPE:
                   2167:       if (prettyprinter_file && pari_outfile == prettyprinter_file->file)
                   2168:       {
                   2169:         pariFILE *f = prettyprinter_file;
                   2170:         prettyprinter_file = NULL; /* to avoid oo recursion on error */
                   2171:         pari_outfile = stdout; pari_fclose(f);
                   2172:       }
                   2173:       err(talker, "Broken Pipe, resetting file stack...");
                   2174: #endif
                   2175:
                   2176:     default:
                   2177:       msg="signal handling";
                   2178:   }
                   2179:   err(bugparier,msg);
                   2180: }
                   2181:
                   2182: static void
                   2183: brace_color(char *s, int c, int force)
                   2184: {
                   2185:   if (disable_color || (gp_colors[c] == c_NONE && !force)) return;
                   2186: #ifdef RL_PROMPT_START_IGNORE
                   2187:   *s++ = RL_PROMPT_START_IGNORE;
                   2188: #endif
                   2189:   strcpy(s, term_get_color(c));
                   2190: #ifdef RL_PROMPT_START_IGNORE
                   2191:   s+=strlen(s);
                   2192:   *s++ = RL_PROMPT_END_IGNORE; *s = 0;
                   2193: #endif
                   2194: }
                   2195:
                   2196: static char *
                   2197: do_prompt()
                   2198: {
                   2199:   static char buf[MAX_PROMPT_LEN + 24]; /* + room for color codes */
                   2200:   char *s;
                   2201:
                   2202:   if (test_mode) return prompt;
                   2203:   s = buf; *s = 0;
                   2204:   /* escape sequences bug readline, so use special bracing (if available) */
                   2205:   brace_color(s, c_PROMPT, 0);
                   2206:   s += strlen(s);
                   2207:   if (filtre(s,NULL, f_COMMENT))
                   2208:     strcpy(s, COMMENTPROMPT);
                   2209:   else
                   2210:     do_strftime(prompt,s);
                   2211:   s += strlen(s);
                   2212:   brace_color(s, c_INPUT, 1); return buf;
                   2213: }
                   2214:
                   2215: static void
                   2216: unblock_SIGINT()
                   2217: {
                   2218: #ifdef USE_SIGRELSE
                   2219:   sigrelse(SIGINT);
                   2220: #elif USE_SIGSETMASK
                   2221:   sigsetmask(0);
                   2222: #endif
                   2223: }
                   2224:
                   2225: /* Read from file (up to '\n' or EOF) and copy at s0 (points in b->buf) */
                   2226: static char *
                   2227: file_input(Buffer *b, char **s0, FILE *file, int TeXmacs)
                   2228: {
                   2229:   int first = 1;
                   2230:   char *s = *s0;
                   2231:   long used0, used = s - b->buf;
                   2232:
                   2233:   used0 = used;
                   2234:   for(;;)
                   2235:   {
                   2236:     long left = b->len - used, ls;
                   2237:     /* if from TeXmacs, tell him we need input */
                   2238:     if (TeXmacs) { tm_start_output(); tm_end_output(); }
                   2239:
                   2240:     if (left < 512)
                   2241:     {
                   2242:       fix_buffer(b, b->len << 1);
                   2243:       left = b->len - used;
                   2244:       *s0 = b->buf + used0;
                   2245:     }
                   2246:     s = b->buf + used;
                   2247:     if (! fgets(s, left, file)) return first? NULL: *s0; /* EOF */
                   2248:     ls = strlen(s); first = 0;
                   2249:     if (ls+1 < left || s[ls-1] == '\n') return *s0; /* \n */
                   2250:     used += ls;
                   2251:   }
                   2252: }
                   2253:
                   2254: #ifdef READLINE
                   2255: static char *
                   2256: gprl_input(Buffer *b, char **s0, char *prompt)
                   2257: {
                   2258:   long used = *s0 - b->buf;
                   2259:   long left = b->len - used;
                   2260:   char *s;
                   2261:
                   2262:   if (! (s = readline(prompt)) ) return NULL; /* EOF */
                   2263:   if ((ulong)left < strlen(s))
                   2264:   {
                   2265:     fix_buffer(b, b->len << 1);
                   2266:     *s0 = b->buf + used;
                   2267:   }
                   2268:   return s;
                   2269: }
                   2270: #endif
                   2271:
                   2272: static void
                   2273: input_loop(Buffer *b, char *buf0, FILE *file, char *prompt)
                   2274: {
                   2275:   const int TeXmacs = (under_texmacs && file == stdin);
                   2276:   const int f_flag = prompt? f_REG: f_REG | f_KEEPCASE;
                   2277:   char *end, *s = b->buf, *buf = buf0;
                   2278:   int wait_for_brace = 0;
                   2279:   int wait_for_input = 0;
                   2280:
                   2281:   /* buffer is not empty, init filter */
                   2282:   (void)ask_filtre(f_INIT);
                   2283:   for(;;)
                   2284:   {
                   2285:     char *t = buf;
                   2286:     if (!ask_filtre(f_COMMENT))
                   2287:     { /* not in comment */
                   2288:       skip_space(t);
                   2289:       if (*t == LBRACE) { t++; wait_for_input = wait_for_brace = 1; }
                   2290:     }
                   2291:     end = filtre(t,s, f_flag);
                   2292:
                   2293:     if (!*s) { if (!wait_for_input) break; }
                   2294:     else
                   2295:     {
                   2296:       if (*(b->buf) == '?') break;
                   2297:
                   2298:       s = end-1; /* *s = last input char */
                   2299:       if (*s == '\\')
                   2300:       {
                   2301:       }
                   2302:       else if (*s == '=')
                   2303:       {
                   2304:         wait_for_input = 1; s++;
                   2305:       }
                   2306:       else
                   2307:       {
                   2308:        if (!wait_for_brace) break;
                   2309:        if (*s == RBRACE) { *s=0; break; }
                   2310:        s++;
                   2311:       }
                   2312:     }
                   2313:     /* read continuation line */
                   2314: #ifdef READLINE
                   2315:     if (!file) { free(buf); buf = gprl_input(b,&s,""); }
                   2316:     else
                   2317: #endif
                   2318:       buf = file_input(b,&s,file,TeXmacs);
                   2319:     if (!buf) break;
                   2320:   }
                   2321:   if (!file && buf) free(buf);
                   2322: }
                   2323:
                   2324: /* prompt = NULL --> from gprc. Return 1 if new input, and 0 if EOF */
                   2325: static int
                   2326: get_line_from_file(char *prompt, Buffer *b, FILE *file)
                   2327: {
                   2328:   const int TeXmacs = (under_texmacs && file == stdin);
                   2329:   char *buf, *s =  b->buf;
                   2330:
                   2331:   handle_C_C = 0;
                   2332:   while (! (buf = file_input(b,&s,file,TeXmacs)) )
                   2333:   { /* EOF */
                   2334:     if (!handle_C_C)
                   2335:     {
                   2336:       if (TeXmacs) tm_start_output();
                   2337:       return 0;
                   2338:     }
                   2339:     /* received ^C  in fgets, retry (as is "\n" were input) */
                   2340:   }
                   2341:   input_loop(b,buf,file,prompt);
                   2342:
                   2343:   if (*s && prompt) /* don't echo if from gprc */
                   2344:   {
                   2345:     if (pariecho)
                   2346:       { pariputs(prompt); pariputs(s); pariputc('\n'); }
                   2347:     else
                   2348:       if (logfile) fprintf(logfile, "%s%s\n",prompt,s);
                   2349:     pariflush();
                   2350:   }
                   2351:   if (under_texmacs) tm_start_output();
                   2352:   return 1;
                   2353: }
                   2354:
                   2355: /* request one line interactively.
                   2356:  * Return 0: EOF
                   2357:  *        1: got one line from readline or infile */
                   2358: #ifndef READLINE
                   2359: static int
                   2360: get_line_from_user(char *prompt, Buffer *b)
                   2361: {
                   2362:   pariputs(prompt);
                   2363:   return get_line_from_file(prompt,b,infile);
                   2364: }
                   2365: #else
                   2366: static int
                   2367: get_line_from_user(char *prompt, Buffer *b)
                   2368: {
                   2369:   if (use_readline)
                   2370:   {
                   2371:     static char *previous_hist = NULL;
                   2372:     char *buf, *s = b->buf;
                   2373:
                   2374:     if (! (buf = gprl_input(b,&s, prompt)) )
                   2375:     { /* EOF */
                   2376:       pariputs("\n"); return 0;
                   2377:     }
                   2378:     input_loop(b,buf,NULL,prompt);
                   2379:     unblock_SIGINT(); /* bug in readline 2.0: need to unblock ^C */
                   2380:
                   2381:     if (*s)
                   2382:     {
                   2383:       /* update history (don't add the same entry twice) */
                   2384:       if (!previous_hist || strcmp(s,previous_hist))
                   2385:       {
                   2386:         if (previous_hist) free(previous_hist);
                   2387:         previous_hist = pari_strdup(s); add_history(s);
                   2388:       }
                   2389:       /* update logfile */
                   2390:       if (logfile) fprintf(logfile, "%s%s\n",prompt,s);
                   2391:     }
                   2392:     return 1;
                   2393:   }
                   2394:   else
                   2395:   {
                   2396:     pariputs(prompt);
                   2397:     return get_line_from_file(prompt,b,infile);
                   2398:   }
                   2399: }
                   2400: #endif
                   2401:
                   2402: static int
                   2403: is_interactive()
                   2404: {
                   2405: #if defined(UNIX) || defined(__EMX__)
                   2406:   return (infile == stdin && !under_texmacs
                   2407:                           && (under_emacs || isatty(fileno(stdin))));
                   2408: #else
                   2409:   return (infile == stdin && !under_texmacs);
                   2410: #endif
                   2411: }
                   2412:
                   2413: /* return 0 if no line could be read (EOF) */
                   2414: static int
                   2415: read_line(char *promptbuf, Buffer *b)
                   2416: {
                   2417:   if (is_interactive())
                   2418:     return get_line_from_user(promptbuf, b);
                   2419:   else
                   2420:     return get_line_from_file(DFT_PROMPT,b,infile);
                   2421: }
                   2422:
                   2423: static void
                   2424: chron(char *s)
                   2425: {
                   2426:   if (*s)
                   2427:   {
                   2428:     char *old = s-1;
                   2429:     if (*s == '#') { pariputs(do_time(ti_LAST)); s++; }
                   2430:     if (*s) err(caracer1,s,old);
                   2431:   }
                   2432:   else { chrono = 1-chrono; sd_timer("",d_ACKNOWLEDGE); }
                   2433: }
                   2434:
                   2435: static int
                   2436: check_meta(char *buf)
                   2437: {
                   2438:   switch(*buf++)
                   2439:   {
                   2440:     case '?': aide(buf, h_REGULAR); break;
                   2441:     case '#': chron(buf); break;
                   2442:     case '\\': escape(buf); break;
                   2443:     case '\0': return 2;
                   2444:     default: return 0;
                   2445:   }
                   2446:   return 1;
                   2447: }
                   2448:
                   2449: /* If there are other buffers open (bufstack != NULL), we are doing an
                   2450:  * immediate read (with read, extern...) */
                   2451: static GEN
                   2452: gp_main_loop(int ismain)
                   2453: {
                   2454:   long av, i,j;
                   2455:   VOLATILE GEN z = gnil;
                   2456:   Buffer *b = new_buffer();
                   2457:   if (!setjmp(b->env))
                   2458:   {
                   2459:     b->flenv = 1;
                   2460:     push_stack(&bufstack, (void*)b);
                   2461:   }
                   2462:   for(; ; setjmp(b->env))
                   2463:   {
                   2464:     if (ismain)
                   2465:     {
                   2466:       static long tloc, outtyp;
                   2467:       tloc = tglobal; outtyp = prettyp; recover(0);
                   2468:       if (setjmp(environnement))
                   2469:       {
                   2470:         char *s = (char*)global_err_data;
                   2471:         if (s && *s) outerr(lisseq(s));
                   2472:        avma = top; parisize = top - bot;
                   2473:        j = tglobal - tloc; i = (tglobal-1)%histsize;
                   2474:        while (j)
                   2475:        {
                   2476:          gunclone(hist[i]); hist[i]=NULL;
                   2477:          if (!i) i = histsize;
                   2478:          i--; j--;
                   2479:        }
                   2480:         tglobal = tloc; prettyp = outtyp;
                   2481:         kill_all_buffers(b);
                   2482:       }
                   2483:     }
                   2484:     added_newline = 1;
                   2485:     if (paribufsize != b->len) fix_buffer(b, paribufsize);
                   2486:
                   2487:     for(;;)
                   2488:     {
                   2489:       int r;
                   2490:       r = read_line(do_prompt(), b);
                   2491:       if (!disable_color) term_color(c_NONE);
                   2492:       if (!r)
                   2493:       {
                   2494: #ifdef _WIN32
                   2495:        Sleep(10); if (win32ctrlc) dowin32ctrlc();
                   2496: #endif
                   2497:        if (popinfile()) gp_quit();
                   2498:        if (!ismain) { pop_buffer(); return z; }
                   2499:       }
                   2500:       else if (!check_meta(b->buf)) break;
                   2501:     }
                   2502:     if (ismain)
                   2503:     {
                   2504:       char c = b->buf[strlen(b->buf) - 1];
                   2505:       gpsilent = separe(c);
                   2506:       (void)gptimer();
                   2507:     }
                   2508:     av = avma;
                   2509:     z = readseq(b->buf, strictmatch);
                   2510:     if (!added_newline) pariputc('\n'); /* last output was print1() */
                   2511:     if (! ismain) continue;
                   2512:     if (chrono) pariputs(do_time(ti_REGULAR)); else do_time(ti_NOPRINT);
                   2513:     if (z == gnil) continue;
                   2514:
                   2515:     if (simplifyflag) z = simplify_i(z);
                   2516:     i = tglobal % histsize; tglobal++;
                   2517:     if (hist[i]) gunclone(hist[i]);
                   2518:     hist[i] = z = gclone(z); avma = av;
                   2519:     if (gpsilent) continue;
                   2520:
                   2521:     if (test_mode) { init80(0); gp_output(z); pariputc('\n'); }
                   2522:     else
                   2523:     {
                   2524:       if (under_texmacs)
                   2525:         texmacs_output(z,tglobal);
                   2526:       else if (prettyp != f_PRETTY || !tex2mail_output(z,tglobal))
                   2527:         normal_output(z,tglobal);
                   2528:     }
                   2529:     pariflush();
                   2530:   }
                   2531: }
                   2532:
                   2533: GEN
                   2534: read0(char *s)
                   2535: {
                   2536:   switchin(s);
                   2537:   if (file_is_binary(infile)) return gpreadbin(s);
                   2538:   return gp_main_loop(0);
                   2539: }
                   2540:
                   2541: static void
                   2542: check_secure(char *s)
                   2543: {
                   2544:   if (secure)
                   2545:     err(talker, "[secure mode]: system commands not allowed\nTried to run '%s'",s);
                   2546: }
                   2547:
                   2548: GEN
                   2549: extern0(char *s)
                   2550: {
                   2551:   check_secure(s);
                   2552:   infile = try_pipe(s, mf_IN)->file;
                   2553:   return gp_main_loop(0);
                   2554: }
                   2555:
                   2556: static int
                   2557: silent()
                   2558: {
                   2559:   if (gpsilent) return 1;
                   2560:   { char c = _analyseur()[1]; return separe(c); }
                   2561: }
                   2562:
                   2563: GEN
                   2564: default0(char *a, char *b, long flag)
                   2565: {
                   2566:   if (flag) flag=d_RETURN;
                   2567:   else
                   2568:     flag = silent()? d_SILENT: d_ACKNOWLEDGE;
                   2569:   return setdefault(a,b,flag);
                   2570: }
                   2571:
                   2572: GEN
                   2573: input0()
                   2574: {
                   2575:   Buffer *b = new_buffer();
                   2576:   GEN x;
                   2577:
                   2578:   push_stack(&bufstack, (void*)b);
                   2579:   while (! get_line_from_file(DFT_INPROMPT,b,infile))
                   2580:     if (popinfile()) { fprintferr("no input ???"); gp_quit(); }
                   2581:   x = lisseq(b->buf);
                   2582:   pop_buffer(); return x;
                   2583: }
                   2584:
                   2585: void
                   2586: system0(char *s)
                   2587: {
                   2588: #if defined(UNIX) || defined(__EMX__)
                   2589:   check_secure(s);
                   2590:   system(s);
                   2591: #else
                   2592:   err(archer);
                   2593: #endif
                   2594: }
                   2595:
                   2596: void
                   2597: error0(GEN *g)
                   2598: {
                   2599:   term_color(c_ERR);
                   2600:   if (!added_newline) pariputc('\n');
                   2601:   pariputs("###   User error:\n\n   ");
                   2602:   print0(g,f_RAW); term_color(c_NONE);
                   2603:   err_recover(talker);
                   2604: }
                   2605:
                   2606: void errcontext(char *msg, char *s, char *entry);
                   2607:
                   2608: int
                   2609: break_loop(long numerr)
                   2610: {
                   2611:   static FILE *oldinfile = NULL;
                   2612:   static char *old = NULL;
                   2613:   static Buffer *b = NULL;
                   2614:   VOLATILE int go_on = 0;
                   2615:   char *s, *t, *msg;
                   2616:
                   2617:   if (b) jump_to_given_buffer(b);
                   2618:   push_stack(&bufstack, (void*)new_buffer());
                   2619:   b = current_buffer; /* buffer created above */
                   2620:   if (setjmp(b->env))
                   2621:   {
                   2622:     msg = "back to break loop";
                   2623:     s = t = NULL;
                   2624:   }
                   2625:   else
                   2626:   {
                   2627:     Buffer *oldb = (Buffer*)bufstack->prev->value;
                   2628:     msg = "Starting break loop (type 'break' to go back to GP)";
                   2629:     old = s = _analyseur();
                   2630:     t = oldb->buf;
                   2631:     /* something fishy, probably a ^C, or we overran analyseur */
                   2632:     if (!s || !s[-1] || s < t || s >= t + oldb->len) s = NULL;
                   2633:     b->flenv = 1; oldinfile = infile;
                   2634:   }
                   2635:
                   2636:   term_color(c_ERR); pariputc('\n');
                   2637:   errcontext(msg, s, t); if (s) pariputc('\n');
                   2638:   term_color(c_NONE);
                   2639:   if (numerr == siginter) pariputs("['' or 'next' will continue]\n");
                   2640:   infile = stdin;
                   2641:   for(;;)
                   2642:   {
                   2643:     int flag;
                   2644:     if (! read_line("> ", b)) break;
                   2645:     if (!(flag = check_meta(b->buf)))
                   2646:     {
                   2647:       GEN x = lisseq(b->buf);
                   2648:       if (did_break())
                   2649:       {
                   2650:         if (numerr == siginter && did_break() == br_NEXT)
                   2651:         {
                   2652:           (void)loop_break(); /* clear status flag */
                   2653:           go_on = 1;
                   2654:         }
                   2655:         break;
                   2656:       }
                   2657:       if (x == gnil) continue;
                   2658:
                   2659:       term_color(c_OUTPUT); gp_output(x);
                   2660:       term_color(c_NONE); pariputc('\n');
                   2661:     }
                   2662:     if (numerr == siginter && flag == 2) { handle_C_C = go_on = 1; break; }
                   2663:   }
                   2664:   if (old && !s) _set_analyseur(old);
                   2665:   b = NULL; infile = oldinfile;
                   2666:   pop_buffer(); return go_on;
                   2667: }
                   2668:
                   2669: int
                   2670: gp_exception_handler(long numerr)
                   2671: {
                   2672:   char *s = (char*)global_err_data;
                   2673:   if (s && *s) { fprintferr("\n"); outerr(lisseq(s)); }
                   2674:   else
                   2675:   {
                   2676:     if (numerr == errpile) avma = top;
                   2677:     return break_loop(numerr);
                   2678:   }
                   2679:   return 0;
                   2680: }
                   2681:
                   2682: long
                   2683: setprecr(long n)
                   2684: {
                   2685:   long m = fmt.nb;
                   2686:
                   2687:   if (n>0) {fmt.nb = n; prec = (long)(n*pariK1 + 3);}
                   2688:   return m;
                   2689: }
                   2690:
                   2691: static void
                   2692: testint(char *s, long *d)
                   2693: {
                   2694:   if (!s) return;
                   2695:   *d = get_int(s, 0);
                   2696:   if (*d <= 0) err(talker,"arguments must be positive integers");
                   2697: }
                   2698:
                   2699: static char *
                   2700: read_arg(int *nread, char *t, long argc, char **argv)
                   2701: {
                   2702:   int i = *nread;
                   2703:   if (isdigit((int)*t)) return t;
                   2704:   if (*t || i==argc) usage(argv[0]);
                   2705:   *nread = i+1; return argv[i];
                   2706: }
                   2707:
                   2708: static char**
                   2709: read_opt(long argc, char **argv)
                   2710: {
                   2711:   char *b=NULL, *p=NULL, *s=NULL, **pre;
                   2712:   int i=1, initrc=1;
                   2713:
                   2714:   pari_outfile=stderr;
                   2715:   while (i<argc)
                   2716:   {
                   2717:     char *t = argv[i++];
                   2718:
                   2719:     if (*t++ != '-') usage(argv[0]);
                   2720:     switch(*t++)
                   2721:     {
                   2722:       case 'b': b = read_arg(&i,t,argc,argv); break;
                   2723:       case 'p': p = read_arg(&i,t,argc,argv); break;
                   2724:       case 's': s = read_arg(&i,t,argc,argv); break;
                   2725:
                   2726:       case 'e':
                   2727:        if (strncmp(t,"macs",4)) usage(argv[0]);
                   2728:         under_emacs = 1; break;
                   2729:       case 'q':
                   2730:         quiet_mode = 1; break;
                   2731:       case 't':
                   2732:        if (strncmp(t,"est",3)) usage(argv[0]);
                   2733:         disable_color = 1; test_mode = 1; /* fall through */
                   2734:       case 'f':
                   2735:        initrc = 0; break;
                   2736:       case '-':
                   2737:         if (strcmp(t, "version") == 0) { print_version(); exit(0); }
                   2738:         if (strcmp(t, "texmacs") == 0) { under_texmacs = 1; break; }
                   2739:        /* fall through */
                   2740:       default:
                   2741:        usage(argv[0]);
                   2742:     }
                   2743:   }
                   2744:   if (under_texmacs) tm_start_output();
                   2745:   pre = initrc? gp_initrc(): NULL;
                   2746:
                   2747:   /* override the values from gprc */
                   2748:   testint(b, &paribufsize); if (paribufsize < 10) paribufsize = 10;
                   2749:   testint(p, &primelimit);
                   2750:   testint(s, &parisize);
                   2751:   if (under_emacs || under_texmacs) disable_color=1;
                   2752:   pari_outfile=stdout; return pre;
                   2753: }
                   2754:
                   2755: #ifdef WINCE
                   2756: int
                   2757: WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   2758:         LPWSTR lpCmdLine, int nShowCmd)
                   2759: {
                   2760:   char **argv = NULL;
                   2761:   int argc = 1;
                   2762: #else
                   2763: int
                   2764: main(int argc, char **argv)
                   2765: {
                   2766: #endif
                   2767:   char **flist;
                   2768:
                   2769:   init_defaults(1); gp_preinit(1);
                   2770:   if (setjmp(environnement))
                   2771:   {
                   2772:     pariputs("### Errors on startup, exiting...\n\n");
                   2773:     exit(1);
                   2774:   }
                   2775: #ifdef __MWERKS__
                   2776:   argc = ccommand(&argv);
                   2777: #endif
                   2778:   flist = read_opt(argc,argv);
                   2779:   pari_addfunctions(&pari_modules, functions_gp,helpmessages_gp);
                   2780:   pari_addfunctions(&pari_modules, functions_highlevel,helpmessages_highlevel);
                   2781:   pari_addfunctions(&pari_oldmodules, functions_oldgp,helpmessages_oldgp);
                   2782:
                   2783:   init_graph(); INIT_SIG_off;
                   2784:   pari_init(parisize, primelimit);
                   2785:   INIT_SIG_on;
                   2786:   pari_sig_init(gp_sighandler);
                   2787: #ifdef READLINE
                   2788:   if (use_readline) {
                   2789:       init_readline();
                   2790:       readline_init = 1;
                   2791:   }
                   2792: #endif
                   2793:   gp_history_fun = gp_history;
                   2794:   whatnow_fun = whatnow;
                   2795:   output_fun = gp_output;
                   2796:   default_exception_handler = gp_exception_handler;
                   2797:   gp_expand_path(path);
                   2798:
                   2799:   if (!quiet_mode) gp_head();
                   2800:   if (flist)
                   2801:   {
                   2802:     long c=chrono, e=pariecho;
                   2803:     FILE *l=logfile;
                   2804:     char **s = flist;
                   2805:     chrono=0; pariecho=0; logfile=NULL;
                   2806:     for ( ; *s; s++) { read0(*s); free(*s); }
                   2807:     chrono=c; pariecho=e; logfile=l; free(flist);
                   2808:   }
                   2809:   (void)gptimer(); (void)timer(); (void)timer2();
                   2810:   (void)gp_main_loop(1);
                   2811:   gp_quit(); return 0; /* not reached */
                   2812: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>