[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     ! 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>