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

Annotation of OpenXM_contrib/pari/src/gp/gp.c, Revision 1.1

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

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