Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is to exceed 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - language - default.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.12.1 lcov report (development 25819-e703fe1174) Lines: 349 567 61.6 %
Date: 2020-09-18 06:10:04 Functions: 41 67 61.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2000  The PARI group.
       2             : 
       3             : This file is part of the PARI/GP package.
       4             : 
       5             : PARI/GP is free software; you can redistribute it and/or modify it under the
       6             : terms of the GNU General Public License as published by the Free Software
       7             : Foundation. It is distributed in the hope that it will be useful, but WITHOUT
       8             : ANY WARRANTY WHATSOEVER.
       9             : 
      10             : Check the License for details. You should have received a copy of it, along
      11             : with the package; see the file 'COPYING'. If not, write to the Free Software
      12             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      13             : #include "pari.h"
      14             : #include "paripriv.h"
      15             : 
      16             : #ifdef _WIN32
      17             : #  include "../systems/mingw/mingw.h"
      18             : #endif
      19             : 
      20             : /* Return all chars, up to next separator
      21             :  * [as strtok but must handle verbatim character string] */
      22             : char*
      23        1853 : get_sep(const char *t)
      24             : {
      25        1853 :   char *buf = stack_malloc(strlen(t)+1);
      26        1853 :   char *s = buf;
      27        1853 :   int outer = 1;
      28             : 
      29             :   for(;;)
      30             :   {
      31        6178 :     switch(*s++ = *t++)
      32             :     {
      33           0 :       case '"':
      34           0 :         outer = !outer; break;
      35        1846 :       case '\0':
      36        1846 :         return buf;
      37           0 :       case ';':
      38           0 :         if (outer) { s[-1] = 0; return buf; }
      39           0 :         break;
      40           7 :       case '\\': /* gobble next char */
      41           7 :         if (! (*s++ = *t++) ) return buf;
      42             :     }
      43             :   }
      44             : }
      45             : 
      46             : /* "atoul" + optional [kmg] suffix */
      47             : static ulong
      48        1589 : my_int(char *s)
      49             : {
      50        1589 :   ulong n = 0;
      51        1589 :   char *p = s;
      52             : 
      53        5044 :   while (isdigit((int)*p)) {
      54             :     ulong m;
      55        3455 :     if (n > (~0UL / 10)) pari_err(e_SYNTAX,"integer too large",s,s);
      56        3455 :     n *= 10; m = n;
      57        3455 :     n += *p++ - '0';
      58        3455 :     if (n < m) pari_err(e_SYNTAX,"integer too large",s,s);
      59             :   }
      60        1589 :   if (n)
      61             :   {
      62        1547 :     switch(*p)
      63             :     {
      64           0 :       case 'k': case 'K': n = umuluu_or_0(n,1000UL);       p++; break;
      65         214 :       case 'm': case 'M': n = umuluu_or_0(n,1000000UL);    p++; break;
      66           0 :       case 'g': case 'G': n = umuluu_or_0(n,1000000000UL); p++; break;
      67             : #ifdef LONG_IS_64BIT
      68           0 :       case 't': case 'T': n = umuluu_or_0(n,1000000000000UL); p++; break;
      69             : #endif
      70             :     }
      71        1547 :     if (!n) pari_err(e_SYNTAX,"integer too large",s,s);
      72             :   }
      73        1589 :   if (*p) pari_err(e_SYNTAX,"I was expecting an integer here", s, s);
      74        1589 :   return n;
      75             : }
      76             : 
      77             : long
      78          30 : get_int(const char *s, long dflt)
      79             : {
      80          30 :   pari_sp av = avma;
      81          30 :   char *p = get_sep(s);
      82             :   long n;
      83          30 :   int minus = 0;
      84             : 
      85          30 :   if (*p == '-') { minus = 1; p++; }
      86          30 :   if (!isdigit((int)*p)) return gc_long(av, dflt);
      87             : 
      88          30 :   n = (long)my_int(p);
      89          30 :   if (n < 0) pari_err(e_SYNTAX,"integer too large",s,s);
      90          30 :   return gc_long(av, minus? -n: n);
      91             : }
      92             : 
      93             : ulong
      94        1559 : get_uint(const char *s)
      95             : {
      96        1559 :   pari_sp av = avma;
      97        1559 :   char *p = get_sep(s);
      98        1559 :   if (*p == '-') pari_err(e_SYNTAX,"arguments must be positive integers",s,s);
      99        1559 :   return gc_ulong(av, my_int(p));
     100             : }
     101             : 
     102             : #if defined(__EMX__) || defined(_WIN32) || defined(__CYGWIN32__)
     103             : #  define PATH_SEPARATOR ';' /* beware DOSish 'C:' disk drives */
     104             : #else
     105             : #  define PATH_SEPARATOR ':'
     106             : #endif
     107             : 
     108             : static const char *
     109        1690 : pari_default_path(void) {
     110             : #if PATH_SEPARATOR == ';'
     111             :   return ".;C:;C:/gp";
     112             : #elif defined(UNIX)
     113        1690 :   return ".:~:~/gp";
     114             : #else
     115             :   return ".";
     116             : #endif
     117             : }
     118             : 
     119             : static void
     120        6720 : delete_dirs(gp_path *p)
     121             : {
     122        6720 :   char **v = p->dirs, **dirs;
     123        6720 :   if (v)
     124             :   {
     125        3360 :     p->dirs = NULL; /* in case of error */
     126        8400 :     for (dirs = v; *dirs; dirs++) pari_free(*dirs);
     127        3360 :     pari_free(v);
     128             :   }
     129        6720 : }
     130             : 
     131             : static void
     132        3360 : expand_path(gp_path *p)
     133             : {
     134        3360 :   char **dirs, *s, *v = p->PATH;
     135        3360 :   int i, n = 0;
     136             : 
     137        3360 :   delete_dirs(p);
     138        3360 :   if (*v)
     139             :   {
     140        1680 :     v = pari_strdup(v);
     141       15120 :     for (s=v; *s; s++)
     142       13440 :       if (*s == PATH_SEPARATOR) {
     143        3360 :         *s = 0;
     144        3360 :         if (s == v || s[-1] != 0) n++; /* ignore empty path components */
     145             :       }
     146        1680 :     dirs = (char**) pari_malloc((n + 2)*sizeof(char *));
     147             : 
     148        6720 :     for (s=v, i=0; i<=n; i++)
     149             :     {
     150             :       char *end, *f;
     151        5040 :       while (!*s) s++; /* skip empty path components */
     152        5040 :       f = end = s + strlen(s);
     153        5040 :       while (f > s && *--f == '/') *f = 0; /* skip trailing '/' */
     154        5040 :       dirs[i] = path_expand(s);
     155        5040 :       s = end + 1; /* next path component */
     156             :     }
     157        1680 :     pari_free((void*)v);
     158             :   }
     159             :   else
     160             :   {
     161        1680 :     dirs = (char**) pari_malloc(sizeof(char *));
     162        1680 :     i = 0;
     163             :   }
     164        3360 :   dirs[i] = NULL; p->dirs = dirs;
     165        3360 : }
     166             : void
     167        1680 : pari_init_paths(void)
     168             : {
     169        1680 :   expand_path(GP_DATA->path);
     170        1680 :   expand_path(GP_DATA->sopath);
     171        1680 : }
     172             : 
     173             : static void
     174        3360 : delete_path(gp_path *p) { delete_dirs(p); free(p->PATH); }
     175             : void
     176        1680 : pari_close_paths(void)
     177             : {
     178        1680 :   delete_path(GP_DATA->path);
     179        1680 :   delete_path(GP_DATA->sopath);
     180        1680 : }
     181             : 
     182             : /********************************************************************/
     183             : /*                                                                  */
     184             : /*                            DEFAULTS                              */
     185             : /*                                                                  */
     186             : /********************************************************************/
     187             : 
     188             : long
     189           0 : getrealprecision(void)
     190             : {
     191           0 :   return GP_DATA->fmt->sigd;
     192             : }
     193             : 
     194             : long
     195           0 : setrealprecision(long n, long *prec)
     196             : {
     197           0 :   GP_DATA->fmt->sigd = n;
     198           0 :   *prec = ndec2prec(n);
     199           0 :   precreal = prec2nbits(*prec);
     200           0 :   return n;
     201             : }
     202             : 
     203             : GEN
     204          30 : sd_toggle(const char *v, long flag, const char *s, int *ptn)
     205             : {
     206          30 :   int state = *ptn;
     207          30 :   if (v)
     208             :   {
     209          30 :     int n = (int)get_int(v,0);
     210          30 :     if (n == state) return gnil;
     211          30 :     if (n != !state)
     212             :     {
     213           0 :       char *t = stack_malloc(64 + strlen(s));
     214           0 :       (void)sprintf(t, "default: incorrect value for %s [0:off / 1:on]", s);
     215           0 :       pari_err(e_SYNTAX, t, v,v);
     216             :     }
     217          30 :     state = *ptn = n;
     218             :   }
     219          30 :   switch(flag)
     220             :   {
     221           0 :     case d_RETURN: return utoi(state);
     222           0 :     case d_ACKNOWLEDGE:
     223           0 :       if (state) pari_printf("   %s = 1 (on)\n", s);
     224           0 :       else       pari_printf("   %s = 0 (off)\n", s);
     225           0 :       break;
     226             :   }
     227          30 :   return gnil;
     228             : }
     229             : 
     230             : static void
     231        1559 : sd_ulong_init(const char *v, const char *s, ulong *ptn, ulong Min, ulong Max)
     232             : {
     233        1559 :   if (v)
     234             :   {
     235        1559 :     ulong n = get_uint(v);
     236        1559 :     if (n > Max || n < Min)
     237             :     {
     238           2 :       char *buf = stack_malloc(strlen(s) + 2 * 20 + 40);
     239           2 :       (void)sprintf(buf, "default: incorrect value for %s [%lu-%lu]",
     240             :                     s, Min, Max);
     241           2 :       pari_err(e_SYNTAX, buf, v,v);
     242             :     }
     243        1557 :     *ptn = n;
     244             :   }
     245        1557 : }
     246             : 
     247             : /* msg is NULL or NULL-terminated array with msg[0] != NULL. */
     248             : GEN
     249         534 : sd_ulong(const char *v, long flag, const char *s, ulong *ptn, ulong Min, ulong Max,
     250             :          const char **msg)
     251             : {
     252         534 :   ulong n = *ptn;
     253         534 :   sd_ulong_init(v, s, ptn, Min, Max);
     254         532 :   switch(flag)
     255             :   {
     256           0 :     case d_RETURN:
     257           0 :       return utoi(*ptn);
     258         116 :     case d_ACKNOWLEDGE:
     259         116 :       if (!v || *ptn != n) {
     260         116 :         if (!msg)         /* no specific message */
     261         116 :           pari_printf("   %s = %lu\n", s, *ptn);
     262           0 :         else if (!msg[1]) /* single message, always printed */
     263           0 :           pari_printf("   %s = %lu %s\n", s, *ptn, msg[0]);
     264             :         else              /* print (new)-n-th message */
     265           0 :           pari_printf("   %s = %lu %s\n", s, *ptn, msg[*ptn]);
     266             :       }
     267         116 :       break;
     268             :   }
     269         532 :   return gnil;
     270             : }
     271             : 
     272             : static void
     273          21 : err_intarray(char *t, char *p, const char *s)
     274             : {
     275          21 :   char *b = stack_malloc(64 + strlen(s));
     276          21 :   sprintf(b, "incorrect value for %s", s);
     277          21 :   pari_err(e_SYNTAX, b, p, t);
     278           0 : }
     279             : static GEN
     280          39 : parse_intarray(const char *v, const char *s)
     281             : {
     282          39 :   pari_sp av = avma;
     283          39 :   char *p, *t = gp_filter(v);
     284             :   long i, l;
     285             :   GEN w;
     286          39 :   if (*t != '[') err_intarray(t, t, s);
     287          32 :   if (t[1] == ']') return gc_const(av, cgetalloc(t_VECSMALL, 1));
     288         125 :   for (p = t+1, l=2; *p; p++)
     289         111 :     if (*p == ',') l++;
     290          70 :     else if (*p < '0' || *p > '9') break;
     291          32 :   if (*p != ']') err_intarray(t, p, s);
     292          18 :   w = cgetalloc(t_VECSMALL, l);
     293          70 :   for (p = t+1, i=0; *p; p++)
     294             :   {
     295          52 :     long n = 0;
     296          97 :     while (*p >= '0' && *p <= '9') n = 10*n + (*p++ -'0');
     297          52 :     w[++i] = n;
     298             :   }
     299          18 :   return gc_const(av, w);
     300             : }
     301             : GEN
     302          39 : sd_intarray(const char *v, long flag, GEN *pz, const char *s)
     303             : {
     304          39 :   if (v) { GEN z = *pz; *pz = parse_intarray(v, s); pari_free(z); }
     305          18 :   switch(flag)
     306             :   {
     307           0 :     case d_RETURN: return zv_to_ZV(*pz);
     308           0 :     case d_ACKNOWLEDGE: pari_printf("   %s = %Ps\n", s, zv_to_ZV(*pz));
     309             :   }
     310          18 :   return gnil;
     311             : }
     312             : 
     313             : GEN
     314        1011 : sd_realprecision(const char *v, long flag)
     315             : {
     316        1011 :   pariout_t *fmt = GP_DATA->fmt;
     317        1011 :   if (v)
     318             :   {
     319        1011 :     ulong newnb = fmt->sigd;
     320             :     long prec;
     321        1011 :     sd_ulong_init(v, "realprecision", &newnb, 1, prec2ndec(LGBITS));
     322        1025 :     if (fmt->sigd == (long)newnb) return gnil;
     323         499 :     if (fmt->sigd >= 0) fmt->sigd = newnb;
     324         499 :     prec = ndec2nbits(newnb);
     325         499 :     if (prec == precreal) return gnil;
     326         485 :     precreal = prec;
     327             :   }
     328         485 :   if (flag == d_RETURN) return stoi(nbits2ndec(precreal));
     329         485 :   if (flag == d_ACKNOWLEDGE)
     330             :   {
     331         158 :     long n = nbits2ndec(precreal);
     332         158 :     pari_printf("   realprecision = %ld significant digits", n);
     333         158 :     if (fmt->sigd < 0)
     334           0 :       pari_puts(" (all digits displayed)");
     335         158 :     else if (n != fmt->sigd)
     336          21 :       pari_printf(" (%ld digits displayed)", fmt->sigd);
     337         158 :     pari_putc('\n');
     338             :   }
     339         485 :   return gnil;
     340             : }
     341             : 
     342             : GEN
     343          14 : sd_realbitprecision(const char *v, long flag)
     344             : {
     345          14 :   pariout_t *fmt = GP_DATA->fmt;
     346          14 :   if (v)
     347             :   {
     348          14 :     ulong newnb = precreal;
     349             :     long n;
     350          14 :     sd_ulong_init(v, "realbitprecision", &newnb, 1, prec2nbits(LGBITS));
     351          14 :     if ((long)newnb == precreal) return gnil;
     352          14 :     n = nbits2ndec(newnb);
     353          14 :     if (!n) n = 1;
     354          14 :     if (fmt->sigd >= 0) fmt->sigd = n;
     355          14 :     precreal = (long) newnb;
     356             :   }
     357          14 :   if (flag == d_RETURN) return stoi(precreal);
     358          14 :   if (flag == d_ACKNOWLEDGE)
     359             :   {
     360          14 :     pari_printf("   realbitprecision = %ld significant bits", precreal);
     361          14 :     if (fmt->sigd < 0)
     362           0 :       pari_puts(" (all digits displayed)");
     363             :     else
     364          14 :       pari_printf(" (%ld decimal digits displayed)", fmt->sigd);
     365          14 :     pari_putc('\n');
     366             :   }
     367          14 :   return gnil;
     368             : }
     369             : 
     370             : GEN
     371          28 : sd_seriesprecision(const char *v, long flag)
     372             : {
     373          28 :   const char *msg[] = {"significant terms", NULL};
     374          28 :   return sd_ulong(v,flag,"seriesprecision",&precdl, 1,LGBITS,msg);
     375             : }
     376             : 
     377             : static long
     378          28 : gp_get_color(char **st)
     379             : {
     380          28 :   char *s, *v = *st;
     381             :   int trans;
     382             :   long c;
     383          28 :   if (isdigit((int)*v))
     384          28 :     { c = atol(v); trans = 1; } /* color on transparent background */
     385             :   else
     386             :   {
     387           0 :     if (*v == '[')
     388             :     {
     389             :       const char *a[3];
     390           0 :       long i = 0;
     391           0 :       for (a[0] = s = ++v; *s && *s != ']'; s++)
     392           0 :         if (*s == ',') { *s = 0; a[++i] = s+1; }
     393           0 :       if (*s != ']') pari_err(e_SYNTAX,"expected character: ']'",s, *st);
     394           0 :       *s = 0; for (i++; i<3; i++) a[i] = "";
     395             :       /*    properties    |   color    | background */
     396           0 :       c = (atoi(a[2])<<8) | atoi(a[0]) | (atoi(a[1])<<4);
     397           0 :       trans = (*(a[1]) == 0);
     398           0 :       v = s + 1;
     399             :     }
     400           0 :     else { c = c_NONE; trans = 0; }
     401             :   }
     402          28 :   if (trans) c = c | (1L<<12);
     403          56 :   while (*v && *v++ != ',') /* empty */;
     404          28 :   if (c != c_NONE) disable_color = 0;
     405          28 :   *st = v; return c;
     406             : }
     407             : 
     408             : /* 1: error, 2: history, 3: prompt, 4: input, 5: output, 6: help, 7: timer */
     409             : GEN
     410           4 : sd_colors(const char *v, long flag)
     411             : {
     412             :   long c,l;
     413           4 :   if (v && !(GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS)))
     414             :   {
     415           4 :     pari_sp av = avma;
     416             :     char *s;
     417           4 :     disable_color=1;
     418           4 :     l = strlen(v);
     419           4 :     if (l <= 2 && strncmp(v, "no", l) == 0)
     420           0 :       v = "";
     421           4 :     if (l <= 6 && strncmp(v, "darkbg", l) == 0)
     422           0 :       v = "1, 5, 3, 7, 6, 2, 3"; /* Assume recent ReadLine. */
     423           4 :     if (l <= 7 && strncmp(v, "lightbg", l) == 0)
     424           4 :       v = "1, 6, 3, 4, 5, 2, 3"; /* Assume recent ReadLine. */
     425           4 :     if (l <= 8 && strncmp(v, "brightfg", l) == 0)      /* Good for windows consoles */
     426           0 :       v = "9, 13, 11, 15, 14, 10, 11";
     427           4 :     if (l <= 6 && strncmp(v, "boldfg", l) == 0)        /* Good for darkbg consoles */
     428           0 :       v = "[1,,1], [5,,1], [3,,1], [7,,1], [6,,1], , [2,,1]";
     429           4 :     s = gp_filter(v);
     430          32 :     for (c=c_ERR; c < c_LAST; c++) gp_colors[c] = gp_get_color(&s);
     431           4 :     set_avma(av);
     432             :   }
     433           4 :   if (flag == d_ACKNOWLEDGE || flag == d_RETURN)
     434             :   {
     435           0 :     char s[128], *t = s;
     436             :     long col[3], n;
     437           0 :     for (*t=0,c=c_ERR; c < c_LAST; c++)
     438             :     {
     439           0 :       n = gp_colors[c];
     440           0 :       if (n == c_NONE)
     441           0 :         sprintf(t,"no");
     442             :       else
     443             :       {
     444           0 :         decode_color(n,col);
     445           0 :         if (n & (1L<<12))
     446             :         {
     447           0 :           if (col[0])
     448           0 :             sprintf(t,"[%ld,,%ld]",col[1],col[0]);
     449             :           else
     450           0 :             sprintf(t,"%ld",col[1]);
     451             :         }
     452             :         else
     453           0 :           sprintf(t,"[%ld,%ld,%ld]",col[1],col[2],col[0]);
     454             :       }
     455           0 :       t += strlen(t);
     456           0 :       if (c < c_LAST - 1) { *t++=','; *t++=' '; }
     457             :     }
     458           0 :     if (flag==d_RETURN) return strtoGENstr(s);
     459           0 :     pari_printf("   colors = \"%s\"\n",s);
     460             :   }
     461           4 :   return gnil;
     462             : }
     463             : 
     464             : GEN
     465           7 : sd_format(const char *v, long flag)
     466             : {
     467           7 :   pariout_t *fmt = GP_DATA->fmt;
     468           7 :   if (v)
     469             :   {
     470           7 :     char c = *v;
     471           7 :     if (c!='e' && c!='f' && c!='g')
     472           0 :       pari_err(e_SYNTAX,"default: inexistent format",v,v);
     473           7 :     fmt->format = c; v++;
     474             : 
     475           7 :     if (isdigit((int)*v))
     476           0 :       { while (isdigit((int)*v)) v++; } /* FIXME: skip obsolete field width */
     477           7 :     if (*v++ == '.')
     478             :     {
     479           7 :       if (*v == '-') fmt->sigd = -1;
     480             :       else
     481           7 :         if (isdigit((int)*v)) fmt->sigd=atol(v);
     482             :     }
     483             :   }
     484           7 :   if (flag == d_RETURN)
     485             :   {
     486           0 :     char *s = stack_malloc(64);
     487           0 :     (void)sprintf(s, "%c.%ld", fmt->format, fmt->sigd);
     488           0 :     return strtoGENstr(s);
     489             :   }
     490           7 :   if (flag == d_ACKNOWLEDGE)
     491           0 :     pari_printf("   format = %c.%ld\n", fmt->format, fmt->sigd);
     492           7 :   return gnil;
     493             : }
     494             : 
     495             : GEN
     496           0 : sd_compatible(const char *v, long flag)
     497             : {
     498           0 :   const char *msg[] = {
     499             :     "(no backward compatibility)",
     500             :     "(no backward compatibility)",
     501             :     "(no backward compatibility)",
     502             :     "(no backward compatibility)", NULL
     503             :   };
     504           0 :   ulong junk = 0;
     505           0 :   return sd_ulong(v,flag,"compatible",&junk, 0,3,msg);
     506             : }
     507             : 
     508             : GEN
     509           0 : sd_secure(const char *v, long flag)
     510             : {
     511           0 :   if (v && GP_DATA->secure)
     512           0 :     pari_ask_confirm("[secure mode]: About to modify the 'secure' flag");
     513           0 :   return sd_toggle(v,flag,"secure", &(GP_DATA->secure));
     514             : }
     515             : 
     516             : GEN
     517          21 : sd_debug(const char *v, long flag)
     518          21 : { return sd_ulong(v,flag,"debug",&DEBUGLEVEL, 0,20,NULL); }
     519             : 
     520             : GEN
     521           0 : sd_debugfiles(const char *v, long flag)
     522           0 : { return sd_ulong(v,flag,"debugfiles",&DEBUGFILES, 0,20,NULL); }
     523             : 
     524             : GEN
     525           0 : sd_debugmem(const char *v, long flag)
     526           0 : { return sd_ulong(v,flag,"debugmem",&DEBUGMEM, 0,20,NULL); }
     527             : 
     528             : /* set D->hist to size = s / total = t */
     529             : static void
     530        1704 : init_hist(gp_data *D, size_t s, ulong t)
     531             : {
     532        1704 :   gp_hist *H = D->hist;
     533        1704 :   H->total = t;
     534        1704 :   H->size = s;
     535        1704 :   H->v = (gp_hist_cell*)pari_calloc(s * sizeof(gp_hist_cell));
     536        1704 : }
     537             : GEN
     538          14 : sd_histsize(const char *s, long flag)
     539             : {
     540          14 :   gp_hist *H = GP_DATA->hist;
     541          14 :   ulong n = H->size;
     542          14 :   GEN r = sd_ulong(s,flag,"histsize",&n, 1,
     543             :                      (LONG_MAX / sizeof(long)) - 1,NULL);
     544          14 :   if (n != H->size)
     545             :   {
     546          14 :     const ulong total = H->total;
     547             :     long g, h, k, kmin;
     548          14 :     gp_hist_cell *v = H->v, *w; /* v = old data, w = new one */
     549          14 :     size_t sv = H->size, sw;
     550             : 
     551          14 :     init_hist(GP_DATA, n, total);
     552          14 :     if (!total) return r;
     553             : 
     554          14 :     w = H->v;
     555          14 :     sw= H->size;
     556             :     /* copy relevant history entries */
     557          14 :     g     = (total-1) % sv;
     558          14 :     h = k = (total-1) % sw;
     559          14 :     kmin = k - minss(sw, sv);
     560          28 :     for ( ; k > kmin; k--, g--, h--)
     561             :     {
     562          14 :       w[h]   = v[g];
     563          14 :       v[g].z = NULL;
     564          14 :       if (!g) g = sv;
     565          14 :       if (!h) h = sw;
     566             :     }
     567             :     /* clean up */
     568          84 :     for ( ; v[g].z; g--)
     569             :     {
     570          70 :       gunclone(v[g].z);
     571          70 :       if (!g) g = sv;
     572             :     }
     573          14 :     pari_free((void*)v);
     574             :   }
     575          14 :   return r;
     576             : }
     577             : 
     578             : static void
     579           0 : TeX_define(const char *s, const char *def) {
     580           0 :   fprintf(pari_logfile, "\\ifx\\%s\\undefined\n  \\def\\%s{%s}\\fi\n", s,s,def);
     581           0 : }
     582             : static void
     583           0 : TeX_define2(const char *s, const char *def) {
     584           0 :   fprintf(pari_logfile, "\\ifx\\%s\\undefined\n  \\def\\%s#1#2{%s}\\fi\n", s,s,def);
     585           0 : }
     586             : 
     587             : static FILE *
     588           0 : open_logfile(const char *s) {
     589           0 :   FILE *log = fopen(s, "a");
     590           0 :   if (!log) pari_err_FILE("logfile",s);
     591           0 :   setbuf(log,(char *)NULL);
     592           0 :   return log;
     593             : }
     594             : 
     595             : GEN
     596           0 : sd_log(const char *v, long flag)
     597             : {
     598           0 :   const char *msg[] = {
     599             :       "(off)",
     600             :       "(on)",
     601             :       "(on with colors)",
     602             :       "(TeX output)", NULL
     603             :   };
     604           0 :   ulong s = pari_logstyle;
     605           0 :   GEN res = sd_ulong(v,flag,"log", &s, 0, 3, msg);
     606             : 
     607           0 :   if (!s != !pari_logstyle) /* Compare converts to boolean */
     608             :   { /* toggled LOG */
     609           0 :     if (pari_logstyle)
     610             :     { /* close log */
     611           0 :       if (flag == d_ACKNOWLEDGE)
     612           0 :         pari_printf("   [logfile was \"%s\"]\n", current_logfile);
     613           0 :       if (pari_logfile) { fclose(pari_logfile); pari_logfile = NULL; }
     614             :     }
     615             :     else
     616             :     {
     617           0 :       pari_logfile = open_logfile(current_logfile);
     618           0 :       if (flag == d_ACKNOWLEDGE)
     619           0 :         pari_printf("   [logfile is \"%s\"]\n", current_logfile);
     620           0 :       else if (flag == d_INITRC)
     621           0 :         pari_printf("Logging to %s\n", current_logfile);
     622             :     }
     623             :   }
     624           0 :   if (pari_logfile && s != pari_logstyle && s == logstyle_TeX)
     625             :   {
     626           0 :     TeX_define("PARIbreak",
     627             :                "\\hskip 0pt plus \\hsize\\relax\\discretionary{}{}{}");
     628           0 :     TeX_define("PARIpromptSTART", "\\vskip\\medskipamount\\bgroup\\bf");
     629           0 :     TeX_define("PARIpromptEND", "\\egroup\\bgroup\\tt");
     630           0 :     TeX_define("PARIinputEND", "\\egroup");
     631           0 :     TeX_define2("PARIout",
     632             :                 "\\vskip\\smallskipamount$\\displaystyle{\\tt\\%#1} = #2$");
     633             :   }
     634             :   /* don't record new value until we are sure everything is fine */
     635           0 :   pari_logstyle = s; return res;
     636             : }
     637             : 
     638             : GEN
     639           0 : sd_TeXstyle(const char *v, long flag)
     640             : {
     641           0 :   const char *msg[] = { "(bits 0x2/0x4 control output of \\left/\\PARIbreak)",
     642             :                         NULL };
     643           0 :   ulong n = GP_DATA->fmt->TeXstyle;
     644           0 :   GEN z = sd_ulong(v,flag,"TeXstyle", &n, 0, 7, msg);
     645           0 :   GP_DATA->fmt->TeXstyle = n; return z;
     646             : }
     647             : 
     648             : GEN
     649           7 : sd_nbthreads(const char *v, long flag)
     650           7 : { return sd_ulong(v,flag,"nbthreads",&pari_mt_nbthreads, 1,LONG_MAX,NULL); }
     651             : 
     652             : GEN
     653           0 : sd_output(const char *v, long flag)
     654             : {
     655           0 :   const char *msg[] = {"(raw)", "(prettymatrix)", "(prettyprint)",
     656             :                  "(external prettyprint)", NULL};
     657           0 :   ulong n = GP_DATA->fmt->prettyp;
     658           0 :   GEN z = sd_ulong(v,flag,"output", &n, 0,3,msg);
     659           0 :   GP_DATA->fmt->prettyp = n;
     660           0 :   GP_DATA->fmt->sp = (n != f_RAW);
     661           0 :   return z;
     662             : }
     663             : 
     664             : GEN
     665           0 : sd_parisizemax(const char *v, long flag)
     666             : {
     667           0 :   ulong size = pari_mainstack->vsize, n = size;
     668           0 :   GEN r = sd_ulong(v,flag,"parisizemax",&n, 0,LONG_MAX,NULL);
     669           0 :   if (n != size) {
     670           0 :     if (flag == d_INITRC)
     671           0 :       paristack_setsize(pari_mainstack->rsize, n);
     672             :     else
     673           0 :       parivstack_resize(n);
     674             :   }
     675           0 :   return r;
     676             : }
     677             : 
     678             : GEN
     679         258 : sd_parisize(const char *v, long flag)
     680             : {
     681         258 :   ulong rsize = pari_mainstack->rsize, n = rsize;
     682         258 :   GEN r = sd_ulong(v,flag,"parisize",&n, 10000,LONG_MAX,NULL);
     683         256 :   if (n != rsize) {
     684         256 :     if (flag == d_INITRC)
     685           0 :       paristack_setsize(n, pari_mainstack->vsize);
     686             :     else
     687         256 :       paristack_newrsize(n);
     688             :   }
     689           0 :   return r;
     690             : }
     691             : 
     692             : GEN
     693           0 : sd_threadsizemax(const char *v, long flag)
     694             : {
     695           0 :   ulong size = GP_DATA->threadsizemax, n = size;
     696           0 :   GEN r = sd_ulong(v,flag,"threadsizemax",&n, 0,LONG_MAX,NULL);
     697           0 :   if (n != size)
     698           0 :     GP_DATA->threadsizemax = n;
     699           0 :   return r;
     700             : }
     701             : 
     702             : GEN
     703           0 : sd_threadsize(const char *v, long flag)
     704             : {
     705           0 :   ulong size = GP_DATA->threadsize, n = size;
     706           0 :   GEN r = sd_ulong(v,flag,"threadsize",&n, 0,LONG_MAX,NULL);
     707           0 :   if (n != size)
     708           0 :     GP_DATA->threadsize = n;
     709           0 :   return r;
     710             : }
     711             : 
     712             : GEN
     713          14 : sd_primelimit(const char *v, long flag)
     714          14 : { return sd_ulong(v,flag,"primelimit",&(GP_DATA->primelimit),
     715             :                   0,2*(ulong)(LONG_MAX-1024) + 1,NULL); }
     716             : 
     717             : GEN
     718           0 : sd_simplify(const char *v, long flag)
     719           0 : { return sd_toggle(v,flag,"simplify", &(GP_DATA->simplify)); }
     720             : 
     721             : GEN
     722           0 : sd_strictmatch(const char *v, long flag)
     723           0 : { return sd_toggle(v,flag,"strictmatch", &(GP_DATA->strictmatch)); }
     724             : 
     725             : GEN
     726           7 : sd_strictargs(const char *v, long flag)
     727           7 : { return sd_toggle(v,flag,"strictargs", &(GP_DATA->strictargs)); }
     728             : 
     729             : GEN
     730           4 : sd_string(const char *v, long flag, const char *s, char **pstr)
     731             : {
     732           4 :   char *old = *pstr;
     733           4 :   if (v)
     734             :   {
     735           4 :     char *str, *ev = path_expand(v);
     736           4 :     long l = strlen(ev) + 256;
     737           4 :     str = (char *) pari_malloc(l);
     738           4 :     strftime_expand(ev,str, l-1); pari_free(ev);
     739           4 :     if (GP_DATA->secure)
     740             :     {
     741           0 :       char *msg=pari_sprintf("[secure mode]: About to change %s to '%s'",s,str);
     742           0 :       pari_ask_confirm(msg);
     743           0 :       pari_free(msg);
     744             :     }
     745           4 :     if (old) pari_free(old);
     746           4 :     *pstr = old = pari_strdup(str);
     747           4 :     pari_free(str);
     748             :   }
     749           0 :   else if (!old) old = (char*)"<undefined>";
     750           4 :   if (flag == d_RETURN) return strtoGENstr(old);
     751           4 :   if (flag == d_ACKNOWLEDGE) pari_printf("   %s = \"%s\"\n",s,old);
     752           4 :   return gnil;
     753             : }
     754             : 
     755             : GEN
     756           0 : sd_logfile(const char *v, long flag)
     757             : {
     758           0 :   GEN r = sd_string(v, flag, "logfile", &current_logfile);
     759           0 :   if (v && pari_logfile)
     760             :   {
     761           0 :     FILE *log = open_logfile(current_logfile);
     762           0 :     fclose(pari_logfile); pari_logfile = log;
     763             :   }
     764           0 :   return r;
     765             : }
     766             : 
     767             : GEN
     768           0 : sd_factor_add_primes(const char *v, long flag)
     769           0 : { return sd_toggle(v,flag,"factor_add_primes", &factor_add_primes); }
     770             : 
     771             : GEN
     772           0 : sd_factor_proven(const char *v, long flag)
     773           0 : { return sd_toggle(v,flag,"factor_proven", &factor_proven); }
     774             : 
     775             : GEN
     776          14 : sd_new_galois_format(const char *v, long flag)
     777          14 : { return sd_toggle(v,flag,"new_galois_format", &new_galois_format); }
     778             : 
     779             : GEN
     780          40 : sd_datadir(const char *v, long flag)
     781             : {
     782             :   const char *str;
     783          40 :   if (v)
     784             :   {
     785           7 :     mt_broadcast(snm_closure(is_entry("default"),
     786             :                  mkvec2(strtoGENstr("datadir"), strtoGENstr(v))));
     787           7 :     if (pari_datadir) pari_free(pari_datadir);
     788           7 :     pari_datadir = path_expand(v);
     789             :   }
     790          40 :   str = pari_datadir? pari_datadir: "none";
     791          40 :   if (flag == d_RETURN) return strtoGENstr(str);
     792           7 :   if (flag == d_ACKNOWLEDGE)
     793           0 :     pari_printf("   datadir = \"%s\"\n", str);
     794           7 :   return gnil;
     795             : }
     796             : 
     797             : static GEN
     798           0 : sd_PATH(const char *v, long flag, const char* s, gp_path *p)
     799             : {
     800           0 :   if (v)
     801             :   {
     802           0 :     mt_broadcast(snm_closure(is_entry("default"),
     803             :                  mkvec2(strtoGENstr(s), strtoGENstr(v))));
     804           0 :     pari_free((void*)p->PATH);
     805           0 :     p->PATH = pari_strdup(v);
     806           0 :     if (flag == d_INITRC) return gnil;
     807           0 :     expand_path(p);
     808             :   }
     809           0 :   if (flag == d_RETURN) return strtoGENstr(p->PATH);
     810           0 :   if (flag == d_ACKNOWLEDGE)
     811           0 :     pari_printf("   %s = \"%s\"\n", s, p->PATH);
     812           0 :   return gnil;
     813             : }
     814             : GEN
     815           0 : sd_path(const char *v, long flag)
     816           0 : { return sd_PATH(v, flag, "path", GP_DATA->path); }
     817             : GEN
     818           0 : sd_sopath(char *v, int flag)
     819           0 : { return sd_PATH(v, flag, "sopath", GP_DATA->sopath); }
     820             : 
     821             : static const char *DFT_PRETTYPRINTER = "tex2mail -TeX -noindent -ragged -by_par";
     822             : GEN
     823           0 : sd_prettyprinter(const char *v, long flag)
     824             : {
     825           0 :   gp_pp *pp = GP_DATA->pp;
     826           0 :   if (v && !(GP_DATA->flags & gpd_TEXMACS))
     827             :   {
     828           0 :     char *old = pp->cmd;
     829           0 :     int cancel = (!strcmp(v,"no"));
     830             : 
     831           0 :     if (GP_DATA->secure)
     832           0 :       pari_err(e_MISC,"[secure mode]: can't modify 'prettyprinter' default (to %s)",v);
     833           0 :     if (!strcmp(v,"yes")) v = DFT_PRETTYPRINTER;
     834           0 :     if (old && strcmp(old,v) && pp->file)
     835             :     {
     836             :       pariFILE *f;
     837           0 :       if (cancel) f = NULL;
     838             :       else
     839             :       {
     840           0 :         f = try_pipe(v, mf_OUT);
     841           0 :         if (!f)
     842             :         {
     843           0 :           pari_warn(warner,"broken prettyprinter: '%s'",v);
     844           0 :           return gnil;
     845             :         }
     846             :       }
     847           0 :       pari_fclose(pp->file);
     848           0 :       pp->file = f;
     849             :     }
     850           0 :     pp->cmd = cancel? NULL: pari_strdup(v);
     851           0 :     if (old) pari_free(old);
     852           0 :     if (flag == d_INITRC) return gnil;
     853             :   }
     854           0 :   if (flag == d_RETURN)
     855           0 :     return strtoGENstr(pp->cmd? pp->cmd: "");
     856           0 :   if (flag == d_ACKNOWLEDGE)
     857           0 :     pari_printf("   prettyprinter = \"%s\"\n",pp->cmd? pp->cmd: "");
     858           0 :   return gnil;
     859             : }
     860             : 
     861             : /* compare entrees s1 s2 according to the attached function name */
     862             : static int
     863           0 : compare_name(const void *s1, const void *s2) {
     864           0 :   entree *e1 = *(entree**)s1, *e2 = *(entree**)s2;
     865           0 :   return strcmp(e1->name, e2->name);
     866             : }
     867             : static void
     868           0 : defaults_list(pari_stack *s)
     869             : {
     870             :   entree *ep;
     871             :   long i;
     872           0 :   for (i = 0; i < functions_tblsz; i++)
     873           0 :     for (ep = defaults_hash[i]; ep; ep = ep->next) pari_stack_pushp(s, ep);
     874           0 : }
     875             : /* ep attached to function f of arity 2. Call f(v,flag) */
     876             : static GEN
     877        1371 : call_f2(entree *ep, const char *v, long flag)
     878        1371 : { return ((GEN (*)(const char*,long))ep->value)(v, flag); }
     879             : GEN
     880        1371 : setdefault(const char *s, const char *v, long flag)
     881             : {
     882             :   entree *ep;
     883        1371 :   if (!s)
     884             :   { /* list all defaults */
     885             :     pari_stack st;
     886             :     entree **L;
     887             :     long i;
     888           0 :     pari_stack_init(&st, sizeof(*L), (void**)&L);
     889           0 :     defaults_list(&st);
     890           0 :     qsort (L, st.n, sizeof(*L), compare_name);
     891           0 :     for (i = 0; i < st.n; i++) (void)call_f2(L[i], NULL, d_ACKNOWLEDGE);
     892           0 :     pari_stack_delete(&st);
     893           0 :     return gnil;
     894             :   }
     895        1371 :   ep = pari_is_default(s);
     896        1371 :   if (!ep)
     897             :   {
     898           0 :     pari_err(e_MISC,"unknown default: %s",s);
     899             :     return NULL; /* LCOV_EXCL_LINE */
     900             :   }
     901        1371 :   return call_f2(ep, v, flag);
     902             : }
     903             : 
     904             : GEN
     905        1353 : default0(const char *a, const char *b) { return setdefault(a,b, b? d_SILENT: d_RETURN); }
     906             : 
     907             : /********************************************************************/
     908             : /*                                                                  */
     909             : /*                     INITIALIZE GP_DATA                           */
     910             : /*                                                                  */
     911             : /********************************************************************/
     912             : /* initialize path */
     913             : static void
     914        3380 : init_path(gp_path *path, const char *v)
     915             : {
     916        3380 :   path->PATH = pari_strdup(v);
     917        3380 :   path->dirs = NULL;
     918        3380 : }
     919             : 
     920             : /* initialize D->fmt */
     921             : static void
     922        1690 : init_fmt(gp_data *D)
     923             : {
     924             : #ifdef LONG_IS_64BIT
     925             :   static pariout_t DFLT_OUTPUT = { 'g', 38, 1, f_PRETTYMAT, 0 };
     926             : #else
     927             :   static pariout_t DFLT_OUTPUT = { 'g', 28, 1, f_PRETTYMAT, 0 };
     928             : #endif
     929        1690 :   D->fmt = &DFLT_OUTPUT;
     930        1690 : }
     931             : 
     932             : /* initialize D->pp */
     933             : static void
     934        1690 : init_pp(gp_data *D)
     935             : {
     936        1690 :   gp_pp *p = D->pp;
     937        1690 :   p->cmd = pari_strdup(DFT_PRETTYPRINTER);
     938        1690 :   p->file = NULL;
     939        1690 : }
     940             : 
     941             : static char *
     942        1690 : init_help(void)
     943             : {
     944        1690 :   char *h = os_getenv("GPHELP");
     945        1690 :   if (!h) h = (char*)paricfg_gphelp;
     946             : #ifdef _WIN32
     947             :   win32_set_pdf_viewer();
     948             : #endif
     949        1690 :   if (h) h = pari_strdup(h);
     950        1690 :   return h;
     951             : }
     952             : 
     953             : static void
     954        1690 : init_graphs(gp_data *D)
     955             : {
     956        1690 :   const char *cols[] = { "",
     957             :     "white","black","blue","violetred","red","green","grey","gainsboro"
     958             :   };
     959        1690 :   const long N = 8;
     960        1690 :   GEN c = cgetalloc(t_VECSMALL, 3), s;
     961             :   long i;
     962        1690 :   c[1] = 4;
     963        1690 :   c[2] = 5;
     964        1690 :   D->graphcolors = c;
     965        1690 :   c = (GEN)pari_malloc((N+1 + 4*N)*sizeof(long));
     966        1690 :   c[0] = evaltyp(t_VEC)|evallg(N+1);
     967       15210 :   for (i = 1, s = c+N+1; i <= N; i++, s += 4)
     968             :   {
     969       13520 :     GEN lp = s;
     970       13520 :     lp[0] = evaltyp(t_STR)|evallg(4);
     971       13520 :     strcpy(GSTR(lp), cols[i]);
     972       13520 :     gel(c,i) = lp;
     973             :   }
     974        1690 :   D->colormap = c;
     975        1690 : }
     976             : 
     977             : gp_data *
     978        1690 : default_gp_data(void)
     979             : {
     980             :   static gp_data __GPDATA, *D = &__GPDATA;
     981             :   static gp_hist __HIST;
     982             :   static gp_pp   __PP;
     983             :   static gp_path __PATH, __SOPATH;
     984             :   static pari_timer __T, __Tw;
     985             : 
     986        1690 :   D->flags       = 0;
     987        1690 :   D->primelimit  = 500000;
     988             : 
     989             :   /* GP-specific */
     990        1690 :   D->breakloop   = 1;
     991        1690 :   D->echo        = 0;
     992        1690 :   D->lim_lines   = 0;
     993        1690 :   D->linewrap    = 0;
     994        1690 :   D->recover     = 1;
     995        1690 :   D->chrono      = 0;
     996             : 
     997        1690 :   D->strictargs  = 0;
     998        1690 :   D->strictmatch = 1;
     999        1690 :   D->simplify    = 1;
    1000        1690 :   D->secure      = 0;
    1001        1690 :   D->use_readline= 0;
    1002        1690 :   D->T    = &__T;
    1003        1690 :   D->Tw   = &__Tw;
    1004        1690 :   D->hist = &__HIST;
    1005        1690 :   D->pp   = &__PP;
    1006        1690 :   D->path = &__PATH;
    1007        1690 :   D->sopath=&__SOPATH;
    1008        1690 :   init_fmt(D);
    1009        1690 :   init_hist(D, 5000, 0);
    1010        1690 :   init_path(D->path, pari_default_path());
    1011        1690 :   init_path(D->sopath, "");
    1012        1690 :   init_pp(D);
    1013        1690 :   init_graphs(D);
    1014        1690 :   D->plothsizes = cgetalloc(t_VECSMALL, 1);
    1015        1690 :   D->prompt_comment = (char*)"comment> ";
    1016        1690 :   D->prompt = pari_strdup("? ");
    1017        1690 :   D->prompt_cont = pari_strdup("");
    1018        1690 :   D->help = init_help();
    1019        1690 :   D->readline_state = DO_ARGS_COMPLETE;
    1020        1690 :   D->histfile = NULL;
    1021        1690 :   return D;
    1022             : }

Generated by: LCOV version 1.13