1 /* Copyright (C) 2006  The PARI group.
2 
3 This file is part of the PARI 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 
15 #include "pari.h"
16 #include "paripriv.h"
17 #include "anal.h"
18 #include "opcode.h"
19 
20 /********************************************************************/
21 /*                                                                  */
22 /*                   break/next/return handling                     */
23 /*                                                                  */
24 /********************************************************************/
25 
26 static THREAD long br_status, br_count;
27 static THREAD GEN br_res;
28 
29 long
loop_break(void)30 loop_break(void)
31 {
32   switch(br_status)
33   {
34     case br_MULTINEXT :
35       if (! --br_count) br_status = br_NEXT;
36       return 1;
37     case br_BREAK : if (! --br_count) br_status = br_NONE; /* fall through */
38     case br_RETURN: return 1;
39     case br_NEXT: br_status = br_NONE; /* fall through */
40   }
41   return 0;
42 }
43 
44 static void
reset_break(void)45 reset_break(void)
46 {
47   br_status = br_NONE;
48   if (br_res) { gunclone_deep(br_res); br_res = NULL; }
49 }
50 
51 GEN
return0(GEN x)52 return0(GEN x)
53 {
54   GEN y = br_res;
55   br_res = (x && x != gnil)? gcloneref(x): NULL;
56   guncloneNULL_deep(y);
57   br_status = br_RETURN; return NULL;
58 }
59 
60 GEN
next0(long n)61 next0(long n)
62 {
63   if (n < 1) pari_err_DOMAIN("next", "n", "<", gen_1, stoi(n));
64   if (n == 1) br_status = br_NEXT;
65   else
66   {
67     br_count = n-1;
68     br_status = br_MULTINEXT;
69   }
70   return NULL;
71 }
72 
73 GEN
break0(long n)74 break0(long n)
75 {
76   if (n < 1) pari_err_DOMAIN("break", "n", "<", gen_1, stoi(n));
77   br_count = n;
78   br_status = br_BREAK; return NULL;
79 }
80 
81 /*******************************************************************/
82 /*                                                                 */
83 /*                            VARIABLES                            */
84 /*                                                                 */
85 /*******************************************************************/
86 
87 /* As a rule, ep->value is a clone (COPY). push_val and pop_val are private
88  * functions for use in sumiter: we want a temporary ep->value, which is NOT
89  * a clone (PUSH), to avoid unnecessary copies. */
90 
91 enum {PUSH_VAL = 0, COPY_VAL = 1, DEFAULT_VAL = 2, REF_VAL = 3};
92 
93 /* ep->args is the stack of old values (INITIAL if initial value, from
94  * installep) */
95 typedef struct var_cell {
96   struct var_cell *prev; /* cell attached to previous value on stack */
97   GEN value; /* last value (not including current one, in ep->value) */
98   char flag; /* status of _current_ ep->value: PUSH or COPY ? */
99   long valence; /* valence of entree* attached to 'value', to be restored
100                     * by pop_val */
101 } var_cell;
102 #define INITIAL NULL
103 
104 /* Push x on value stack attached to ep. */
105 static void
new_val_cell(entree * ep,GEN x,char flag)106 new_val_cell(entree *ep, GEN x, char flag)
107 {
108   var_cell *v = (var_cell*) pari_malloc(sizeof(var_cell));
109   v->value  = (GEN)ep->value;
110   v->prev   = (var_cell*) ep->pvalue;
111   v->flag   = flag;
112   v->valence= ep->valence;
113 
114   /* beware: f(p) = Nv = 0
115    *         Nv = p; f(Nv) --> this call would destroy p [ isclone ] */
116   ep->value = (flag == COPY_VAL)? gclone(x):
117                                   (x && isclone(x))? gcopy(x): x;
118   /* Do this last. In case the clone is <C-C>'ed before completion ! */
119   ep->pvalue= (char*)v;
120   ep->valence=EpVAR;
121 }
122 
123 /* kill ep->value and replace by preceding one, poped from value stack */
124 static void
pop_val(entree * ep)125 pop_val(entree *ep)
126 {
127   var_cell *v = (var_cell*) ep->pvalue;
128   if (v != INITIAL)
129   {
130     GEN old_val = (GEN) ep->value; /* protect against SIGINT */
131     ep->value  = v->value;
132     if (v->flag == COPY_VAL) gunclone_deep(old_val);
133     ep->pvalue = (char*) v->prev;
134     ep->valence=v->valence;
135     pari_free((void*)v);
136   }
137 }
138 
139 void
freeep(entree * ep)140 freeep(entree *ep)
141 {
142   if (EpSTATIC(ep)) return; /* gp function loaded at init time */
143   if (ep->help) {pari_free((void*)ep->help); ep->help=NULL;}
144   if (ep->code) {pari_free((void*)ep->code); ep->code=NULL;}
145   switch(EpVALENCE(ep))
146   {
147     case EpVAR:
148       while (ep->pvalue!=INITIAL) pop_val(ep);
149       break;
150     case EpALIAS:
151       killblock((GEN)ep->value); ep->value=NULL; break;
152   }
153 }
154 
155 INLINE void
pushvalue(entree * ep,GEN x)156 pushvalue(entree *ep, GEN x) {
157   new_val_cell(ep, x, COPY_VAL);
158 }
159 
160 INLINE void
zerovalue(entree * ep)161 zerovalue(entree *ep)
162 {
163   var_cell *v = (var_cell*) pari_malloc(sizeof(var_cell));
164   v->value  = (GEN)ep->value;
165   v->prev   = (var_cell*) ep->pvalue;
166   v->flag   = PUSH_VAL;
167   v->valence= ep->valence;
168   ep->value = gen_0;
169   ep->pvalue= (char*)v;
170   ep->valence=EpVAR;
171 }
172 
173 /* as above IF ep->value was PUSHed, or was created after block number 'loc'
174    return 0 if not deleted, 1 otherwise [for recover()] */
175 int
pop_val_if_newer(entree * ep,long loc)176 pop_val_if_newer(entree *ep, long loc)
177 {
178   var_cell *v = (var_cell*) ep->pvalue;
179 
180   if (v == INITIAL) return 0;
181   if (v->flag == COPY_VAL && !pop_entree_block(ep, loc)) return 0;
182   ep->value = v->value;
183   ep->pvalue= (char*) v->prev;
184   ep->valence=v->valence;
185   pari_free((void*)v); return 1;
186 }
187 
188 /* set new value of ep directly to val (COPY), do not save last value unless
189  * it's INITIAL. */
190 void
changevalue(entree * ep,GEN x)191 changevalue(entree *ep, GEN x)
192 {
193   var_cell *v = (var_cell*) ep->pvalue;
194   if (v == INITIAL) new_val_cell(ep, x, COPY_VAL);
195   else
196   {
197     GEN old_val = (GEN) ep->value; /* beware: gunclone_deep may destroy old x */
198     ep->value = (void *) gclone(x);
199     if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL;
200   }
201 }
202 
203 INLINE GEN
copyvalue(entree * ep)204 copyvalue(entree *ep)
205 {
206   var_cell *v = (var_cell*) ep->pvalue;
207   if (v && v->flag != COPY_VAL)
208   {
209     ep->value = (void*) gclone((GEN)ep->value);
210     v->flag = COPY_VAL;
211   }
212   return (GEN) ep->value;
213 }
214 
215 INLINE void
err_var(GEN x)216 err_var(GEN x) { pari_err_TYPE("evaluator [variable name expected]", x); }
217 
218 enum chk_VALUE { chk_ERROR, chk_NOCREATE, chk_CREATE };
219 
220 INLINE void
checkvalue(entree * ep,enum chk_VALUE flag)221 checkvalue(entree *ep, enum chk_VALUE flag)
222 {
223   if (mt_is_thread())
224     pari_err(e_MISC,"mt: attempt to change exported variable '%s'",ep->name);
225   if (ep->valence==EpNEW)
226     switch(flag)
227     {
228       case chk_ERROR:
229         /* Do nothing until we can report a meaningful error message
230            The extra variable will be cleaned-up anyway */
231       case chk_CREATE:
232         pari_var_create(ep);
233         ep->valence = EpVAR;
234         ep->value = initial_value(ep);
235         break;
236       case chk_NOCREATE:
237         break;
238     }
239   else if (ep->valence!=EpVAR)
240     pari_err(e_MISC, "attempt to change built-in %s", ep->name);
241 }
242 
243 INLINE GEN
checkvalueptr(entree * ep)244 checkvalueptr(entree *ep)
245 {
246   checkvalue(ep, chk_NOCREATE);
247   return ep->valence==EpNEW? gen_0: (GEN)ep->value;
248 }
249 
250 /* make GP variables safe for set_avma(top) */
251 static void
lvar_make_safe(void)252 lvar_make_safe(void)
253 {
254   long n;
255   entree *ep;
256   for (n = 0; n < functions_tblsz; n++)
257     for (ep = functions_hash[n]; ep; ep = ep->next)
258       if (EpVALENCE(ep) == EpVAR)
259       { /* make sure ep->value is a COPY */
260         var_cell *v = (var_cell*)ep->pvalue;
261         if (v && v->flag == PUSH_VAL) {
262           GEN x = (GEN)ep->value;
263           if (x) changevalue(ep, (GEN)ep->value); else pop_val(ep);
264         }
265       }
266 }
267 
268 static void
check_array_index(long c,long l)269 check_array_index(long c, long l)
270 {
271   if (c < 1) pari_err_COMPONENT("", "<", gen_1, stoi(c));
272   if (c >= l) pari_err_COMPONENT("", ">", stoi(l-1), stoi(c));
273 }
274 
275 GEN*
safegel(GEN x,long l)276 safegel(GEN x, long l)
277 {
278   if (!is_matvec_t(typ(x)))
279     pari_err_TYPE("safegel",x);
280   check_array_index(l, lg(x));
281   return &(gel(x,l));
282 }
283 
284 GEN*
safelistel(GEN x,long l)285 safelistel(GEN x, long l)
286 {
287   GEN d;
288   if (typ(x)!=t_LIST || list_typ(x)!=t_LIST_RAW)
289     pari_err_TYPE("safelistel",x);
290   d = list_data(x);
291   check_array_index(l, lg(d));
292   return &(gel(d,l));
293 }
294 
295 long*
safeel(GEN x,long l)296 safeel(GEN x, long l)
297 {
298   if (typ(x)!=t_VECSMALL)
299     pari_err_TYPE("safeel",x);
300   check_array_index(l, lg(x));
301   return &(x[l]);
302 }
303 
304 GEN*
safegcoeff(GEN x,long a,long b)305 safegcoeff(GEN x, long a, long b)
306 {
307   if (typ(x)!=t_MAT) pari_err_TYPE("safegcoeff", x);
308   check_array_index(b, lg(x));
309   check_array_index(a, lg(gel(x,b)));
310   return &(gcoeff(x,a,b));
311 }
312 
313 typedef struct matcomp
314 {
315   GEN *ptcell;
316   GEN parent;
317   int full_col, full_row;
318 } matcomp;
319 
320 typedef struct gp_pointer
321 {
322   matcomp c;
323   GEN x, ox;
324   entree *ep;
325   long vn;
326   long sp;
327 } gp_pointer;
328 
329 /* assign res at *pt in "simple array object" p and return it, or a copy.*/
330 static void
change_compo(matcomp * c,GEN res)331 change_compo(matcomp *c, GEN res)
332 {
333   GEN p = c->parent, *pt = c->ptcell;
334   long i, t;
335 
336   if (typ(p) == t_VECSMALL)
337   {
338     if (typ(res) != t_INT || is_bigint(res))
339       pari_err_TYPE("t_VECSMALL assignment", res);
340     *pt = (GEN)itos(res); return;
341   }
342   t = typ(res);
343   if (c->full_row)
344   {
345     if (t != t_VEC) pari_err_TYPE("matrix row assignment", res);
346     if (lg(res) != lg(p)) pari_err_DIM("matrix row assignment");
347     for (i=1; i<lg(p); i++)
348     {
349       GEN p1 = gcoeff(p,c->full_row,i); /* Protect against SIGINT */
350       gcoeff(p,c->full_row,i) = gclone(gel(res,i));
351       if (isclone(p1)) gunclone_deep(p1);
352     }
353     return;
354   }
355   if (c->full_col)
356   {
357     if (t != t_COL) pari_err_TYPE("matrix col assignment", res);
358     if (lg(res) != lg(*pt)) pari_err_DIM("matrix col assignment");
359   }
360 
361   res = gclone(res);
362   gunclone_deep(*pt);
363   *pt = res;
364 }
365 
366 /***************************************************************************
367  **                                                                       **
368  **                           Byte-code evaluator                         **
369  **                                                                       **
370  ***************************************************************************/
371 
372 struct var_lex
373 {
374   long flag;
375   GEN value;
376 };
377 
378 struct trace
379 {
380   long pc;
381   GEN closure;
382 };
383 
384 static THREAD long sp, rp, dbg_level;
385 static THREAD long *st, *precs;
386 static THREAD GEN *locks;
387 static THREAD gp_pointer *ptrs;
388 static THREAD entree **lvars;
389 static THREAD struct var_lex *var;
390 static THREAD struct trace *trace;
391 static THREAD pari_stack s_st, s_ptrs, s_var, s_trace, s_prec;
392 static THREAD pari_stack s_lvars, s_locks;
393 
394 static void
changelex(long vn,GEN x)395 changelex(long vn, GEN x)
396 {
397   struct var_lex *v=var+s_var.n+vn;
398   GEN old_val = v->value;
399   v->value = gclone(x);
400   if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL;
401 }
402 
403 INLINE GEN
copylex(long vn)404 copylex(long vn)
405 {
406   struct var_lex *v = var+s_var.n+vn;
407   if (v->flag!=COPY_VAL && v->flag!=REF_VAL)
408   {
409     v->value = gclone(v->value);
410     v->flag  = COPY_VAL;
411   }
412   return v->value;
413 }
414 
415 INLINE void
setreflex(long vn)416 setreflex(long vn)
417 {
418   struct var_lex *v = var+s_var.n+vn;
419   v->flag  = REF_VAL;
420 }
421 
422 INLINE void
pushlex(long vn,GEN x)423 pushlex(long vn, GEN x)
424 {
425   struct var_lex *v=var+s_var.n+vn;
426   v->flag  = PUSH_VAL;
427   v->value = x;
428 }
429 
430 INLINE void
freelex(void)431 freelex(void)
432 {
433   struct var_lex *v=var+s_var.n-1;
434   s_var.n--;
435   if (v->flag == COPY_VAL) gunclone_deep(v->value);
436 }
437 
438 INLINE void
restore_vars(long nbmvar,long nblvar,long nblock)439 restore_vars(long nbmvar, long nblvar, long nblock)
440 {
441   long j;
442   for(j=1;j<=nbmvar;j++)
443     freelex();
444   for(j=1;j<=nblvar;j++)
445     { s_lvars.n--; pop_val(lvars[s_lvars.n]); }
446   for(j=1;j<=nblock;j++)
447     { s_locks.n--; gunclone(locks[s_locks.n]); }
448 }
449 
450 INLINE void
restore_trace(long nbtrace)451 restore_trace(long nbtrace)
452 {
453   long j;
454   for(j=1;j<=nbtrace;j++)
455   {
456     GEN C = trace[s_trace.n-j].closure;
457     clone_unlock(C);
458   }
459   s_trace.n-=nbtrace;
460 }
461 
462 INLINE long
trace_push(long pc,GEN C)463 trace_push(long pc, GEN C)
464 {
465   long tr;
466   BLOCK_SIGINT_START
467   tr = pari_stack_new(&s_trace);
468   trace[tr].pc = pc;
469   clone_lock(C);
470   trace[tr].closure = C;
471   BLOCK_SIGINT_END
472   return tr;
473 }
474 
475 void
push_lex(GEN a,GEN C)476 push_lex(GEN a, GEN C)
477 {
478   long vn=pari_stack_new(&s_var);
479   struct var_lex *v=var+vn;
480   v->flag  = PUSH_VAL;
481   v->value = a;
482   if (C) (void) trace_push(-1, C);
483 }
484 
485 GEN
get_lex(long vn)486 get_lex(long vn)
487 {
488   struct var_lex *v=var+s_var.n+vn;
489   return v->value;
490 }
491 
492 void
set_lex(long vn,GEN x)493 set_lex(long vn, GEN x)
494 {
495   struct var_lex *v=var+s_var.n+vn;
496   if (v->flag == COPY_VAL) { gunclone_deep(v->value); v->flag = PUSH_VAL; }
497   v->value = x;
498 }
499 
500 void
pop_lex(long n)501 pop_lex(long n)
502 {
503   long j;
504   for(j=1; j<=n; j++)
505     freelex();
506   s_trace.n--;
507 }
508 
509 static THREAD pari_stack s_relocs;
510 static THREAD entree **relocs;
511 
512 void
pari_init_evaluator(void)513 pari_init_evaluator(void)
514 {
515   sp=0;
516   pari_stack_init(&s_st,sizeof(*st),(void**)&st);
517   pari_stack_alloc(&s_st,32);
518   s_st.n=s_st.alloc;
519   rp=0;
520   pari_stack_init(&s_ptrs,sizeof(*ptrs),(void**)&ptrs);
521   pari_stack_alloc(&s_ptrs,16);
522   s_ptrs.n=s_ptrs.alloc;
523   pari_stack_init(&s_var,sizeof(*var),(void**)&var);
524   pari_stack_init(&s_lvars,sizeof(*lvars),(void**)&lvars);
525   pari_stack_init(&s_locks,sizeof(*locks),(void**)&locks);
526   pari_stack_init(&s_trace,sizeof(*trace),(void**)&trace);
527   br_res = NULL;
528   pari_stack_init(&s_relocs,sizeof(*relocs),(void**)&relocs);
529   pari_stack_init(&s_prec,sizeof(*precs),(void**)&precs);
530 }
531 void
pari_close_evaluator(void)532 pari_close_evaluator(void)
533 {
534   pari_stack_delete(&s_st);
535   pari_stack_delete(&s_ptrs);
536   pari_stack_delete(&s_var);
537   pari_stack_delete(&s_lvars);
538   pari_stack_delete(&s_trace);
539   pari_stack_delete(&s_relocs);
540   pari_stack_delete(&s_prec);
541 }
542 
543 static gp_pointer *
new_ptr(void)544 new_ptr(void)
545 {
546   if (rp==s_ptrs.n-1)
547   {
548     long i;
549     gp_pointer *old = ptrs;
550     (void)pari_stack_new(&s_ptrs);
551     if (old != ptrs)
552       for(i=0; i<rp; i++)
553       {
554         gp_pointer *g = &ptrs[i];
555         if(g->sp >= 0) gel(st,g->sp) = (GEN) &(g->x);
556       }
557   }
558   return &ptrs[rp++];
559 }
560 
561 void
push_localbitprec(long p)562 push_localbitprec(long p)
563 {
564   long n = pari_stack_new(&s_prec);
565   precs[n] = p;
566 }
567 void
push_localprec(long p)568 push_localprec(long p) { push_localbitprec(prec2nbits(p)); }
569 
570 void
pop_localprec(void)571 pop_localprec(void) { s_prec.n--; }
572 
573 long
get_localbitprec(void)574 get_localbitprec(void) { return s_prec.n? precs[s_prec.n-1]: precreal; }
575 
576 long
get_localprec(void)577 get_localprec(void) { return nbits2prec(get_localbitprec()); }
578 
579 static void
checkprec(const char * f,long p,long M)580 checkprec(const char *f, long p, long M)
581 {
582   if (p < 1) pari_err_DOMAIN(f, "p", "<", gen_1, stoi(p));
583   if (p > M) pari_err_DOMAIN(f, "p", ">", utoipos(M), utoi(p));
584 }
585 static long
_prec(GEN p,const char * f)586 _prec(GEN p, const char *f)
587 {
588   pari_sp av = avma;
589   if (typ(p) == t_INT) return itos(p);
590   p = gceil(p);
591   if (typ(p) != t_INT) pari_err_TYPE(f, p);
592   return gc_long(av, itos(p));
593 }
594 void
localprec(GEN pp)595 localprec(GEN pp)
596 {
597   long p = _prec(pp, "localprec");
598   checkprec("localprec", p, prec2ndec(LGBITS));
599   p = ndec2nbits(p); push_localbitprec(p);
600 }
601 void
localbitprec(GEN pp)602 localbitprec(GEN pp)
603 {
604   long p = _prec(pp, "localbitprec");
605   checkprec("localbitprec", p, (long)LGBITS);
606   push_localbitprec(p);
607 }
608 long
getlocalprec(long prec)609 getlocalprec(long prec) { return prec2ndec(prec); }
610 long
getlocalbitprec(long bit)611 getlocalbitprec(long bit) { return bit; }
612 
613 static GEN
_precision0(GEN x)614 _precision0(GEN x)
615 {
616   long a = gprecision(x);
617   return a? utoi(prec2ndec(a)): mkoo();
618 }
619 GEN
precision0(GEN x,long n)620 precision0(GEN x, long n)
621 { return n? gprec(x,n): _precision0(x); }
622 static GEN
_bitprecision0(GEN x)623 _bitprecision0(GEN x)
624 {
625   long a = gprecision(x);
626   return a? utoi(prec2nbits(a)): mkoo();
627 }
628 GEN
bitprecision0(GEN x,long n)629 bitprecision0(GEN x, long n)
630 {
631   if (n < 0)
632     pari_err_DOMAIN("bitprecision", "bitprecision", "<", gen_0, stoi(n));
633   if (n) {
634     pari_sp av = avma;
635     GEN y = gprec_w(x, nbits2prec(n));
636     return gerepilecopy(av, y);
637   }
638   return _bitprecision0(x);
639 }
640 GEN
precision00(GEN x,GEN n)641 precision00(GEN x, GEN n)
642 {
643   if (!n) return _precision0(x);
644   return precision0(x, _prec(n, "precision"));
645 }
646 GEN
bitprecision00(GEN x,GEN n)647 bitprecision00(GEN x, GEN n)
648 {
649   if (!n) return _bitprecision0(x);
650   return bitprecision0(x, _prec(n, "bitprecision"));
651 }
652 
653 INLINE GEN
copyupto(GEN z,GEN t)654 copyupto(GEN z, GEN t)
655 {
656   if (is_universal_constant(z) || (z>(GEN)pari_mainstack->bot && z<=t))
657     return z;
658   else
659     return gcopy(z);
660 }
661 
662 static void closure_eval(GEN C);
663 
664 INLINE GEN
get_and_reset_break(void)665 get_and_reset_break(void)
666 {
667   GEN z = br_res? gcopy(br_res): gnil;
668   reset_break(); return z;
669 }
670 
671 INLINE GEN
closure_return(GEN C)672 closure_return(GEN C)
673 {
674   pari_sp av = avma;
675   closure_eval(C);
676   if (br_status) { set_avma(av); return get_and_reset_break(); }
677   return gerepileupto(av, gel(st,--sp));
678 }
679 
680 /* for the break_loop debugger. Not memory clean */
681 GEN
closure_evalbrk(GEN C,long * status)682 closure_evalbrk(GEN C, long *status)
683 {
684   closure_eval(C); *status = br_status;
685   return br_status? get_and_reset_break(): gel(st,--sp);
686 }
687 
688 INLINE long
closure_varn(GEN x)689 closure_varn(GEN x)
690 {
691   if (!x) return -1;
692   if (!gequalX(x)) err_var(x);
693   return varn(x);
694 }
695 
696 INLINE void
closure_castgen(GEN z,long mode)697 closure_castgen(GEN z, long mode)
698 {
699   switch (mode)
700   {
701   case Ggen:
702     gel(st,sp++)=z;
703     break;
704   case Gsmall:
705     st[sp++]=gtos(z);
706     break;
707   case Gusmall:
708     st[sp++]=gtou(z);
709     break;
710   case Gvar:
711     st[sp++]=closure_varn(z);
712     break;
713   case Gvoid:
714     break;
715   default:
716     pari_err_BUG("closure_castgen, type unknown");
717   }
718 }
719 
720 INLINE void
closure_castlong(long z,long mode)721 closure_castlong(long z, long mode)
722 {
723   switch (mode)
724   {
725   case Gsmall:
726     st[sp++]=z;
727     break;
728   case Gusmall:
729     if (z < 0)
730       pari_err_TYPE("stou [integer >=0 expected]", stoi(z));
731     st[sp++]=(ulong) z;
732     break;
733   case Ggen:
734     gel(st,sp++)=stoi(z);
735     break;
736   case Gvar:
737     err_var(stoi(z));
738   case Gvoid:
739     break;
740   default:
741     pari_err_BUG("closure_castlong, type unknown");
742   }
743 }
744 
745 const char *
closure_func_err(void)746 closure_func_err(void)
747 {
748   long fun=s_trace.n-1, pc;
749   const char *code;
750   GEN C, oper;
751   if (fun < 0 || trace[fun].pc < 0) return NULL;
752   pc = trace[fun].pc; C  = trace[fun].closure;
753   code = closure_codestr(C); oper = closure_get_oper(C);
754   if (code[pc]==OCcallgen || code[pc]==OCcallgen2 ||
755       code[pc]==OCcallint || code[pc]==OCcalllong || code[pc]==OCcallvoid)
756     return ((entree*)oper[pc])->name;
757   return NULL;
758 }
759 
760 /* return the next label for the call chain debugger closure_err(),
761  * incorporating the name of the user of member function. Return NULL for an
762  * anonymous (inline) closure. */
763 static char *
get_next_label(const char * s,int member,char ** next_fun)764 get_next_label(const char *s, int member, char **next_fun)
765 {
766   const char *v, *t = s+1;
767   char *u, *next_label;
768 
769   if (!is_keyword_char(*s)) return NULL;
770   while (is_keyword_char(*t)) t++;
771   /* e.g. (x->1/x)(0) instead of (x)->1/x */
772   if (t[0] == '-' && t[1] == '>') return NULL;
773   next_label = (char*)pari_malloc(t - s + 32);
774   sprintf(next_label, "in %sfunction ", member? "member ": "");
775   u = *next_fun = next_label + strlen(next_label);
776   v = s;
777   while (v < t) *u++ = *v++;
778   *u++ = 0; return next_label;
779 }
780 
781 static const char *
get_arg_name(GEN C,long i)782 get_arg_name(GEN C, long i)
783 {
784   GEN d = closure_get_dbg(C), frpc = gel(d,2), fram = gel(d,3);
785   long j, l = lg(frpc);
786   for (j=1; j<l; j++)
787     if (frpc[j]==1 && i<lg(gel(fram,j)))
788       return ((entree*)mael(fram,j,i))->name;
789   return "(unnamed)";
790 }
791 
792 void
closure_err(long level)793 closure_err(long level)
794 {
795   GEN base;
796   const long lastfun = s_trace.n - 1 - level;
797   char *next_label, *next_fun;
798   long i = maxss(0, lastfun - 19);
799   if (lastfun < 0) return; /*e.g. when called by gp_main_loop's simplify */
800   if (i > 0) while (lg(trace[i].closure)==6) i--;
801   base = closure_get_text(trace[i].closure); /* gcc -Wall*/
802   next_label = pari_strdup(i == 0? "at top-level": "[...] at");
803   next_fun = next_label;
804   for (; i <= lastfun; i++)
805   {
806     GEN C = trace[i].closure;
807     if (lg(C) >= 7) base=closure_get_text(C);
808     if ((i==lastfun || lg(trace[i+1].closure)>=7))
809     {
810       GEN dbg = gel(closure_get_dbg(C),1);
811       /* After a SIGINT, pc can be slightly off: ensure 0 <= pc < lg() */
812       long pc = minss(lg(dbg)-1, trace[i].pc>=0 ? trace[i].pc: 1);
813       long offset = pc? dbg[pc]: 0;
814       int member;
815       const char *s, *sbase;
816       if (typ(base)!=t_VEC) sbase = GSTR(base);
817       else if (offset>=0)   sbase = GSTR(gel(base,2));
818       else { sbase = GSTR(gel(base,1)); offset += strlen(sbase); }
819       s = sbase + offset;
820       member = offset>0 && (s[-1] == '.');
821       /* avoid "in function foo: foo" */
822       if (!next_fun || strcmp(next_fun, s)) {
823         print_errcontext(pariErr, next_label, s, sbase);
824         out_putc(pariErr, '\n');
825       }
826       pari_free(next_label);
827       if (i == lastfun) break;
828 
829       next_label = get_next_label(s, member, &next_fun);
830       if (!next_label) {
831         next_label = pari_strdup("in anonymous function");
832         next_fun = NULL;
833       }
834     }
835   }
836 }
837 
838 GEN
pari_self(void)839 pari_self(void)
840 {
841   long fun = s_trace.n - 1;
842   if (fun > 0) while (lg(trace[fun].closure)==6) fun--;
843   return fun >= 0 ? trace[fun].closure: NULL;
844 }
845 
846 long
closure_context(long start,long level)847 closure_context(long start, long level)
848 {
849   const long lastfun = s_trace.n - 1 - level;
850   long i, fun = lastfun;
851   if (fun<0) return lastfun;
852   while (fun>start && lg(trace[fun].closure)==6) fun--;
853   for (i=fun; i <= lastfun; i++)
854     push_frame(trace[i].closure, trace[i].pc,0);
855   for (  ; i < s_trace.n; i++)
856     push_frame(trace[i].closure, trace[i].pc,1);
857   return s_trace.n-level;
858 }
859 
860 INLINE void
st_alloc(long n)861 st_alloc(long n)
862 {
863   if (sp+n>s_st.n)
864   {
865     pari_stack_alloc(&s_st,n+16);
866     s_st.n=s_st.alloc;
867     if (DEBUGMEM>=2) pari_warn(warner,"doubling evaluator stack");
868   }
869 }
870 
871 INLINE void
ptr_proplock(gp_pointer * g,GEN C)872 ptr_proplock(gp_pointer *g, GEN C)
873 {
874   g->x = C;
875   if (isclone(g->x))
876   {
877     clone_unlock_deep(g->ox);
878     g->ox = g->x;
879     ++bl_refc(g->ox);
880   }
881 }
882 
883 static void
closure_eval(GEN C)884 closure_eval(GEN C)
885 {
886   const char *code=closure_codestr(C);
887   GEN oper=closure_get_oper(C);
888   GEN data=closure_get_data(C);
889   long loper=lg(oper);
890   long saved_sp=sp-closure_arity(C);
891   long saved_rp=rp, saved_prec=s_prec.n;
892   long j, nbmvar=0, nblvar=0, nblock=0;
893   long pc, t;
894 #ifdef STACK_CHECK
895   GEN stackelt;
896   if (PARI_stack_limit && (void*) &stackelt <= PARI_stack_limit)
897     pari_err(e_MISC, "deep recursion");
898 #endif
899   t = trace_push(0, C);
900   if (lg(C)==8)
901   {
902     GEN z=closure_get_frame(C);
903     long l=lg(z)-1;
904     pari_stack_alloc(&s_var,l);
905     s_var.n+=l;
906     nbmvar+=l;
907     for(j=1;j<=l;j++)
908     {
909       var[s_var.n-j].flag=PUSH_VAL;
910       var[s_var.n-j].value=gel(z,j);
911     }
912   }
913 
914   for(pc=1;pc<loper;pc++)
915   {
916     op_code opcode=(op_code) code[pc];
917     long operand=oper[pc];
918     if (sp<0) pari_err_BUG("closure_eval, stack underflow");
919     st_alloc(16);
920     trace[t].pc = pc;
921     CHECK_CTRLC
922     switch(opcode)
923     {
924     case OCpushlong:
925       st[sp++]=operand;
926       break;
927     case OCpushgnil:
928       gel(st,sp++)=gnil;
929       break;
930     case OCpushgen:
931       gel(st,sp++)=gel(data,operand);
932       break;
933     case OCpushreal:
934       gel(st,sp++)=strtor(GSTR(data[operand]),get_localprec());
935       break;
936     case OCpushstoi:
937       gel(st,sp++)=stoi(operand);
938       break;
939     case OCpushvar:
940       {
941         entree *ep = (entree *)operand;
942         gel(st,sp++)=pol_x(pari_var_create(ep));
943         break;
944       }
945     case OCpushdyn:
946       {
947         entree *ep = (entree *)operand;
948         if (!mt_is_thread())
949         {
950           checkvalue(ep, chk_CREATE);
951           gel(st,sp++)=(GEN)ep->value;
952         } else
953         {
954           GEN val = export_get(ep->name);
955           if (!val)
956             pari_err(e_MISC,"mt: please use export(%s)", ep->name);
957           gel(st,sp++)=val;
958         }
959         break;
960       }
961     case OCpushlex:
962       gel(st,sp++)=var[s_var.n+operand].value;
963       break;
964     case OCsimpleptrdyn:
965       {
966         gp_pointer *g = new_ptr();
967         g->vn=0;
968         g->ep = (entree*) operand;
969         g->x = checkvalueptr(g->ep);
970         g->ox = g->x; clone_lock(g->ox);
971         g->sp = sp;
972         gel(st,sp++) = (GEN)&(g->x);
973         break;
974       }
975     case OCsimpleptrlex:
976       {
977         gp_pointer *g = new_ptr();
978         g->vn=operand;
979         g->ep=(entree *)0x1L;
980         g->x = (GEN) var[s_var.n+operand].value;
981         g->ox = g->x; clone_lock(g->ox);
982         g->sp = sp;
983         gel(st,sp++) = (GEN)&(g->x);
984         break;
985       }
986     case OCnewptrdyn:
987       {
988         entree *ep = (entree *)operand;
989         gp_pointer *g = new_ptr();
990         matcomp *C;
991         checkvalue(ep, chk_ERROR);
992         g->sp = -1;
993         g->x = copyvalue(ep);
994         g->ox = g->x; clone_lock(g->ox);
995         g->vn=0;
996         g->ep=NULL;
997         C=&g->c;
998         C->full_col = C->full_row = 0;
999         C->parent   = (GEN)    g->x;
1000         C->ptcell   = (GEN *) &g->x;
1001         break;
1002       }
1003     case OCnewptrlex:
1004       {
1005         gp_pointer *g = new_ptr();
1006         matcomp *C;
1007         g->sp = -1;
1008         g->x = copylex(operand);
1009         g->ox = g->x; clone_lock(g->ox);
1010         g->vn=0;
1011         g->ep=NULL;
1012         C=&g->c;
1013         C->full_col = C->full_row = 0;
1014         C->parent   = (GEN)     g->x;
1015         C->ptcell   = (GEN *) &(g->x);
1016         break;
1017       }
1018     case OCpushptr:
1019       {
1020         gp_pointer *g = &ptrs[rp-1];
1021         g->sp = sp;
1022         gel(st,sp++) = (GEN)&(g->x);
1023       }
1024       break;
1025     case OCendptr:
1026       for(j=0;j<operand;j++)
1027       {
1028         gp_pointer *g = &ptrs[--rp];
1029         if (g->ep)
1030         {
1031           if (g->vn)
1032             changelex(g->vn, g->x);
1033           else
1034             changevalue(g->ep, g->x);
1035         }
1036         else change_compo(&(g->c), g->x);
1037         clone_unlock_deep(g->ox);
1038       }
1039       break;
1040     case OCstoredyn:
1041       {
1042         entree *ep = (entree *)operand;
1043         checkvalue(ep, chk_NOCREATE);
1044         changevalue(ep, gel(st,--sp));
1045         break;
1046       }
1047     case OCstorelex:
1048       changelex(operand,gel(st,--sp));
1049       break;
1050     case OCstoreptr:
1051       {
1052         gp_pointer *g = &ptrs[--rp];
1053         change_compo(&(g->c), gel(st,--sp));
1054         clone_unlock_deep(g->ox);
1055         break;
1056       }
1057     case OCstackgen:
1058       {
1059         GEN z = gerepileupto(st[sp-2],gel(st,sp-1));
1060         gmael(st,sp-3,operand) = copyupto(z,gel(st,sp-2));
1061         st[sp-2] = avma;
1062         sp--;
1063         break;
1064       }
1065     case OCprecreal:
1066       st[sp++]=get_localprec();
1067       break;
1068     case OCbitprecreal:
1069       st[sp++]=get_localbitprec();
1070       break;
1071     case OCprecdl:
1072       st[sp++]=precdl;
1073       break;
1074     case OCavma:
1075       st[sp++]=avma;
1076       break;
1077     case OCcowvardyn:
1078       {
1079         entree *ep = (entree *)operand;
1080         checkvalue(ep, chk_ERROR);
1081         (void)copyvalue(ep);
1082         break;
1083       }
1084     case OCcowvarlex:
1085       (void)copylex(operand);
1086       break;
1087     case OCsetref:
1088       setreflex(operand);
1089       break;
1090     case OClock:
1091     {
1092       GEN v = gel(st,sp-1);
1093       if (isclone(v))
1094       {
1095         long n = pari_stack_new(&s_locks);
1096         locks[n] = v;
1097         nblock++;
1098         ++bl_refc(v);
1099       }
1100       break;
1101     }
1102     case OCstoi:
1103       gel(st,sp-1)=stoi(st[sp-1]);
1104       break;
1105     case OCutoi:
1106       gel(st,sp-1)=utoi(st[sp-1]);
1107       break;
1108     case OCitos:
1109       st[sp+operand]=gtos(gel(st,sp+operand));
1110       break;
1111     case OCitou:
1112       st[sp+operand]=gtou(gel(st,sp+operand));
1113       break;
1114     case OCtostr:
1115       {
1116         GEN z = gel(st,sp+operand);
1117         st[sp+operand] = (long) (z ? GENtostr_unquoted(z): NULL);
1118         break;
1119       }
1120     case OCvarn:
1121       st[sp+operand] = closure_varn(gel(st,sp+operand));
1122       break;
1123     case OCcopy:
1124       gel(st,sp-1) = gcopy(gel(st,sp-1));
1125       break;
1126     case OCgerepile:
1127     {
1128       pari_sp av;
1129       GEN x;
1130       sp--;
1131       av = st[sp-1];
1132       x = gel(st,sp);
1133       if (isonstack(x))
1134       {
1135         pari_sp av2 = (pari_sp)(x + lg(x));
1136         if ((long) (av - av2) > 1000000L)
1137         {
1138           if (DEBUGMEM>=2)
1139             pari_warn(warnmem,"eval: recovering %ld bytes", av - av2);
1140           x = gerepileupto(av, x);
1141         }
1142       } else set_avma(av);
1143       gel(st,sp-1) = x;
1144       break;
1145     }
1146     case OCcopyifclone:
1147       if (isclone(gel(st,sp-1)))
1148         gel(st,sp-1) = gcopy(gel(st,sp-1));
1149       break;
1150     case OCcompo1:
1151       {
1152         GEN  p=gel(st,sp-2);
1153         long c=st[sp-1];
1154         sp-=2;
1155         switch(typ(p))
1156         {
1157         case t_VEC: case t_COL:
1158           check_array_index(c, lg(p));
1159           closure_castgen(gel(p,c),operand);
1160           break;
1161         case t_LIST:
1162           {
1163             long lx;
1164             if (list_typ(p)!=t_LIST_RAW)
1165               pari_err_TYPE("_[_] OCcompo1 [not a vector]", p);
1166             p = list_data(p); lx = p? lg(p): 1;
1167             check_array_index(c, lx);
1168             closure_castgen(gel(p,c),operand);
1169             break;
1170           }
1171         case t_VECSMALL:
1172           check_array_index(c,lg(p));
1173           closure_castlong(p[c],operand);
1174           break;
1175         default:
1176           pari_err_TYPE("_[_] OCcompo1 [not a vector]", p);
1177           break;
1178         }
1179         break;
1180       }
1181     case OCcompo1ptr:
1182       {
1183         long c=st[sp-1];
1184         long lx;
1185         gp_pointer *g = &ptrs[rp-1];
1186         matcomp *C=&g->c;
1187         GEN p = g->x;
1188         sp--;
1189         switch(typ(p))
1190         {
1191         case t_VEC: case t_COL:
1192           check_array_index(c, lg(p));
1193           C->ptcell = (GEN *) p+c;
1194           ptr_proplock(g, *(C->ptcell));
1195           break;
1196         case t_VECSMALL:
1197           check_array_index(c, lg(p));
1198           C->ptcell = (GEN *) p+c;
1199           g->x = stoi(p[c]);
1200           break;
1201         case t_LIST:
1202           if (list_typ(p)!=t_LIST_RAW)
1203             pari_err_TYPE("&_[_] OCcompo1 [not a vector]", p);
1204           p = list_data(p); lx = p? lg(p): 1;
1205           check_array_index(c,lx);
1206           C->ptcell = (GEN *) p+c;
1207           ptr_proplock(g, *(C->ptcell));
1208           break;
1209         default:
1210           pari_err_TYPE("&_[_] OCcompo1ptr [not a vector]", p);
1211         }
1212         C->parent   = p;
1213         break;
1214       }
1215     case OCcompo2:
1216       {
1217         GEN  p=gel(st,sp-3);
1218         long c=st[sp-2];
1219         long d=st[sp-1];
1220         if (typ(p)!=t_MAT) pari_err_TYPE("_[_,_] OCcompo2 [not a matrix]", p);
1221         check_array_index(d, lg(p));
1222         check_array_index(c, lg(gel(p,d)));
1223         sp-=3;
1224         closure_castgen(gcoeff(p,c,d),operand);
1225         break;
1226       }
1227     case OCcompo2ptr:
1228       {
1229         long c=st[sp-2];
1230         long d=st[sp-1];
1231         gp_pointer *g = &ptrs[rp-1];
1232         matcomp *C=&g->c;
1233         GEN p = g->x;
1234         sp-=2;
1235         if (typ(p)!=t_MAT)
1236           pari_err_TYPE("&_[_,_] OCcompo2ptr [not a matrix]", p);
1237         check_array_index(d, lg(p));
1238         check_array_index(c, lg(gel(p,d)));
1239         C->ptcell = (GEN *) gel(p,d)+c;
1240         C->parent   = p;
1241         ptr_proplock(g, *(C->ptcell));
1242         break;
1243       }
1244     case OCcompoC:
1245       {
1246         GEN  p=gel(st,sp-2);
1247         long c=st[sp-1];
1248         if (typ(p)!=t_MAT)
1249           pari_err_TYPE("_[,_] OCcompoC [not a matrix]", p);
1250         check_array_index(c, lg(p));
1251         sp--;
1252         gel(st,sp-1) = gel(p,c);
1253         break;
1254       }
1255     case OCcompoCptr:
1256       {
1257         long c=st[sp-1];
1258         gp_pointer *g = &ptrs[rp-1];
1259         matcomp *C=&g->c;
1260         GEN p = g->x;
1261         sp--;
1262         if (typ(p)!=t_MAT)
1263           pari_err_TYPE("&_[,_] OCcompoCptr [not a matrix]", p);
1264         check_array_index(c, lg(p));
1265         C->ptcell = (GEN *) p+c;
1266         C->full_col = c;
1267         C->parent   = p;
1268         ptr_proplock(g, *(C->ptcell));
1269         break;
1270       }
1271     case OCcompoL:
1272       {
1273         GEN  p=gel(st,sp-2);
1274         long r=st[sp-1];
1275         sp--;
1276         if (typ(p)!=t_MAT)
1277           pari_err_TYPE("_[_,] OCcompoL [not a matrix]", p);
1278         check_array_index(r,lg(p) == 1? 1: lgcols(p));
1279         gel(st,sp-1) = row(p,r);
1280         break;
1281       }
1282     case OCcompoLptr:
1283       {
1284         long r=st[sp-1];
1285         gp_pointer *g = &ptrs[rp-1];
1286         matcomp *C=&g->c;
1287         GEN p = g->x, p2;
1288         sp--;
1289         if (typ(p)!=t_MAT)
1290           pari_err_TYPE("&_[_,] OCcompoLptr [not a matrix]", p);
1291         check_array_index(r,lg(p) == 1? 1: lgcols(p));
1292         p2 = rowcopy(p,r);
1293         C->full_row = r; /* record row number */
1294         C->ptcell = &p2;
1295         C->parent   = p;
1296         g->x = p2;
1297         break;
1298       }
1299     case OCdefaultarg:
1300       if (var[s_var.n+operand].flag==DEFAULT_VAL)
1301       {
1302         GEN z = gel(st,sp-1);
1303         if (typ(z)==t_CLOSURE)
1304         {
1305           pushlex(operand, closure_evalnobrk(z));
1306           copylex(operand);
1307         }
1308         else
1309           pushlex(operand, z);
1310       }
1311       sp--;
1312       break;
1313     case OClocalvar:
1314       {
1315         long n;
1316         entree *ep = (entree *)operand;
1317         checkvalue(ep, chk_NOCREATE);
1318         n = pari_stack_new(&s_lvars);
1319         lvars[n] = ep;
1320         nblvar++;
1321         pushvalue(ep,gel(st,--sp));
1322         break;
1323       }
1324     case OClocalvar0:
1325       {
1326         long n;
1327         entree *ep = (entree *)operand;
1328         checkvalue(ep, chk_NOCREATE);
1329         n = pari_stack_new(&s_lvars);
1330         lvars[n] = ep;
1331         nblvar++;
1332         zerovalue(ep);
1333         break;
1334       }
1335     case OCexportvar:
1336       {
1337         entree *ep = (entree *)operand;
1338         mt_export_add(ep->name, gel(st,--sp));
1339         break;
1340       }
1341     case OCunexportvar:
1342       {
1343         entree *ep = (entree *)operand;
1344         mt_export_del(ep->name);
1345         break;
1346       }
1347 
1348 #define EVAL_f(f) \
1349   switch (ep->arity) \
1350   { \
1351     case 0: f(); break; \
1352     case 1: sp--; f(st[sp]); break; \
1353     case 2: sp-=2; f(st[sp],st[sp+1]); break; \
1354     case 3: sp-=3; f(st[sp],st[sp+1],st[sp+2]); break; \
1355     case 4: sp-=4; f(st[sp],st[sp+1],st[sp+2],st[sp+3]); break; \
1356     case 5: sp-=5; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4]); break; \
1357     case 6: sp-=6; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5]); break; \
1358     case 7: sp-=7; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6]); break; \
1359     case 8: sp-=8; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7]); break; \
1360     case 9: sp-=9; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8]); break; \
1361     case 10: sp-=10; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9]); break; \
1362     case 11: sp-=11; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10]); break; \
1363     case 12: sp-=12; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11]); break; \
1364     case 13: sp-=13; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12]); break; \
1365     case 14: sp-=14; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13]); break; \
1366     case 15: sp-=15; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14]); break; \
1367     case 16: sp-=16; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15]); break; \
1368     case 17: sp-=17; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16]); break; \
1369     case 18: sp-=18; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17]); break; \
1370     case 19: sp-=19; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17],st[sp+18]); break; \
1371     case 20: sp-=20; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17],st[sp+18],st[sp+19]); break; \
1372     default: \
1373       pari_err_IMPL("functions with more than 20 parameters");\
1374       goto endeval; /*LCOV_EXCL_LINE*/ \
1375   }
1376 
1377     case OCcallgen:
1378       {
1379         entree *ep = (entree *)operand;
1380         GEN res;
1381         /* Macro Madness : evaluate function ep->value on arguments
1382          * st[sp-ep->arity .. sp]. Set res = result. */
1383         EVAL_f(res = ((GEN (*)(ANYARG))ep->value));
1384         if (br_status) goto endeval;
1385         gel(st,sp++)=res;
1386         break;
1387       }
1388     case OCcallgen2: /*same for ep->arity = 2. Is this optimization worth it ?*/
1389       {
1390         entree *ep = (entree *)operand;
1391         GEN res;
1392         sp-=2;
1393         res = ((GEN (*)(GEN,GEN))ep->value)(gel(st,sp),gel(st,sp+1));
1394         if (br_status) goto endeval;
1395         gel(st,sp++)=res;
1396         break;
1397       }
1398     case OCcalllong:
1399       {
1400         entree *ep = (entree *)operand;
1401         long res;
1402         EVAL_f(res = ((long (*)(ANYARG))ep->value));
1403         if (br_status) goto endeval;
1404         st[sp++] = res;
1405         break;
1406       }
1407     case OCcallint:
1408       {
1409         entree *ep = (entree *)operand;
1410         long res;
1411         EVAL_f(res = ((int (*)(ANYARG))ep->value));
1412         if (br_status) goto endeval;
1413         st[sp++] = res;
1414         break;
1415       }
1416     case OCcallvoid:
1417       {
1418         entree *ep = (entree *)operand;
1419         EVAL_f(((void (*)(ANYARG))ep->value));
1420         if (br_status) goto endeval;
1421         break;
1422       }
1423 #undef EVAL_f
1424 
1425     case OCcalluser:
1426       {
1427         long n=operand;
1428         GEN fun = gel(st,sp-1-n);
1429         long arity, isvar;
1430         GEN z;
1431         if (typ(fun)!=t_CLOSURE) pari_err(e_NOTFUNC, fun);
1432         isvar = closure_is_variadic(fun);
1433         arity = closure_arity(fun);
1434         if (!isvar || n < arity)
1435         {
1436           st_alloc(arity-n);
1437           if (n>arity)
1438             pari_err(e_MISC,"too many parameters in user-defined function call");
1439           for (j=n+1;j<=arity;j++)
1440             gel(st,sp++)=0;
1441           if (isvar) gel(st,sp-1) = cgetg(1,t_VEC);
1442         }
1443         else
1444         {
1445           GEN v;
1446           long j, m = n-arity+1;
1447           v = cgetg(m+1,t_VEC);
1448           sp-=m;
1449           for (j=1; j<=m; j++)
1450             gel(v,j) = gel(st,sp+j-1)? gcopy(gel(st,sp+j-1)): gen_0;
1451           gel(st,sp++)=v;
1452         }
1453         z = closure_return(fun);
1454         if (br_status) goto endeval;
1455         gel(st, sp-1) = z;
1456         break;
1457       }
1458     case OCnewframe:
1459       if (operand>0) nbmvar+=operand;
1460       else operand=-operand;
1461       pari_stack_alloc(&s_var,operand);
1462       s_var.n+=operand;
1463       for(j=1;j<=operand;j++)
1464       {
1465         var[s_var.n-j].flag=PUSH_VAL;
1466         var[s_var.n-j].value=gen_0;
1467       }
1468       break;
1469     case OCsaveframe:
1470       {
1471         GEN cl = (operand?gcopy:shallowcopy)(gel(st,sp-1));
1472         GEN f = gel(cl, 7);
1473         long j, l = lg(f);
1474         GEN v = cgetg(l, t_VEC);
1475         for (j = 1; j < l; j++)
1476           if (signe(gel(f,l-j))==0)
1477           {
1478             GEN val = var[s_var.n-j].value;
1479             gel(v,j) = operand?gcopy(val):val;
1480           } else
1481             gel(v,j) = gnil;
1482         gel(cl,7) = v;
1483         gel(st,sp-1) = cl;
1484       }
1485       break;
1486     case OCpackargs:
1487     {
1488       GEN def = cgetg(operand+1, t_VECSMALL);
1489       GEN args = cgetg(operand+1, t_VEC);
1490       pari_stack_alloc(&s_var,operand);
1491       sp-=operand;
1492       for (j=0;j<operand;j++)
1493       {
1494         if (gel(st,sp+j))
1495         {
1496           gel(args,j+1) = gel(st,sp+j);
1497           uel(def ,j+1) = 1;
1498         }
1499         else
1500         {
1501           gel(args,j+1) = gen_0;
1502           uel(def ,j+1) = 0;
1503         }
1504       }
1505       gel(st, sp++) = args;
1506       gel(st, sp++) = def;
1507       break;
1508     }
1509     case OCgetargs:
1510       pari_stack_alloc(&s_var,operand);
1511       s_var.n+=operand;
1512       nbmvar+=operand;
1513       sp-=operand;
1514       for (j=0;j<operand;j++)
1515       {
1516         if (gel(st,sp+j))
1517           pushlex(j-operand,gel(st,sp+j));
1518         else
1519         {
1520           var[s_var.n+j-operand].flag=DEFAULT_VAL;
1521           var[s_var.n+j-operand].value=gen_0;
1522         }
1523       }
1524       break;
1525     case OCcheckuserargs:
1526       for (j=0; j<operand; j++)
1527         if (var[s_var.n-operand+j].flag==DEFAULT_VAL)
1528           pari_err(e_MISC,"missing mandatory argument"
1529                    " '%s' in user function",get_arg_name(C,j+1));
1530       break;
1531     case OCcheckargs:
1532       for (j=sp-1;operand;operand>>=1UL,j--)
1533         if ((operand&1L) && gel(st,j)==NULL)
1534           pari_err(e_MISC,"missing mandatory argument");
1535       break;
1536     case OCcheckargs0:
1537       for (j=sp-1;operand;operand>>=1UL,j--)
1538         if ((operand&1L) && gel(st,j))
1539           pari_err(e_MISC,"argument type not implemented");
1540       break;
1541     case OCdefaultlong:
1542       sp--;
1543       if (st[sp+operand])
1544         st[sp+operand]=gtos(gel(st,sp+operand));
1545       else
1546         st[sp+operand]=st[sp];
1547       break;
1548     case OCdefaultulong:
1549       sp--;
1550       if (st[sp+operand])
1551         st[sp+operand]=gtou(gel(st,sp+operand));
1552       else
1553         st[sp+operand]=st[sp];
1554       break;
1555     case OCdefaultgen:
1556       sp--;
1557       if (!st[sp+operand])
1558         st[sp+operand]=st[sp];
1559       break;
1560     case OCvec:
1561       gel(st,sp++)=cgetg(operand,t_VEC);
1562       st[sp++]=avma;
1563       break;
1564     case OCcol:
1565       gel(st,sp++)=cgetg(operand,t_COL);
1566       st[sp++]=avma;
1567       break;
1568     case OCmat:
1569       {
1570         GEN z;
1571         long l=st[sp-1];
1572         z=cgetg(operand,t_MAT);
1573         for(j=1;j<operand;j++)
1574           gel(z,j) = cgetg(l,t_COL);
1575         gel(st,sp-1) = z;
1576         st[sp++]=avma;
1577       }
1578       break;
1579     case OCpop:
1580       sp-=operand;
1581       break;
1582     case OCdup:
1583       {
1584         long i, s=st[sp-1];
1585         st_alloc(operand);
1586         for(i=1;i<=operand;i++)
1587           st[sp++]=s;
1588       }
1589       break;
1590     }
1591   }
1592   if (0)
1593   {
1594 endeval:
1595     sp = saved_sp;
1596     for(  ; rp>saved_rp ;  )
1597     {
1598       gp_pointer *g = &ptrs[--rp];
1599       clone_unlock_deep(g->ox);
1600     }
1601   }
1602   s_prec.n = saved_prec;
1603   s_trace.n--;
1604   restore_vars(nbmvar, nblvar, nblock);
1605   clone_unlock(C);
1606 }
1607 
1608 GEN
closure_evalgen(GEN C)1609 closure_evalgen(GEN C)
1610 {
1611   pari_sp ltop=avma;
1612   closure_eval(C);
1613   if (br_status) return gc_NULL(ltop);
1614   return gerepileupto(ltop,gel(st,--sp));
1615 }
1616 
1617 long
evalstate_get_trace(void)1618 evalstate_get_trace(void)
1619 { return s_trace.n; }
1620 
1621 void
evalstate_set_trace(long lvl)1622 evalstate_set_trace(long lvl)
1623 { s_trace.n = lvl; }
1624 
1625 void
evalstate_save(struct pari_evalstate * state)1626 evalstate_save(struct pari_evalstate *state)
1627 {
1628   state->avma = avma;
1629   state->sp   = sp;
1630   state->rp   = rp;
1631   state->prec = s_prec.n;
1632   state->var  = s_var.n;
1633   state->lvars= s_lvars.n;
1634   state->locks= s_locks.n;
1635   state->trace= s_trace.n;
1636   compilestate_save(&state->comp);
1637   mtstate_save(&state->mt);
1638 }
1639 
1640 void
evalstate_restore(struct pari_evalstate * state)1641 evalstate_restore(struct pari_evalstate *state)
1642 {
1643   set_avma(state->avma);
1644   mtstate_restore(&state->mt);
1645   sp = state->sp;
1646   rp = state->rp;
1647   s_prec.n = state->prec;
1648   restore_vars(s_var.n-state->var, s_lvars.n-state->lvars,
1649                s_locks.n-state->locks);
1650   restore_trace(s_trace.n-state->trace);
1651   reset_break();
1652   compilestate_restore(&state->comp);
1653 }
1654 
1655 GEN
evalstate_restore_err(struct pari_evalstate * state)1656 evalstate_restore_err(struct pari_evalstate *state)
1657 {
1658   GENbin* err = copy_bin(pari_err_last());
1659   evalstate_restore(state);
1660   return bin_copy(err);
1661 }
1662 
1663 void
evalstate_reset(void)1664 evalstate_reset(void)
1665 {
1666   mtstate_reset();
1667   sp = 0;
1668   rp = 0;
1669   dbg_level = 0;
1670   restore_vars(s_var.n, s_lvars.n, s_locks.n);
1671   s_trace.n = 0;
1672   reset_break();
1673   compilestate_reset();
1674   parsestate_reset();
1675   set_avma(pari_mainstack->top);
1676 }
1677 
1678 void
evalstate_clone(void)1679 evalstate_clone(void)
1680 {
1681   long i;
1682   for (i = 1; i<=s_var.n; i++) copylex(-i);
1683   lvar_make_safe();
1684   for (i = 0; i< s_trace.n; i++)
1685   {
1686     GEN C = trace[i].closure;
1687     if (isonstack(C)) trace[i].closure = gclone(C);
1688   }
1689 }
1690 
1691 GEN
closure_trapgen(GEN C,long numerr)1692 closure_trapgen(GEN C, long numerr)
1693 {
1694   VOLATILE GEN x;
1695   struct pari_evalstate state;
1696   evalstate_save(&state);
1697   pari_CATCH(numerr) { x = (GEN)1L; }
1698   pari_TRY { x = closure_evalgen(C); } pari_ENDCATCH;
1699   if (x == (GEN)1L) evalstate_restore(&state);
1700   return x;
1701 }
1702 
1703 GEN
closure_evalnobrk(GEN C)1704 closure_evalnobrk(GEN C)
1705 {
1706   pari_sp ltop=avma;
1707   closure_eval(C);
1708   if (br_status) pari_err(e_MISC, "break not allowed here");
1709   return gerepileupto(ltop,gel(st,--sp));
1710 }
1711 
1712 void
closure_evalvoid(GEN C)1713 closure_evalvoid(GEN C)
1714 {
1715   pari_sp ltop=avma;
1716   closure_eval(C);
1717   set_avma(ltop);
1718 }
1719 
1720 GEN
closure_evalres(GEN C)1721 closure_evalres(GEN C)
1722 {
1723   return closure_return(C);
1724 }
1725 
1726 INLINE GEN
closure_returnupto(GEN C)1727 closure_returnupto(GEN C)
1728 {
1729   pari_sp av=avma;
1730   return copyupto(closure_return(C),(GEN)av);
1731 }
1732 
1733 GEN
pareval_worker(GEN C)1734 pareval_worker(GEN C)
1735 {
1736   return closure_callgenall(C, 0);
1737 }
1738 
1739 GEN
pareval(GEN C)1740 pareval(GEN C)
1741 {
1742   pari_sp av = avma;
1743   long l = lg(C), i;
1744   GEN worker;
1745   if (!is_vec_t(typ(C))) pari_err_TYPE("pareval",C);
1746   for (i=1; i<l; i++)
1747     if (typ(gel(C,i))!=t_CLOSURE)
1748       pari_err_TYPE("pareval",gel(C,i));
1749   worker = snm_closure(is_entry("_pareval_worker"), NULL);
1750   return gerepileupto(av, gen_parapply(worker, C));
1751 }
1752 
1753 GEN
parvector_worker(GEN i,GEN C)1754 parvector_worker(GEN i, GEN C)
1755 {
1756   return closure_callgen1(C, i);
1757 }
1758 
1759 GEN
parfor_worker(GEN i,GEN C)1760 parfor_worker(GEN i, GEN C)
1761 {
1762   retmkvec2(gcopy(i), closure_callgen1(C, i));
1763 }
1764 
1765 GEN
parvector(long n,GEN code)1766 parvector(long n, GEN code)
1767 {
1768   long i, pending = 0, workid;
1769   GEN worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
1770   GEN a, V, done;
1771   struct pari_mt pt;
1772   mt_queue_start_lim(&pt, worker, n);
1773   a = mkvec(cgetipos(3)); /* left on the stack */
1774   V = cgetg(n+1, t_VEC);
1775   for (i=1; i<=n || pending; i++)
1776   {
1777     mael(a,1,2) = i;
1778     mt_queue_submit(&pt, i, i<=n? a: NULL);
1779     done = mt_queue_get(&pt, &workid, &pending);
1780     if (done) gel(V,workid) = done;
1781   }
1782   mt_queue_end(&pt);
1783   return V;
1784 }
1785 
1786 /* B <- {a + k * m : k = 0, ..., (b-a)/m)} */
1787 static void
arithprogset(GEN B,GEN a,GEN b,long m)1788 arithprogset(GEN B, GEN a, GEN b, long m)
1789 {
1790   long k;
1791   for (k = 1; cmpii(a, b) <= 0; a = addui(m,a), k++) gel(B, k) = a;
1792   setlg(B, k);
1793 }
1794 static GEN
vecsum_i(GEN v)1795 vecsum_i(GEN v)
1796 {
1797   long i, l = lg(v);
1798   GEN s;
1799   if (l == 1) return gen_0;
1800   s = gel(v,1); for (i = 2; i < l; i++) s = gadd(s, gel(v,i));
1801   return s;
1802 }
1803 GEN
parsum(GEN a,GEN b,GEN code)1804 parsum(GEN a, GEN b, GEN code)
1805 {
1806   pari_sp av = avma;
1807   GEN worker, L, v, s, N;
1808   long r, m, pending;
1809   struct pari_mt pt;
1810   pari_sp av2;
1811 
1812   if (typ(a) != t_INT) pari_err_TYPE("parsum",a);
1813   if (gcmp(b,a) < 0) return gen_0;
1814   worker = snm_closure(is_entry("_parapply_slice_worker"), mkvec(code));
1815   b = gfloor(b);
1816   N = addiu(subii(b, a), 1);
1817   m = itou(sqrti(N)); if (cmpiu(N, m) < 0) m = itou(N);
1818   mt_queue_start_lim(&pt, worker, m);
1819   L = cgetg(m + 2, t_VEC); v = mkvec(L);
1820   s = gen_0; a = setloop(a); pending = 0; av2 = avma;
1821   for (r = 1; r <= m || pending; r++)
1822   {
1823     long workid;
1824     GEN done;
1825     if (r <= m) { arithprogset(L, icopy(a), b, m); a = incloop(a); }
1826     mt_queue_submit(&pt, 0, r <= m? v: NULL);
1827     done = mt_queue_get(&pt, &workid, &pending);
1828     if (done) s = gerepileupto(av2, gadd(s, vecsum_i(done)));
1829   }
1830   mt_queue_end(&pt); return gerepileupto(av, s);
1831 }
1832 
1833 void
parfor(GEN a,GEN b,GEN code,void * E,long call (void *,GEN,GEN))1834 parfor(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN))
1835 {
1836   pari_sp av = avma, av2;
1837   long running, pending = 0, lim;
1838   long status = br_NONE;
1839   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
1840   GEN done, stop = NULL;
1841   struct pari_mt pt;
1842   if (typ(a) != t_INT) pari_err_TYPE("parfor",a);
1843   if (b)
1844   {
1845     if (gcmp(b,a) < 0) return;
1846     if (typ(b) == t_INFINITY)
1847     {
1848       if (inf_get_sign(b) < 0) return;
1849       b = NULL;
1850     }
1851     else
1852       b = gfloor(b);
1853   }
1854   lim = b ? itos_or_0(subii(addis(b,1),a)): 0;
1855   mt_queue_start_lim(&pt, worker, lim);
1856   a = mkvec(setloop(a));
1857   av2 = avma;
1858   while ((running = (!stop && (!b || cmpii(gel(a,1),b) <= 0))) || pending)
1859   {
1860     mt_queue_submit(&pt, 0, running ? a: NULL);
1861     done = mt_queue_get(&pt, NULL, &pending);
1862     if (call && done && (!stop || cmpii(gel(done,1),stop) < 0))
1863       if (call(E, gel(done,1), gel(done,2)))
1864       {
1865         status = br_status;
1866         br_status = br_NONE;
1867         stop = gerepileuptoint(av2, gel(done,1));
1868       }
1869     gel(a,1) = incloop(gel(a,1));
1870     if (!stop) set_avma(av2);
1871   }
1872   set_avma(av2);
1873   mt_queue_end(&pt);
1874   br_status = status;
1875   set_avma(av);
1876 }
1877 
1878 static void
parforiter_init(struct parfor_iter * T,GEN code)1879 parforiter_init(struct parfor_iter *T, GEN code)
1880 {
1881   T->pending = 0;
1882   T->worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
1883   mt_queue_start(&T->pt, T->worker);
1884 }
1885 
1886 static GEN
parforiter_next(struct parfor_iter * T,GEN v)1887 parforiter_next(struct parfor_iter *T, GEN v)
1888 {
1889   mt_queue_submit(&T->pt, 0, v);
1890   return mt_queue_get(&T->pt, NULL, &T->pending);
1891 }
1892 
1893 static void
parforiter_stop(struct parfor_iter * T)1894 parforiter_stop(struct parfor_iter *T)
1895 {
1896   while (T->pending)
1897   {
1898     mt_queue_submit(&T->pt, 0, NULL);
1899     (void) mt_queue_get(&T->pt, NULL, &T->pending);
1900   }
1901   mt_queue_end(&T->pt);
1902 }
1903 
1904 void
parfor_init(parfor_t * T,GEN a,GEN b,GEN code)1905 parfor_init(parfor_t *T, GEN a, GEN b, GEN code)
1906 {
1907   if (typ(a) != t_INT) pari_err_TYPE("parfor",a);
1908   T->b = b ? gfloor(b): NULL;
1909   T->a = mkvec(setloop(a));
1910   parforiter_init(&T->iter, code);
1911 }
1912 
1913 GEN
parfor_next(parfor_t * T)1914 parfor_next(parfor_t *T)
1915 {
1916   long running;
1917   while ((running=((!T->b || cmpii(gel(T->a,1),T->b) <= 0))) || T->iter.pending)
1918   {
1919     GEN done = parforiter_next(&T->iter, running ? T->a: NULL);
1920     gel(T->a,1) = incloop(gel(T->a,1));
1921     if (done) return done;
1922   }
1923   mt_queue_end(&T->iter.pt);
1924   return NULL;
1925 }
1926 
1927 void
parfor_stop(parfor_t * T)1928 parfor_stop(parfor_t *T) { parforiter_stop(&T->iter); }
1929 
1930 static long
gp_evalvoid2(void * E,GEN x,GEN y)1931 gp_evalvoid2(void *E, GEN x, GEN y)
1932 {
1933   GEN code =(GEN) E;
1934   push_lex(x, code);
1935   push_lex(y, NULL);
1936   closure_evalvoid(code);
1937   pop_lex(2);
1938   return loop_break();
1939 }
1940 
1941 void
parfor0(GEN a,GEN b,GEN code,GEN code2)1942 parfor0(GEN a, GEN b, GEN code, GEN code2)
1943 {
1944   parfor(a, b, code, (void*)code2, code2 ? gp_evalvoid2: NULL);
1945 }
1946 
1947 void
parforprimestep_init(parforprime_t * T,GEN a,GEN b,GEN q,GEN code)1948 parforprimestep_init(parforprime_t *T, GEN a, GEN b, GEN q, GEN code)
1949 {
1950   forprimestep_init(&T->forprime, a, b, q);
1951   T->v = mkvec(gen_0);
1952   parforiter_init(&T->iter, code);
1953 }
1954 
1955 void
parforprime_init(parforprime_t * T,GEN a,GEN b,GEN code)1956 parforprime_init(parforprime_t *T, GEN a, GEN b, GEN code)
1957 { parforprimestep_init(T, a, b, NULL, code); }
1958 
1959 GEN
parforprime_next(parforprime_t * T)1960 parforprime_next(parforprime_t *T)
1961 {
1962   long running;
1963   while ((running = !!forprime_next(&T->forprime)) || T->iter.pending)
1964   {
1965     GEN done;
1966     gel(T->v, 1) = T->forprime.pp;
1967     done = parforiter_next(&T->iter, running ? T->v: NULL);
1968     if (done) return done;
1969   }
1970   mt_queue_end(&T->iter.pt);
1971   return NULL;
1972 }
1973 
1974 void
parforprime_stop(parforprime_t * T)1975 parforprime_stop(parforprime_t *T) { parforiter_stop(&T->iter); }
1976 
1977 void
parforprimestep(GEN a,GEN b,GEN q,GEN code,void * E,long call (void *,GEN,GEN))1978 parforprimestep(GEN a, GEN b, GEN q, GEN code, void *E, long call(void*, GEN, GEN))
1979 {
1980   pari_sp av = avma, av2;
1981   long running, pending = 0;
1982   long status = br_NONE;
1983   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
1984   GEN v, done, stop = NULL;
1985   struct pari_mt pt;
1986   forprime_t T;
1987 
1988   if (!forprimestep_init(&T, a,b,q)) { set_avma(av); return; }
1989   mt_queue_start(&pt, worker);
1990   v = mkvec(gen_0);
1991   av2 = avma;
1992   while ((running = (!stop && forprime_next(&T))) || pending)
1993   {
1994     gel(v, 1) = T.pp;
1995     mt_queue_submit(&pt, 0, running ? v: NULL);
1996     done = mt_queue_get(&pt, NULL, &pending);
1997     if (call && done && (!stop || cmpii(gel(done,1),stop) < 0))
1998       if (call(E, gel(done,1), gel(done,2)))
1999       {
2000         status = br_status;
2001         br_status = br_NONE;
2002         stop = gerepileuptoint(av2, gel(done,1));
2003       }
2004     if (!stop) set_avma(av2);
2005   }
2006   set_avma(av2);
2007   mt_queue_end(&pt);
2008   br_status = status;
2009   set_avma(av);
2010 }
2011 
2012 void
parforprime(GEN a,GEN b,GEN code,void * E,long call (void *,GEN,GEN))2013 parforprime(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN))
2014 {
2015   parforprimestep(a, b, NULL, code, E, call);
2016 }
2017 
2018 void
parforprime0(GEN a,GEN b,GEN code,GEN code2)2019 parforprime0(GEN a, GEN b, GEN code, GEN code2)
2020 {
2021   parforprime(a, b, code, (void*)code2, code2? gp_evalvoid2: NULL);
2022 }
2023 
2024 void
parforprimestep0(GEN a,GEN b,GEN q,GEN code,GEN code2)2025 parforprimestep0(GEN a, GEN b, GEN q, GEN code, GEN code2)
2026 {
2027   parforprimestep(a, b, q, code, (void*)code2, code2? gp_evalvoid2: NULL);
2028 }
2029 
2030 void
parforvec_init(parforvec_t * T,GEN x,GEN code,long flag)2031 parforvec_init(parforvec_t *T, GEN x, GEN code, long flag)
2032 {
2033   forvec_init(&T->forvec, x, flag);
2034   T->v = mkvec(gen_0);
2035   parforiter_init(&T->iter, code);
2036 }
2037 
2038 GEN
parforvec_next(parforvec_t * T)2039 parforvec_next(parforvec_t *T)
2040 {
2041   GEN v = gen_0;
2042   while ((v = forvec_next(&T->forvec)) || T->iter.pending)
2043   {
2044     GEN done;
2045     if (v) gel(T->v, 1) = v;
2046     done = parforiter_next(&T->iter, v ? T->v: NULL);
2047     if (done) return done;
2048   }
2049   mt_queue_end(&T->iter.pt);
2050   return NULL;
2051 }
2052 
2053 void
parforvec_stop(parforvec_t * T)2054 parforvec_stop(parforvec_t *T) { parforiter_stop(&T->iter); }
2055 
2056 void
parforvec(GEN x,GEN code,long flag,void * E,long call (void *,GEN,GEN))2057 parforvec(GEN x, GEN code, long flag, void *E, long call(void*, GEN, GEN))
2058 {
2059   pari_sp av = avma, av2;
2060   long running, pending = 0;
2061   long status = br_NONE;
2062   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
2063   GEN done, stop = NULL;
2064   struct pari_mt pt;
2065   forvec_t T;
2066   GEN a, v = gen_0;
2067 
2068   if (!forvec_init(&T, x, flag)) { set_avma(av); return; }
2069   mt_queue_start(&pt, worker);
2070   a = mkvec(gen_0);
2071   av2 = avma;
2072   while ((running = (!stop && v && (v = forvec_next(&T)))) || pending)
2073   {
2074     gel(a, 1) = v;
2075     mt_queue_submit(&pt, 0, running ? a: NULL);
2076     done = mt_queue_get(&pt, NULL, &pending);
2077     if (call && done && (!stop || lexcmp(gel(done,1),stop) < 0))
2078       if (call(E, gel(done,1), gel(done,2)))
2079       {
2080         status = br_status;
2081         br_status = br_NONE;
2082         stop = gerepilecopy(av2, gel(done,1));
2083       }
2084     if (!stop) set_avma(av2);
2085   }
2086   set_avma(av2);
2087   mt_queue_end(&pt);
2088   br_status = status;
2089   set_avma(av);
2090 }
2091 
2092 void
parforvec0(GEN x,GEN code,GEN code2,long flag)2093 parforvec0(GEN x, GEN code, GEN code2, long flag)
2094 {
2095   parforvec(x, code, flag, (void*)code2, code2? gp_evalvoid2: NULL);
2096 }
2097 
2098 void
parforeach_init(parforeach_t * T,GEN x,GEN code)2099 parforeach_init(parforeach_t *T, GEN x, GEN code)
2100 {
2101   switch(typ(x))
2102   {
2103     case t_LIST:
2104       x = list_data(x); /* FALL THROUGH */
2105       if (!x) return;
2106     case t_MAT: case t_VEC: case t_COL:
2107       break;
2108     default:
2109       pari_err_TYPE("foreach",x);
2110       return; /*LCOV_EXCL_LINE*/
2111   }
2112   T->x = x; T->i = 1; T->l = lg(x);
2113   T->W = mkvec(gen_0);
2114   T->iter.pending = 0;
2115   T->iter.worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
2116   mt_queue_start(&T->iter.pt, T->iter.worker);
2117 }
2118 
2119 GEN
parforeach_next(parforeach_t * T)2120 parforeach_next(parforeach_t *T)
2121 {
2122   while (T->i < T->l || T->iter.pending)
2123   {
2124     GEN done;
2125     long workid;
2126     if (T->i < T->l) gel(T->W,1) = gel(T->x, T->i);
2127     mt_queue_submit(&T->iter.pt, T->i, T->i < T->l ? T->W: NULL);
2128     T->i = minss(T->i+1, T->l);
2129     done = mt_queue_get(&T->iter.pt, &workid, &T->iter.pending);
2130     if (done) return mkvec2(gel(T->x,workid),done);
2131   }
2132   mt_queue_end(&T->iter.pt);
2133   return NULL;
2134 }
2135 
2136 void
parforeach_stop(parforeach_t * T)2137 parforeach_stop(parforeach_t *T) { parforiter_stop(&T->iter); }
2138 
2139 void
parforeach(GEN x,GEN code,void * E,long call (void *,GEN,GEN))2140 parforeach(GEN x, GEN code, void *E, long call(void*, GEN, GEN))
2141 {
2142   pari_sp av = avma, av2;
2143   long pending = 0, n, i, stop = 0;
2144   long status = br_NONE, workid;
2145   GEN worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
2146   GEN done, W;
2147   struct pari_mt pt;
2148   switch(typ(x))
2149   {
2150     case t_LIST:
2151       x = list_data(x); /* FALL THROUGH */
2152       if (!x) return;
2153     case t_MAT: case t_VEC: case t_COL:
2154       break;
2155     default:
2156       pari_err_TYPE("foreach",x);
2157       return; /*LCOV_EXCL_LINE*/
2158   }
2159   clone_lock(x); n = lg(x)-1;
2160   mt_queue_start_lim(&pt, worker, n);
2161   W = cgetg(2, t_VEC);
2162   av2 = avma;
2163   for (i=1; i<=n || pending; i++)
2164   {
2165     if (!stop && i <= n) gel(W,1) = gel(x,i);
2166     mt_queue_submit(&pt, i, !stop && i<=n? W: NULL);
2167     done = mt_queue_get(&pt, &workid, &pending);
2168     if (call && done && (!stop || workid < stop))
2169       if (call(E, gel(x, workid), done))
2170       {
2171         status = br_status;
2172         br_status = br_NONE;
2173         stop = workid;
2174       }
2175   }
2176   set_avma(av2);
2177   mt_queue_end(&pt);
2178   br_status = status;
2179   set_avma(av);
2180 }
2181 
2182 void
parforeach0(GEN x,GEN code,GEN code2)2183 parforeach0(GEN x, GEN code, GEN code2)
2184 {
2185   parforeach(x, code, (void*)code2, code2? gp_evalvoid2: NULL);
2186 }
2187 
2188 void
closure_callvoid1(GEN C,GEN x)2189 closure_callvoid1(GEN C, GEN x)
2190 {
2191   long i, ar = closure_arity(C);
2192   gel(st,sp++) = x;
2193   for(i=2; i <= ar; i++) gel(st,sp++) = NULL;
2194   closure_evalvoid(C);
2195 }
2196 
2197 GEN
closure_callgen0prec(GEN C,long prec)2198 closure_callgen0prec(GEN C, long prec)
2199 {
2200   GEN z;
2201   long i, ar = closure_arity(C);
2202   for(i=1; i<= ar; i++) gel(st,sp++) = NULL;
2203   push_localprec(prec);
2204   z = closure_returnupto(C);
2205   pop_localprec();
2206   return z;
2207 }
2208 
2209 GEN
closure_callgen1(GEN C,GEN x)2210 closure_callgen1(GEN C, GEN x)
2211 {
2212   long i, ar = closure_arity(C);
2213   gel(st,sp++) = x;
2214   for(i=2; i<= ar; i++) gel(st,sp++) = NULL;
2215   return closure_returnupto(C);
2216 }
2217 
2218 GEN
closure_callgen1prec(GEN C,GEN x,long prec)2219 closure_callgen1prec(GEN C, GEN x, long prec)
2220 {
2221   GEN z;
2222   long i, ar = closure_arity(C);
2223   gel(st,sp++) = x;
2224   for(i=2; i<= ar; i++) gel(st,sp++) = NULL;
2225   push_localprec(prec);
2226   z = closure_returnupto(C);
2227   pop_localprec();
2228   return z;
2229 }
2230 
2231 GEN
closure_callgen2(GEN C,GEN x,GEN y)2232 closure_callgen2(GEN C, GEN x, GEN y)
2233 {
2234   long i, ar = closure_arity(C);
2235   st_alloc(ar);
2236   gel(st,sp++) = x;
2237   gel(st,sp++) = y;
2238   for(i=3; i<=ar; i++) gel(st,sp++) = NULL;
2239   return closure_returnupto(C);
2240 }
2241 
2242 GEN
closure_callgenvec(GEN C,GEN args)2243 closure_callgenvec(GEN C, GEN args)
2244 {
2245   long i, l = lg(args)-1, ar = closure_arity(C);
2246   st_alloc(ar);
2247   if (l > ar)
2248     pari_err(e_MISC,"too many parameters in user-defined function call");
2249   if (closure_is_variadic(C) && l==ar && typ(gel(args,l))!=t_VEC)
2250     pari_err_TYPE("call", gel(args,l));
2251   for (i = 1; i <= l;  i++) gel(st,sp++) = gel(args,i);
2252   for(      ; i <= ar; i++) gel(st,sp++) = NULL;
2253   return closure_returnupto(C);
2254 }
2255 
2256 GEN
closure_callgenvecprec(GEN C,GEN args,long prec)2257 closure_callgenvecprec(GEN C, GEN args, long prec)
2258 {
2259   GEN z;
2260   push_localprec(prec);
2261   z = closure_callgenvec(C, args);
2262   pop_localprec();
2263   return z;
2264 }
2265 
2266 GEN
closure_callgenvecdef(GEN C,GEN args,GEN def)2267 closure_callgenvecdef(GEN C, GEN args, GEN def)
2268 {
2269   long i, l = lg(args)-1, ar = closure_arity(C);
2270   st_alloc(ar);
2271   if (l > ar)
2272     pari_err(e_MISC,"too many parameters in user-defined function call");
2273   if (closure_is_variadic(C) && l==ar && typ(gel(args,l))!=t_VEC)
2274     pari_err_TYPE("call", gel(args,l));
2275   for (i = 1; i <= l;  i++) gel(st,sp++) = def[i] ? gel(args,i): NULL;
2276   for(      ; i <= ar; i++) gel(st,sp++) = NULL;
2277   return closure_returnupto(C);
2278 }
2279 
2280 GEN
closure_callgenvecdefprec(GEN C,GEN args,GEN def,long prec)2281 closure_callgenvecdefprec(GEN C, GEN args, GEN def, long prec)
2282 {
2283   GEN z;
2284   push_localprec(prec);
2285   z = closure_callgenvecdef(C, args, def);
2286   pop_localprec();
2287   return z;
2288 }
2289 GEN
closure_callgenall(GEN C,long n,...)2290 closure_callgenall(GEN C, long n, ...)
2291 {
2292   va_list ap;
2293   long i, ar = closure_arity(C);
2294   va_start(ap,n);
2295   if (n > ar)
2296     pari_err(e_MISC,"too many parameters in user-defined function call");
2297   st_alloc(ar);
2298   for (i = 1; i <=n;  i++) gel(st,sp++) = va_arg(ap, GEN);
2299   for(      ; i <=ar; i++) gel(st,sp++) = NULL;
2300   va_end(ap);
2301   return closure_returnupto(C);
2302 }
2303 
2304 GEN
gp_eval(void * E,GEN x)2305 gp_eval(void *E, GEN x)
2306 {
2307   GEN code = (GEN)E;
2308   set_lex(-1,x);
2309   return closure_evalnobrk(code);
2310 }
2311 
2312 GEN
gp_evalupto(void * E,GEN x)2313 gp_evalupto(void *E, GEN x)
2314 {
2315   pari_sp av = avma;
2316   return copyupto(gp_eval(E,x), (GEN)av);
2317 }
2318 
2319 GEN
gp_evalprec(void * E,GEN x,long prec)2320 gp_evalprec(void *E, GEN x, long prec)
2321 {
2322   GEN z;
2323   push_localprec(prec);
2324   z = gp_eval(E, x);
2325   pop_localprec();
2326   return z;
2327 }
2328 
2329 long
gp_evalbool(void * E,GEN x)2330 gp_evalbool(void *E, GEN x)
2331 { pari_sp av = avma; return gc_long(av, !gequal0(gp_eval(E,x))); }
2332 
2333 long
gp_evalvoid(void * E,GEN x)2334 gp_evalvoid(void *E, GEN x)
2335 {
2336   GEN code = (GEN)E;
2337   set_lex(-1,x);
2338   closure_evalvoid(code);
2339   return loop_break();
2340 }
2341 
2342 GEN
gp_call(void * E,GEN x)2343 gp_call(void *E, GEN x)
2344 {
2345   GEN code = (GEN)E;
2346   return closure_callgen1(code, x);
2347 }
2348 
2349 GEN
gp_callprec(void * E,GEN x,long prec)2350 gp_callprec(void *E, GEN x, long prec)
2351 {
2352   GEN code = (GEN)E;
2353   return closure_callgen1prec(code, x, prec);
2354 }
2355 
2356 GEN
gp_call2(void * E,GEN x,GEN y)2357 gp_call2(void *E, GEN x, GEN y)
2358 {
2359   GEN code = (GEN)E;
2360   return closure_callgen2(code, x, y);
2361 }
2362 
2363 long
gp_callbool(void * E,GEN x)2364 gp_callbool(void *E, GEN x)
2365 {
2366   pari_sp av = avma;
2367   GEN code = (GEN)E;
2368   return gc_long(av, !gequal0(closure_callgen1(code, x)));
2369 }
2370 
2371 long
gp_callvoid(void * E,GEN x)2372 gp_callvoid(void *E, GEN x)
2373 {
2374   GEN code = (GEN)E;
2375   closure_callvoid1(code, x);
2376   return loop_break();
2377 }
2378 
2379 INLINE const char *
disassemble_cast(long mode)2380 disassemble_cast(long mode)
2381 {
2382   switch (mode)
2383   {
2384   case Gsmall:
2385     return "small";
2386   case Ggen:
2387     return "gen";
2388   case Gvar:
2389     return "var";
2390   case Gvoid:
2391     return "void";
2392   default:
2393     return "unknown";
2394   }
2395 }
2396 
2397 void
closure_disassemble(GEN C)2398 closure_disassemble(GEN C)
2399 {
2400   const char * code;
2401   GEN oper;
2402   long i;
2403   if (typ(C)!=t_CLOSURE) pari_err_TYPE("disassemble",C);
2404   code=closure_codestr(C);
2405   oper=closure_get_oper(C);
2406   for(i=1;i<lg(oper);i++)
2407   {
2408     op_code opcode=(op_code) code[i];
2409     long operand=oper[i];
2410     pari_printf("%05ld\t",i);
2411     switch(opcode)
2412     {
2413     case OCpushlong:
2414       pari_printf("pushlong\t%ld\n",operand);
2415       break;
2416     case OCpushgnil:
2417       pari_printf("pushgnil\n");
2418       break;
2419     case OCpushgen:
2420       pari_printf("pushgen\t\t%ld\n",operand);
2421       break;
2422     case OCpushreal:
2423       pari_printf("pushreal\t%ld\n",operand);
2424       break;
2425     case OCpushstoi:
2426       pari_printf("pushstoi\t%ld\n",operand);
2427       break;
2428     case OCpushvar:
2429       {
2430         entree *ep = (entree *)operand;
2431         pari_printf("pushvar\t%s\n",ep->name);
2432         break;
2433       }
2434     case OCpushdyn:
2435       {
2436         entree *ep = (entree *)operand;
2437         pari_printf("pushdyn\t\t%s\n",ep->name);
2438         break;
2439       }
2440     case OCpushlex:
2441       pari_printf("pushlex\t\t%ld\n",operand);
2442       break;
2443     case OCstoredyn:
2444       {
2445         entree *ep = (entree *)operand;
2446         pari_printf("storedyn\t%s\n",ep->name);
2447         break;
2448       }
2449     case OCstorelex:
2450       pari_printf("storelex\t%ld\n",operand);
2451       break;
2452     case OCstoreptr:
2453       pari_printf("storeptr\n");
2454       break;
2455     case OCsimpleptrdyn:
2456       {
2457         entree *ep = (entree *)operand;
2458         pari_printf("simpleptrdyn\t%s\n",ep->name);
2459         break;
2460       }
2461     case OCsimpleptrlex:
2462       pari_printf("simpleptrlex\t%ld\n",operand);
2463       break;
2464     case OCnewptrdyn:
2465       {
2466         entree *ep = (entree *)operand;
2467         pari_printf("newptrdyn\t%s\n",ep->name);
2468         break;
2469       }
2470     case OCnewptrlex:
2471       pari_printf("newptrlex\t%ld\n",operand);
2472       break;
2473     case OCpushptr:
2474       pari_printf("pushptr\n");
2475       break;
2476     case OCstackgen:
2477       pari_printf("stackgen\t%ld\n",operand);
2478       break;
2479     case OCendptr:
2480       pari_printf("endptr\t\t%ld\n",operand);
2481       break;
2482     case OCprecreal:
2483       pari_printf("precreal\n");
2484       break;
2485     case OCbitprecreal:
2486       pari_printf("bitprecreal\n");
2487       break;
2488     case OCprecdl:
2489       pari_printf("precdl\n");
2490       break;
2491     case OCstoi:
2492       pari_printf("stoi\n");
2493       break;
2494     case OCutoi:
2495       pari_printf("utoi\n");
2496       break;
2497     case OCitos:
2498       pari_printf("itos\t\t%ld\n",operand);
2499       break;
2500     case OCitou:
2501       pari_printf("itou\t\t%ld\n",operand);
2502       break;
2503     case OCtostr:
2504       pari_printf("tostr\t\t%ld\n",operand);
2505       break;
2506     case OCvarn:
2507       pari_printf("varn\t\t%ld\n",operand);
2508       break;
2509     case OCcopy:
2510       pari_printf("copy\n");
2511       break;
2512     case OCcopyifclone:
2513       pari_printf("copyifclone\n");
2514       break;
2515     case OCcompo1:
2516       pari_printf("compo1\t\t%s\n",disassemble_cast(operand));
2517       break;
2518     case OCcompo1ptr:
2519       pari_printf("compo1ptr\n");
2520       break;
2521     case OCcompo2:
2522       pari_printf("compo2\t\t%s\n",disassemble_cast(operand));
2523       break;
2524     case OCcompo2ptr:
2525       pari_printf("compo2ptr\n");
2526       break;
2527     case OCcompoC:
2528       pari_printf("compoC\n");
2529       break;
2530     case OCcompoCptr:
2531       pari_printf("compoCptr\n");
2532       break;
2533     case OCcompoL:
2534       pari_printf("compoL\n");
2535       break;
2536     case OCcompoLptr:
2537       pari_printf("compoLptr\n");
2538       break;
2539     case OCcheckargs:
2540       pari_printf("checkargs\t0x%lx\n",operand);
2541       break;
2542     case OCcheckargs0:
2543       pari_printf("checkargs0\t0x%lx\n",operand);
2544       break;
2545     case OCcheckuserargs:
2546       pari_printf("checkuserargs\t%ld\n",operand);
2547       break;
2548     case OCdefaultlong:
2549       pari_printf("defaultlong\t%ld\n",operand);
2550       break;
2551     case OCdefaultulong:
2552       pari_printf("defaultulong\t%ld\n",operand);
2553       break;
2554     case OCdefaultgen:
2555       pari_printf("defaultgen\t%ld\n",operand);
2556       break;
2557     case OCpackargs:
2558       pari_printf("packargs\t%ld\n",operand);
2559       break;
2560     case OCgetargs:
2561       pari_printf("getargs\t\t%ld\n",operand);
2562       break;
2563     case OCdefaultarg:
2564       pari_printf("defaultarg\t%ld\n",operand);
2565       break;
2566     case OClocalvar:
2567       {
2568         entree *ep = (entree *)operand;
2569         pari_printf("localvar\t%s\n",ep->name);
2570         break;
2571       }
2572     case OClocalvar0:
2573       {
2574         entree *ep = (entree *)operand;
2575         pari_printf("localvar0\t%s\n",ep->name);
2576         break;
2577       }
2578     case OCexportvar:
2579       {
2580         entree *ep = (entree *)operand;
2581         pari_printf("exportvar\t%s\n",ep->name);
2582         break;
2583       }
2584     case OCunexportvar:
2585       {
2586         entree *ep = (entree *)operand;
2587         pari_printf("unexportvar\t%s\n",ep->name);
2588         break;
2589       }
2590     case OCcallgen:
2591       {
2592         entree *ep = (entree *)operand;
2593         pari_printf("callgen\t\t%s\n",ep->name);
2594         break;
2595       }
2596     case OCcallgen2:
2597       {
2598         entree *ep = (entree *)operand;
2599         pari_printf("callgen2\t%s\n",ep->name);
2600         break;
2601       }
2602     case OCcalllong:
2603       {
2604         entree *ep = (entree *)operand;
2605         pari_printf("calllong\t%s\n",ep->name);
2606         break;
2607       }
2608     case OCcallint:
2609       {
2610         entree *ep = (entree *)operand;
2611         pari_printf("callint\t\t%s\n",ep->name);
2612         break;
2613       }
2614     case OCcallvoid:
2615       {
2616         entree *ep = (entree *)operand;
2617         pari_printf("callvoid\t%s\n",ep->name);
2618         break;
2619       }
2620     case OCcalluser:
2621       pari_printf("calluser\t%ld\n",operand);
2622       break;
2623     case OCvec:
2624       pari_printf("vec\t\t%ld\n",operand);
2625       break;
2626     case OCcol:
2627       pari_printf("col\t\t%ld\n",operand);
2628       break;
2629     case OCmat:
2630       pari_printf("mat\t\t%ld\n",operand);
2631       break;
2632     case OCnewframe:
2633       pari_printf("newframe\t%ld\n",operand);
2634       break;
2635     case OCsaveframe:
2636       pari_printf("saveframe\t%ld\n", operand);
2637       break;
2638     case OCpop:
2639       pari_printf("pop\t\t%ld\n",operand);
2640       break;
2641     case OCdup:
2642       pari_printf("dup\t\t%ld\n",operand);
2643       break;
2644     case OCavma:
2645       pari_printf("avma\n",operand);
2646       break;
2647     case OCgerepile:
2648       pari_printf("gerepile\n",operand);
2649       break;
2650     case OCcowvardyn:
2651       {
2652         entree *ep = (entree *)operand;
2653         pari_printf("cowvardyn\t%s\n",ep->name);
2654         break;
2655       }
2656     case OCcowvarlex:
2657       pari_printf("cowvarlex\t%ld\n",operand);
2658       break;
2659     case OCsetref:
2660       pari_printf("setref\t\t%ld\n",operand);
2661       break;
2662     case OClock:
2663       pari_printf("lock\t\t%ld\n",operand);
2664       break;
2665     }
2666   }
2667 }
2668 
2669 static int
opcode_need_relink(op_code opcode)2670 opcode_need_relink(op_code opcode)
2671 {
2672   switch(opcode)
2673   {
2674   case OCpushlong:
2675   case OCpushgen:
2676   case OCpushgnil:
2677   case OCpushreal:
2678   case OCpushstoi:
2679   case OCpushlex:
2680   case OCstorelex:
2681   case OCstoreptr:
2682   case OCsimpleptrlex:
2683   case OCnewptrlex:
2684   case OCpushptr:
2685   case OCstackgen:
2686   case OCendptr:
2687   case OCprecreal:
2688   case OCbitprecreal:
2689   case OCprecdl:
2690   case OCstoi:
2691   case OCutoi:
2692   case OCitos:
2693   case OCitou:
2694   case OCtostr:
2695   case OCvarn:
2696   case OCcopy:
2697   case OCcopyifclone:
2698   case OCcompo1:
2699   case OCcompo1ptr:
2700   case OCcompo2:
2701   case OCcompo2ptr:
2702   case OCcompoC:
2703   case OCcompoCptr:
2704   case OCcompoL:
2705   case OCcompoLptr:
2706   case OCcheckargs:
2707   case OCcheckargs0:
2708   case OCcheckuserargs:
2709   case OCpackargs:
2710   case OCgetargs:
2711   case OCdefaultarg:
2712   case OCdefaultgen:
2713   case OCdefaultlong:
2714   case OCdefaultulong:
2715   case OCcalluser:
2716   case OCvec:
2717   case OCcol:
2718   case OCmat:
2719   case OCnewframe:
2720   case OCsaveframe:
2721   case OCdup:
2722   case OCpop:
2723   case OCavma:
2724   case OCgerepile:
2725   case OCcowvarlex:
2726   case OCsetref:
2727   case OClock:
2728     break;
2729   case OCpushvar:
2730   case OCpushdyn:
2731   case OCstoredyn:
2732   case OCsimpleptrdyn:
2733   case OCnewptrdyn:
2734   case OClocalvar:
2735   case OClocalvar0:
2736   case OCexportvar:
2737   case OCunexportvar:
2738   case OCcallgen:
2739   case OCcallgen2:
2740   case OCcalllong:
2741   case OCcallint:
2742   case OCcallvoid:
2743   case OCcowvardyn:
2744     return 1;
2745   }
2746   return 0;
2747 }
2748 
2749 static void
closure_relink(GEN C,hashtable * table)2750 closure_relink(GEN C, hashtable *table)
2751 {
2752   const char *code = closure_codestr(C);
2753   GEN oper = closure_get_oper(C);
2754   GEN fram = gel(closure_get_dbg(C),3);
2755   long i, j;
2756   for(i=1;i<lg(oper);i++)
2757     if (oper[i] && opcode_need_relink((op_code)code[i]))
2758       oper[i] = (long) hash_search(table,(void*) oper[i])->val;
2759   for (i=1;i<lg(fram);i++)
2760     for (j=1;j<lg(gel(fram,i));j++)
2761       if (mael(fram,i,j))
2762         mael(fram,i,j) = (long) hash_search(table,(void*) mael(fram,i,j))->val;
2763 }
2764 
2765 void
gen_relink(GEN x,hashtable * table)2766 gen_relink(GEN x, hashtable *table)
2767 {
2768   long i, lx, tx = typ(x);
2769   switch(tx)
2770   {
2771     case t_CLOSURE:
2772       closure_relink(x, table);
2773       gen_relink(closure_get_data(x), table);
2774       if (lg(x)==8) gen_relink(closure_get_frame(x), table);
2775       break;
2776     case t_LIST:
2777       if (list_data(x)) gen_relink(list_data(x), table);
2778       break;
2779     case t_VEC: case t_COL: case t_MAT: case t_ERROR:
2780       lx = lg(x);
2781       for (i=lontyp[tx]; i<lx; i++) gen_relink(gel(x,i), table);
2782   }
2783 }
2784 
2785 static void
closure_unlink(GEN C)2786 closure_unlink(GEN C)
2787 {
2788   const char *code = closure_codestr(C);
2789   GEN oper = closure_get_oper(C);
2790   GEN fram = gel(closure_get_dbg(C),3);
2791   long i, j;
2792   for(i=1;i<lg(oper);i++)
2793     if (oper[i] && opcode_need_relink((op_code) code[i]))
2794     {
2795       long n = pari_stack_new(&s_relocs);
2796       relocs[n] = (entree *) oper[i];
2797     }
2798   for (i=1;i<lg(fram);i++)
2799     for (j=1;j<lg(gel(fram,i));j++)
2800       if (mael(fram,i,j))
2801       {
2802         long n = pari_stack_new(&s_relocs);
2803         relocs[n] = (entree *) mael(fram,i,j);
2804       }
2805 }
2806 
2807 static void
gen_unlink(GEN x)2808 gen_unlink(GEN x)
2809 {
2810   long i, lx, tx = typ(x);
2811   switch(tx)
2812   {
2813     case t_CLOSURE:
2814       closure_unlink(x);
2815       gen_unlink(closure_get_data(x));
2816       if (lg(x)==8) gen_unlink(closure_get_frame(x));
2817       break;
2818     case t_LIST:
2819       if (list_data(x)) gen_unlink(list_data(x));
2820       break;
2821     case t_VEC: case t_COL: case t_MAT: case t_ERROR:
2822       lx = lg(x);
2823       for (i = lontyp[tx]; i<lx; i++) gen_unlink(gel(x,i));
2824   }
2825 }
2826 
2827 GEN
copybin_unlink(GEN C)2828 copybin_unlink(GEN C)
2829 {
2830   long i, l , n, nold = s_relocs.n;
2831   GEN v, w, V, res;
2832   if (C)
2833     gen_unlink(C);
2834   else
2835   { /* contents of all variables */
2836     long v, maxv = pari_var_next();
2837     for (v=0; v<maxv; v++)
2838     {
2839       entree *ep = varentries[v];
2840       if (!ep || !ep->value) continue;
2841       gen_unlink((GEN)ep->value);
2842     }
2843   }
2844   n = s_relocs.n-nold;
2845   v = cgetg(n+1, t_VECSMALL);
2846   for(i=0; i<n; i++)
2847     v[i+1] = (long) relocs[i];
2848   s_relocs.n = nold;
2849   w = vecsmall_uniq(v); l = lg(w);
2850   res = cgetg(3,t_VEC);
2851   V = cgetg(l, t_VEC);
2852   for(i=1; i<l; i++)
2853   {
2854     entree *ep = (entree*) w[i];
2855     gel(V,i) = strtoGENstr(ep->name);
2856   }
2857   gel(res,1) = vecsmall_copy(w);
2858   gel(res,2) = V;
2859   return res;
2860 }
2861 
2862 /* e = t_VECSMALL of entree *ep [ addresses ],
2863  * names = t_VEC of strtoGENstr(ep.names),
2864  * Return hashtable : ep => is_entry(ep.name) */
2865 hashtable *
hash_from_link(GEN e,GEN names,int use_stack)2866 hash_from_link(GEN e, GEN names, int use_stack)
2867 {
2868   long i, l = lg(e);
2869   hashtable *h = hash_create_ulong(l-1, use_stack);
2870   if (lg(names) != l) pari_err_DIM("hash_from_link");
2871   for (i = 1; i < l; i++)
2872   {
2873     char *s = GSTR(gel(names,i));
2874     hash_insert(h, (void*)e[i], (void*)fetch_entry(s));
2875   }
2876   return h;
2877 }
2878 
2879 void
bincopy_relink(GEN C,GEN V)2880 bincopy_relink(GEN C, GEN V)
2881 {
2882   pari_sp av = avma;
2883   hashtable *table = hash_from_link(gel(V,1),gel(V,2),1);
2884   gen_relink(C, table);
2885   set_avma(av);
2886 }
2887