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

Generated by: LCOV version 1.16