1 /* -*- compile-command: "g++-3.4 -I.. -g -c global.cc  -DHAVE_CONFIG_H -DIN_GIAC" -*- */
2 
3 #include "giacPCH.h"
4 
5 /*
6  *  Copyright (C) 2000,14 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 using namespace std;
23 #ifdef HAVE_SSTREAM
24 #include <sstream>
25 #else
26 #include <strstream>
27 #endif
28 #if !defined GIAC_HAS_STO_38 && !defined NSPIRE && !defined FXCG && !defined POCKETCAS
29 #include <fstream>
30 #endif
31 #include "global.h"
32 // #include <time.h>
33 #if !defined BESTA_OS && !defined FXCG
34 #include <signal.h>
35 #endif
36 #include <math.h>
37 #ifndef WINDOWS
38 #include <stdint.h>   // for uintptr_t
39 #endif
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 #ifdef HAVE_SYS_TYPES_H
44 #include <sys/types.h>
45 #endif
46 #ifdef HAVE_PWD_H
47 #include <pwd.h>
48 #endif
49 #include <string.h>
50 #include <stdexcept>
51 #include <algorithm>
52 #if !defined BESTA_OS && !defined FXCG
53 #include <cerrno>
54 #endif
55 #include "gen.h"
56 #include "identificateur.h"
57 #include "symbolic.h"
58 #include "sym2poly.h"
59 #include "plot.h"
60 #include "rpn.h"
61 #include "prog.h"
62 #include "usual.h"
63 #include "tex.h"
64 #include "path.h"
65 #include "input_lexer.h"
66 #include "giacintl.h"
67 #ifdef HAVE_LOCALE_H
68 #include <locale.h>
69 #endif
70 #ifdef _HAS_LIMITS
71 #include <limits>
72 #endif
73 #ifndef BESTA_OS
74 #ifdef WIN32
75 #ifndef VISUALC
76 #if !defined(GNUWINCE) && !defined(__MINGW_H)
77 #include <sys/cygwin.h>
78 #include <windows.h>
79 #endif // ndef gnuwince
80 #endif // ndef visualc
81 #endif // win32
82 #endif // ndef bestaos
83 
84 #if defined VISUALC && !defined BESTA_OS && !defined RTOS_THREADX && !defined FREERTOS
85 #include <Windows.h>
86 #endif
87 
88 #ifdef BESTA_OS
89 #include <stdlib.h>
90 #endif // besta_os
91 
92 #include <stdio.h>
93 #include <stdarg.h>
94 
95 #if defined(FIR)
96 extern "C" int firvsprintf(char*,const char*, va_list);
97 #endif
98 
99 #ifdef FXCG
100 extern "C" int KeyPressed( void );
101 #endif
102 
103 #ifdef KHICAS
104 #include "kdisplay.h"
105 #endif
106 
107 #ifdef NSPIRE_NEWLIB
108 #include <libndls.h>
109 #endif
110 
my_sprintf(char * s,const char * format,...)111 int my_sprintf(char * s, const char * format, ...){
112     int z;
113     va_list ap;
114     va_start(ap,format);
115 #if defined(FIR) && !defined(FIR_LINUX)
116     z = firvsprintf(s, format, ap);
117 #else
118     z = vsprintf(s, format, ap);
119 #endif
120     va_end(ap);
121     return z;
122 }
123 
124 #ifndef NO_NAMESPACE_GIAC
125 namespace giac {
126 #endif // ndef NO_NAMESPACE_GIAC
opaque_double_copy(void * source,void * target)127   void opaque_double_copy(void * source,void * target){
128     *((double *) target) = * ((double *) source);
129   }
130 
opaque_double_val(const void * source)131   double opaque_double_val(const void * source){
132     longlong r = * (longlong *)(source) ;
133     (* (gen *) (&r)).type = 0;
134     return * (double *)(&r);
135   }
136 
137   // FIXME: make the replacement call for APPLE
system_no_deprecation(const char * command)138   int system_no_deprecation(const char *command) {
139 #if defined _IOS_FIX_ || defined FXCG || defined OSXIOS
140     return 0;
141 #else
142     return system(command);
143 #endif
144   }
145 
146   double min_proba_time=10; // in seconds
147 
148 #ifdef FXCG
control_c()149   void control_c(){
150     int i=0 ; // KeyPressed(); // check for EXIT key pressed?
151     if (i==1){ ctrl_c=true; interrupted=true; }
152   }
153 #endif
154 
155 #ifdef TIMEOUT
156 #ifndef EMCC
time(int)157   double time(int ){
158     return double(CLOCK())/1000000; // CLOCKS_PER_SEC;
159   }
160 #endif
161   time_t caseval_begin,caseval_current;
162   double caseval_maxtime=15; // max 15 seconds
163   int caseval_n=0,caseval_mod=0,caseval_unitialized=-123454321;
164 #if !defined POCKETCAS
control_c()165   void control_c(){
166 #if defined NSPIRE || defined KHICAS
167     if (
168 #if defined NSPIRE || defined NSPIRE_NEWLIB
169 	on_key_enabled && on_key_pressed()
170 #else
171 	back_key_pressed()
172 #endif
173 	){
174       kbd_interrupted=true;
175       ctrl_c=interrupted=true;
176     }
177 #else
178     if (caseval_unitialized!=-123454321){
179       caseval_unitialized=-123454321;
180       caseval_mod=0;
181       caseval_n=0;
182       caseval_maxtime=15;
183     }
184     if (caseval_mod>0){
185       ++caseval_n;
186       if (caseval_n >=caseval_mod){
187 	caseval_n=0;
188 	caseval_current=time(0);
189 #ifdef EMCC
190 	if (difftime(caseval_current,caseval_begin)>caseval_maxtime)
191 #else
192 	if (caseval_current>caseval_maxtime+caseval_begin)
193 #endif
194 	  {
195 	    CERR << "Timeout" << '\n'; ctrl_c=true; interrupted=true;
196 	    caseval_begin=caseval_current;
197 	  }
198       }
199     }
200 #endif // NSPIRE
201   }
202 #endif // POCKETCAS
203 #endif // TIMEOUT
204 
205 #if defined KHICAS
usleep(int t)206   void usleep(int t){
207     os_wait_1ms(t/1000);
208   }
209 #else
210 #ifdef NSPIRE_NEWLIB
usleep(int t)211   void usleep(int t){
212     msleep(t/1000);
213   }
214 #endif
215 
216 #endif
217 
218 #if defined VISUALC || defined BESTA_OS
219 #if !defined FREERTOS && !defined HAVE_LIBMPIR
220   int R_OK=4;
221 #endif
access(const char * path,int mode)222   int access(const char *path, int mode ){
223     // return _access(path, mode );
224     return 0;
225   }
226 #ifdef RTOS_THREADX
227 extern "C" void Sleep(unsigned int miliSecond);
228 #endif
229 
usleep(int t)230   void usleep(int t){
231 #ifdef RTOS_THREADX
232     Sleep(t/1000);
233 #else
234     Sleep(int(t/1000.+.5));
235 #endif
236   }
237 #endif
238 
239 #ifdef __APPLE__
240   int PARENTHESIS_NWAIT=10;
241 #else
242   int PARENTHESIS_NWAIT=100;
243 #endif
244 
245   // FIXME: threads allowed curently disabled
246   // otherwise fermat_gcd_mod_2var crashes at puccini
247   bool threads_allowed=true,mpzclass_allowed=true;
248 #ifdef HAVE_LIBPTHREAD
249   pthread_mutex_t interactive_mutex = PTHREAD_MUTEX_INITIALIZER;
250 #endif
251 
vector_aide_ptr()252   std::vector<aide> * & vector_aide_ptr (){
253     static std::vector<aide> * ans = 0;
254     if (!ans) ans=new std::vector<aide>;
255     return ans;
256   }
vector_completions_ptr()257   std::vector<std::string> * & vector_completions_ptr (){
258     static std::vector<std::string> * ans = 0;
259     if (!ans) ans=new  std::vector<std::string>;
260     return ans;
261   }
262 #ifdef NSPIRE_NEWLIB
263   const context * context0=new context;
264 #else
265   const context * context0=0;
266 #endif
267   // Global variable when context is 0
268   void (*fl_widget_delete_function)(void *) =0;
269 #ifndef NSPIRE
270   ostream & (*fl_widget_archive_function)(ostream &,void *)=0;
271   gen (*fl_widget_unarchive_function)(istream &)=0;
272 #endif
273   gen (*fl_widget_updatepict_function)(const gen & g)=0;
274   std::string (*fl_widget_texprint_function)(void * ptr)=0;
275 
276   const char * _last_evaled_function_name_=0;
last_evaled_function_name(GIAC_CONTEXT)277   const char * & last_evaled_function_name(GIAC_CONTEXT){
278     if (contextptr && contextptr->globalptr )
279       return contextptr->globalptr->_last_evaled_function_name_;
280     else
281       return _last_evaled_function_name_;
282   }
283 
284   const char * _currently_scanned=0;
currently_scanned(GIAC_CONTEXT)285   const char * & currently_scanned(GIAC_CONTEXT){
286     if (contextptr && contextptr->globalptr )
287       return contextptr->globalptr->_currently_scanned_;
288     else
289       return _currently_scanned;
290   }
291 
292   const gen * _last_evaled_argptr_=0;
last_evaled_argptr(GIAC_CONTEXT)293   const gen * & last_evaled_argptr(GIAC_CONTEXT){
294     if (contextptr && contextptr->globalptr )
295       return contextptr->globalptr->_last_evaled_argptr_;
296     else
297       return _last_evaled_argptr_;
298   }
299 
300   static int _language_=0;
language(GIAC_CONTEXT)301   int & language(GIAC_CONTEXT){
302     if (contextptr && contextptr->globalptr )
303       return contextptr->globalptr->_language_;
304     else
305       return _language_;
306   }
language(int b,GIAC_CONTEXT)307   void language(int b,GIAC_CONTEXT){
308     if (contextptr && contextptr->globalptr )
309       contextptr->globalptr->_language_=b;
310 #ifndef EMCC
311     else
312 #endif
313       _language_=b;
314   }
315 
316   static int _max_sum_sqrt_=3;
max_sum_sqrt(GIAC_CONTEXT)317   int & max_sum_sqrt(GIAC_CONTEXT){
318     if (contextptr && contextptr->globalptr )
319       return contextptr->globalptr->_max_sum_sqrt_;
320     else
321       return _max_sum_sqrt_;
322   }
max_sum_sqrt(int b,GIAC_CONTEXT)323   void max_sum_sqrt(int b,GIAC_CONTEXT){
324     if (contextptr && contextptr->globalptr )
325       contextptr->globalptr->_max_sum_sqrt_=b;
326     else
327       _max_sum_sqrt_=b;
328   }
329 
330 #ifdef GIAC_HAS_STO_38 // Prime sum(x^2,x,0,100000) crash on hardware
331   static int _max_sum_add_=10000;
332 #else
333   static int _max_sum_add_=100000;
334 #endif
max_sum_add(GIAC_CONTEXT)335   int & max_sum_add(GIAC_CONTEXT){
336     if (contextptr && contextptr->globalptr )
337       return contextptr->globalptr->_max_sum_add_;
338     else
339       return _max_sum_add_;
340   }
341 
342   static int _default_color_=FL_BLACK;
default_color(GIAC_CONTEXT)343   int & default_color(GIAC_CONTEXT){
344     if (contextptr && contextptr->globalptr )
345       return contextptr->globalptr->_default_color_;
346     else
347       return _default_color_;
348   }
default_color(int c,GIAC_CONTEXT)349   void default_color(int c,GIAC_CONTEXT){
350     if (contextptr && contextptr->globalptr)
351       contextptr->globalptr->_default_color_=c;
352     else
353       _default_color_=c;
354   }
355 
356   static void * _evaled_table_=0;
evaled_table(GIAC_CONTEXT)357   void * & evaled_table(GIAC_CONTEXT){
358     if (contextptr && contextptr->globalptr )
359       return contextptr->globalptr->_evaled_table_;
360     else
361       return _evaled_table_;
362   }
363 
364   static void * _extra_ptr_=0;
extra_ptr(GIAC_CONTEXT)365   void * & extra_ptr(GIAC_CONTEXT){
366     if (contextptr && contextptr->globalptr )
367       return contextptr->globalptr->_extra_ptr_;
368     else
369       return _extra_ptr_;
370   }
371 
372   static int _spread_Row_=0;
spread_Row(GIAC_CONTEXT)373   int & spread_Row(GIAC_CONTEXT){
374     if (contextptr && contextptr->globalptr )
375       return contextptr->globalptr->_spread_Row_;
376     else
377       return _spread_Row_;
378   }
spread_Row(int c,GIAC_CONTEXT)379   void spread_Row(int c,GIAC_CONTEXT){
380     if (contextptr && contextptr->globalptr)
381       contextptr->globalptr->_spread_Row_=c;
382     else
383       _spread_Row_=c;
384   }
385 
386   static int _spread_Col_=0;
spread_Col(GIAC_CONTEXT)387   int & spread_Col(GIAC_CONTEXT){
388     if (contextptr && contextptr->globalptr )
389       return contextptr->globalptr->_spread_Col_;
390     else
391       return _spread_Col_;
392   }
spread_Col(int c,GIAC_CONTEXT)393   void spread_Col(int c,GIAC_CONTEXT){
394     if (contextptr && contextptr->globalptr)
395       contextptr->globalptr->_spread_Col_=c;
396     else
397       _spread_Col_=c;
398   }
399 
400   static int _printcell_current_row_=0;
printcell_current_row(GIAC_CONTEXT)401   int & printcell_current_row(GIAC_CONTEXT){
402     if (contextptr && contextptr->globalptr )
403       return contextptr->globalptr->_printcell_current_row_;
404     else
405       return _printcell_current_row_;
406   }
printcell_current_row(int c,GIAC_CONTEXT)407   void printcell_current_row(int c,GIAC_CONTEXT){
408     if (contextptr && contextptr->globalptr)
409       contextptr->globalptr->_printcell_current_row_=c;
410     else
411       _printcell_current_row_=c;
412   }
413 
414   static int _printcell_current_col_=0;
printcell_current_col(GIAC_CONTEXT)415   int & printcell_current_col(GIAC_CONTEXT){
416     if (contextptr && contextptr->globalptr )
417       return contextptr->globalptr->_printcell_current_col_;
418     else
419       return _printcell_current_col_;
420   }
printcell_current_col(int c,GIAC_CONTEXT)421   void printcell_current_col(int c,GIAC_CONTEXT){
422     if (contextptr && contextptr->globalptr)
423       contextptr->globalptr->_printcell_current_col_=c;
424     else
425       _printcell_current_col_=c;
426   }
427 
428   static double _total_time_=0.0;
total_time(GIAC_CONTEXT)429   double & total_time(GIAC_CONTEXT){
430     if (contextptr && contextptr->globalptr )
431       return contextptr->globalptr->_total_time_;
432     else
433       return _total_time_;
434   }
435 
436 #if 1
437   static double _epsilon_=1e-12;
438 #else
439 #ifdef __SGI_CPP_LIMITS
440   static double _epsilon_=100*numeric_limits<double>::epsilon();
441 #else
442   static double _epsilon_=1e-12;
443 #endif
444 #endif
epsilon(GIAC_CONTEXT)445   double & epsilon(GIAC_CONTEXT){
446     if (contextptr && contextptr->globalptr )
447       return contextptr->globalptr->_epsilon_;
448     else
449       return _epsilon_;
450   }
epsilon(double c,GIAC_CONTEXT)451   void epsilon(double c,GIAC_CONTEXT){
452     if (contextptr && contextptr->globalptr)
453       contextptr->globalptr->_epsilon_=c;
454     else
455       _epsilon_=c;
456   }
457 
458   static double _proba_epsilon_=1e-15;
proba_epsilon(GIAC_CONTEXT)459   double & proba_epsilon(GIAC_CONTEXT){
460     if (contextptr && contextptr->globalptr )
461       return contextptr->globalptr->_proba_epsilon_;
462     else
463       return _proba_epsilon_;
464   }
465 
466   static bool _expand_re_im_=true;
expand_re_im(GIAC_CONTEXT)467   bool & expand_re_im(GIAC_CONTEXT){
468     if (contextptr && contextptr->globalptr )
469       return contextptr->globalptr->_expand_re_im_;
470     else
471       return _expand_re_im_;
472   }
expand_re_im(bool b,GIAC_CONTEXT)473   void expand_re_im(bool b,GIAC_CONTEXT){
474     if (contextptr && contextptr->globalptr )
475       contextptr->globalptr->_expand_re_im_=b;
476     else
477       _expand_re_im_=b;
478   }
479 
480   static int _scientific_format_=0;
scientific_format(GIAC_CONTEXT)481   int & scientific_format(GIAC_CONTEXT){
482     if (contextptr && contextptr->globalptr )
483       return contextptr->globalptr->_scientific_format_;
484     else
485       return _scientific_format_;
486   }
scientific_format(int b,GIAC_CONTEXT)487   void scientific_format(int b,GIAC_CONTEXT){
488     if (contextptr && contextptr->globalptr )
489       contextptr->globalptr->_scientific_format_=b;
490     else
491       _scientific_format_=b;
492   }
493 
494   static int _decimal_digits_=12;
495 
decimal_digits(GIAC_CONTEXT)496   int & decimal_digits(GIAC_CONTEXT){
497     if (contextptr && contextptr->globalptr )
498       return contextptr->globalptr->_decimal_digits_;
499     else
500       return _decimal_digits_;
501   }
decimal_digits(int b,GIAC_CONTEXT)502   void decimal_digits(int b,GIAC_CONTEXT){
503     if (contextptr && contextptr->globalptr )
504       contextptr->globalptr->_decimal_digits_=b;
505     else
506       _decimal_digits_=b;
507   }
508 
509   static int _minchar_for_quote_as_string_=1;
510 
minchar_for_quote_as_string(GIAC_CONTEXT)511   int & minchar_for_quote_as_string(GIAC_CONTEXT){
512     if (contextptr && contextptr->globalptr )
513       return contextptr->globalptr->_minchar_for_quote_as_string_;
514     else
515       return _minchar_for_quote_as_string_;
516   }
minchar_for_quote_as_string(int b,GIAC_CONTEXT)517   void minchar_for_quote_as_string(int b,GIAC_CONTEXT){
518     if (contextptr && contextptr->globalptr )
519       contextptr->globalptr->_minchar_for_quote_as_string_=b;
520     else
521       _minchar_for_quote_as_string_=b;
522   }
523 
524   static int _xcas_mode_=0;
xcas_mode(GIAC_CONTEXT)525   int & xcas_mode(GIAC_CONTEXT){
526     if (contextptr && contextptr->globalptr )
527       return contextptr->globalptr->_xcas_mode_;
528     else
529       return _xcas_mode_;
530   }
xcas_mode(int b,GIAC_CONTEXT)531   void xcas_mode(int b,GIAC_CONTEXT){
532     if (contextptr && contextptr->globalptr )
533       contextptr->globalptr->_xcas_mode_=b;
534     else
535       _xcas_mode_=b;
536   }
537 
538 
539   static int _integer_format_=0;
integer_format(GIAC_CONTEXT)540   int & integer_format(GIAC_CONTEXT){
541     if (contextptr && contextptr->globalptr )
542       return contextptr->globalptr->_integer_format_;
543     else
544       return _integer_format_;
545   }
integer_format(int b,GIAC_CONTEXT)546   void integer_format(int b,GIAC_CONTEXT){
547     if (contextptr && contextptr->globalptr )
548       contextptr->globalptr->_integer_format_=b;
549     else
550       _integer_format_=b;
551   }
552   static int _latex_format_=0;
latex_format(GIAC_CONTEXT)553   int & latex_format(GIAC_CONTEXT){
554     if (contextptr && contextptr->globalptr )
555       return contextptr->globalptr->_latex_format_;
556     else
557       return _latex_format_;
558   }
559 #ifdef BCD
560   static u32 _bcd_decpoint_='.'|('E'<<16)|(' '<<24);
bcd_decpoint(GIAC_CONTEXT)561   u32 & bcd_decpoint(GIAC_CONTEXT){
562     if (contextptr && contextptr->globalptr )
563       return contextptr->globalptr->_bcd_decpoint_;
564     else
565       return _bcd_decpoint_;
566   }
567 
568   static u32 _bcd_mantissa_=12+(15<<8);
bcd_mantissa(GIAC_CONTEXT)569   u32 & bcd_mantissa(GIAC_CONTEXT){
570     if (contextptr && contextptr->globalptr )
571       return contextptr->globalptr->_bcd_mantissa_;
572     else
573       return _bcd_mantissa_;
574   }
575 
576   static u32 _bcd_flags_=0;
bcd_flags(GIAC_CONTEXT)577   u32 & bcd_flags(GIAC_CONTEXT){
578     if (contextptr && contextptr->globalptr )
579       return contextptr->globalptr->_bcd_flags_;
580     else
581       return _bcd_flags_;
582   }
583 
584   static bool _bcd_printdouble_=false;
bcd_printdouble(GIAC_CONTEXT)585   bool & bcd_printdouble(GIAC_CONTEXT){
586     if (contextptr && contextptr->globalptr )
587       return contextptr->globalptr->_bcd_printdouble_;
588     else
589       return _bcd_printdouble_;
590   }
591 
592 #endif
593 
594   static bool _integer_mode_=true;
integer_mode(GIAC_CONTEXT)595   bool & integer_mode(GIAC_CONTEXT){
596     if (contextptr && contextptr->globalptr )
597       return contextptr->globalptr->_integer_mode_;
598     else
599       return _integer_mode_;
600   }
601 
integer_mode(bool b,GIAC_CONTEXT)602   void integer_mode(bool b,GIAC_CONTEXT){
603     if (contextptr && contextptr->globalptr )
604       contextptr->globalptr->_integer_mode_=b;
605     else
606       _integer_mode_=b;
607   }
608 
609   bool python_color=false;
610 #ifdef NSPIRE_NEWLIB
611   bool os_shell=false;
612 #else
613   bool os_shell=true;
614 #endif
615 
616 #ifdef KHICAS
617   static int _python_compat_=true;
618 #else
619   static int _python_compat_=false;
620 #endif
python_compat(GIAC_CONTEXT)621   int & python_compat(GIAC_CONTEXT){
622     if (contextptr && contextptr->globalptr )
623       return contextptr->globalptr->_python_compat_;
624     else
625       return _python_compat_;
626   }
627 
python_compat(int b,GIAC_CONTEXT)628   void python_compat(int b,GIAC_CONTEXT){
629     python_color=b; //cout << "python_color " << b << '\n';
630     if (contextptr && contextptr->globalptr )
631       contextptr->globalptr->_python_compat_=b;
632     else
633       _python_compat_=b;
634   }
635 
636   static bool _complex_mode_=false;
complex_mode(GIAC_CONTEXT)637   bool & complex_mode(GIAC_CONTEXT){
638     if (contextptr && contextptr->globalptr )
639       return contextptr->globalptr->_complex_mode_;
640     else
641       return _complex_mode_;
642   }
643 
complex_mode(bool b,GIAC_CONTEXT)644   void complex_mode(bool b,GIAC_CONTEXT){
645     if (contextptr && contextptr->globalptr )
646       contextptr->globalptr->_complex_mode_=b;
647     else
648       _complex_mode_=b;
649   }
650 
651   static bool _escape_real_=true;
escape_real(GIAC_CONTEXT)652   bool & escape_real(GIAC_CONTEXT){
653     if (contextptr && contextptr->globalptr )
654       return contextptr->globalptr->_escape_real_;
655     else
656       return _escape_real_;
657   }
658 
escape_real(bool b,GIAC_CONTEXT)659   void escape_real(bool b,GIAC_CONTEXT){
660     if (contextptr && contextptr->globalptr )
661       contextptr->globalptr->_escape_real_=b;
662     else
663       _escape_real_=b;
664   }
665 
666   static bool _do_lnabs_=true;
do_lnabs(GIAC_CONTEXT)667   bool & do_lnabs(GIAC_CONTEXT){
668     if (contextptr && contextptr->globalptr )
669       return contextptr->globalptr->_do_lnabs_;
670     else
671       return _do_lnabs_;
672   }
673 
do_lnabs(bool b,GIAC_CONTEXT)674   void do_lnabs(bool b,GIAC_CONTEXT){
675     if (contextptr && contextptr->globalptr )
676       contextptr->globalptr->_do_lnabs_=b;
677     else
678       _do_lnabs_=b;
679   }
680 
681   static bool _eval_abs_=true;
eval_abs(GIAC_CONTEXT)682   bool & eval_abs(GIAC_CONTEXT){
683     if (contextptr && contextptr->globalptr )
684       return contextptr->globalptr->_eval_abs_;
685     else
686       return _eval_abs_;
687   }
688 
eval_abs(bool b,GIAC_CONTEXT)689   void eval_abs(bool b,GIAC_CONTEXT){
690     if (contextptr && contextptr->globalptr )
691       contextptr->globalptr->_eval_abs_=b;
692     else
693       _eval_abs_=b;
694   }
695 
696   static bool _eval_equaltosto_=true;
eval_equaltosto(GIAC_CONTEXT)697   bool & eval_equaltosto(GIAC_CONTEXT){
698     if (contextptr && contextptr->globalptr )
699       return contextptr->globalptr->_eval_equaltosto_;
700     else
701       return _eval_equaltosto_;
702   }
703 
eval_equaltosto(bool b,GIAC_CONTEXT)704   void eval_equaltosto(bool b,GIAC_CONTEXT){
705     if (contextptr && contextptr->globalptr )
706       contextptr->globalptr->_eval_equaltosto_=b;
707     else
708       _eval_equaltosto_=b;
709   }
710 
711   static bool _all_trig_sol_=false;
all_trig_sol(GIAC_CONTEXT)712   bool & all_trig_sol(GIAC_CONTEXT){
713     if (contextptr && contextptr->globalptr )
714       return contextptr->globalptr->_all_trig_sol_;
715     else
716       return _all_trig_sol_;
717   }
718 
all_trig_sol(bool b,GIAC_CONTEXT)719   void all_trig_sol(bool b,GIAC_CONTEXT){
720     if (contextptr && contextptr->globalptr )
721       contextptr->globalptr->_all_trig_sol_=b;
722     else
723       _all_trig_sol_=b;
724   }
725 
726   static bool _try_parse_i_=true;
try_parse_i(GIAC_CONTEXT)727   bool & try_parse_i(GIAC_CONTEXT){
728     if (contextptr && contextptr->globalptr )
729       return contextptr->globalptr->_try_parse_i_;
730     else
731       return _try_parse_i_;
732   }
733 
try_parse_i(bool b,GIAC_CONTEXT)734   void try_parse_i(bool b,GIAC_CONTEXT){
735     if (contextptr && contextptr->globalptr )
736       contextptr->globalptr->_try_parse_i_=b;
737     else
738       _try_parse_i_=b;
739   }
740 
741   static bool _specialtexprint_double_=false;
specialtexprint_double(GIAC_CONTEXT)742   bool & specialtexprint_double(GIAC_CONTEXT){
743     if (contextptr && contextptr->globalptr )
744       return contextptr->globalptr->_specialtexprint_double_;
745     else
746       return _specialtexprint_double_;
747   }
748 
specialtexprint_double(bool b,GIAC_CONTEXT)749   void specialtexprint_double(bool b,GIAC_CONTEXT){
750     if (contextptr && contextptr->globalptr )
751       contextptr->globalptr->_specialtexprint_double_=b;
752     else
753       _specialtexprint_double_=b;
754   }
755 
756   static bool _atan_tan_no_floor_=false;
atan_tan_no_floor(GIAC_CONTEXT)757   bool & atan_tan_no_floor(GIAC_CONTEXT){
758     if (contextptr && contextptr->globalptr )
759       return contextptr->globalptr->_atan_tan_no_floor_;
760     else
761       return _atan_tan_no_floor_;
762   }
763 
atan_tan_no_floor(bool b,GIAC_CONTEXT)764   void atan_tan_no_floor(bool b,GIAC_CONTEXT){
765     if (contextptr && contextptr->globalptr )
766       contextptr->globalptr->_atan_tan_no_floor_=b;
767     else
768       _atan_tan_no_floor_=b;
769   }
770 
771   static bool _keep_acosh_asinh_=false;
keep_acosh_asinh(GIAC_CONTEXT)772   bool & keep_acosh_asinh(GIAC_CONTEXT){
773     if (contextptr && contextptr->globalptr )
774       return contextptr->globalptr->_keep_acosh_asinh_;
775     else
776       return _keep_acosh_asinh_;
777   }
778 
keep_acosh_asinh(bool b,GIAC_CONTEXT)779   void keep_acosh_asinh(bool b,GIAC_CONTEXT){
780     if (contextptr && contextptr->globalptr )
781       contextptr->globalptr->_keep_acosh_asinh_=b;
782     else
783       _keep_acosh_asinh_=b;
784   }
785 
786   static bool _keep_algext_=false;
keep_algext(GIAC_CONTEXT)787   bool & keep_algext(GIAC_CONTEXT){
788     if (contextptr && contextptr->globalptr )
789       return contextptr->globalptr->_keep_algext_;
790     else
791       return _keep_algext_;
792   }
793 
keep_algext(bool b,GIAC_CONTEXT)794   void keep_algext(bool b,GIAC_CONTEXT){
795     if (contextptr && contextptr->globalptr )
796       contextptr->globalptr->_keep_algext_=b;
797     else
798       _keep_algext_=b;
799   }
800 
801   static bool _lexer_close_parenthesis_=true;
lexer_close_parenthesis(GIAC_CONTEXT)802   bool & lexer_close_parenthesis(GIAC_CONTEXT){
803     if (contextptr && contextptr->globalptr )
804       return contextptr->globalptr->_lexer_close_parenthesis_;
805     else
806       return _lexer_close_parenthesis_;
807   }
808 
lexer_close_parenthesis(bool b,GIAC_CONTEXT)809   void lexer_close_parenthesis(bool b,GIAC_CONTEXT){
810     if (contextptr && contextptr->globalptr )
811       contextptr->globalptr->_lexer_close_parenthesis_=b;
812     else
813       _lexer_close_parenthesis_=b;
814   }
815 
816   static bool _rpn_mode_=false;
rpn_mode(GIAC_CONTEXT)817   bool & rpn_mode(GIAC_CONTEXT){
818     if (contextptr && contextptr->globalptr )
819       return contextptr->globalptr->_rpn_mode_;
820     else
821       return _rpn_mode_;
822   }
823 
rpn_mode(bool b,GIAC_CONTEXT)824   void rpn_mode(bool b,GIAC_CONTEXT){
825     if (contextptr && contextptr->globalptr )
826       contextptr->globalptr->_rpn_mode_=b;
827     else
828       _rpn_mode_=b;
829   }
830 
831   static bool _ntl_on_=true;
ntl_on(GIAC_CONTEXT)832   bool & ntl_on(GIAC_CONTEXT){
833     if (contextptr && contextptr->globalptr )
834       return contextptr->globalptr->_ntl_on_;
835     else
836       return _ntl_on_;
837   }
838 
ntl_on(bool b,GIAC_CONTEXT)839   void ntl_on(bool b,GIAC_CONTEXT){
840     if (contextptr && contextptr->globalptr )
841       contextptr->globalptr->_ntl_on_=b;
842     else
843       _ntl_on_=b;
844   }
845 
846   static bool _complex_variables_=false;
complex_variables(GIAC_CONTEXT)847   bool & complex_variables(GIAC_CONTEXT){
848     if (contextptr && contextptr->globalptr )
849       return contextptr->globalptr->_complex_variables_;
850     else
851       return _complex_variables_;
852   }
853 
complex_variables(bool b,GIAC_CONTEXT)854   void complex_variables(bool b,GIAC_CONTEXT){
855     if (contextptr && contextptr->globalptr )
856       contextptr->globalptr->_complex_variables_=b;
857     else
858       _complex_variables_=b;
859   }
860 
861   static bool _increasing_power_=false;
increasing_power(GIAC_CONTEXT)862   bool & increasing_power(GIAC_CONTEXT){
863     if (contextptr && contextptr->globalptr )
864       return contextptr->globalptr->_increasing_power_;
865     else
866       return _increasing_power_;
867   }
868 
increasing_power(bool b,GIAC_CONTEXT)869   void increasing_power(bool b,GIAC_CONTEXT){
870     if (contextptr && contextptr->globalptr )
871       contextptr->globalptr->_increasing_power_=b;
872     else
873       _increasing_power_=b;
874   }
875 
_history_in_()876   static vecteur & _history_in_(){
877     static vecteur * ans = 0;
878     if (ans)
879       ans=new vecteur;
880     return *ans;
881   }
history_in(GIAC_CONTEXT)882   vecteur & history_in(GIAC_CONTEXT){
883     if (contextptr)
884       return *contextptr->history_in_ptr;
885     else
886       return _history_in_();
887   }
888 
_history_out_()889   static vecteur & _history_out_(){
890     static vecteur * ans = 0;
891     if (!ans)
892       ans=new vecteur;
893     return *ans;
894   }
history_out(GIAC_CONTEXT)895   vecteur & history_out(GIAC_CONTEXT){
896     if (contextptr)
897       return *contextptr->history_out_ptr;
898     else
899       return _history_out_();
900   }
901 
_history_plot_()902   static vecteur & _history_plot_(){
903     static vecteur * ans = 0;
904     if (!ans)
905       ans=new vecteur;
906     return *ans;
907   }
history_plot(GIAC_CONTEXT)908   vecteur & history_plot(GIAC_CONTEXT){
909     if (contextptr)
910       return *contextptr->history_plot_ptr;
911     else
912       return _history_plot_();
913   }
914 
915   static bool _approx_mode_=false;
approx_mode(GIAC_CONTEXT)916   bool & approx_mode(GIAC_CONTEXT){
917     if (contextptr && contextptr->globalptr )
918       return contextptr->globalptr->_approx_mode_;
919     else
920       return _approx_mode_;
921   }
922 
approx_mode(bool b,GIAC_CONTEXT)923   void approx_mode(bool b,GIAC_CONTEXT){
924     if (contextptr && contextptr->globalptr )
925       contextptr->globalptr->_approx_mode_=b;
926     else
927       _approx_mode_=b;
928   }
929 
930   static char _series_variable_name_='h';
series_variable_name(GIAC_CONTEXT)931   char & series_variable_name(GIAC_CONTEXT){
932     if (contextptr && contextptr->globalptr )
933       return contextptr->globalptr->_series_variable_name_;
934     else
935       return _series_variable_name_;
936   }
937 
series_variable_name(char b,GIAC_CONTEXT)938   void series_variable_name(char b,GIAC_CONTEXT){
939     if (contextptr && contextptr->globalptr )
940       contextptr->globalptr->_series_variable_name_=b;
941     else
942       _series_variable_name_=b;
943   }
944 
945   static unsigned short _series_default_order_=5;
series_default_order(GIAC_CONTEXT)946   unsigned short & series_default_order(GIAC_CONTEXT){
947     if (contextptr && contextptr->globalptr )
948       return contextptr->globalptr->_series_default_order_;
949     else
950       return _series_default_order_;
951   }
952 
series_default_order(unsigned short b,GIAC_CONTEXT)953   void series_default_order(unsigned short b,GIAC_CONTEXT){
954     if (contextptr && contextptr->globalptr )
955       contextptr->globalptr->_series_default_order_=b;
956     else
957       _series_default_order_=b;
958   }
959 
960   static int _angle_mode_=0;
angle_radian(GIAC_CONTEXT)961   bool angle_radian(GIAC_CONTEXT)
962   {
963     if(contextptr && contextptr->globalptr)
964       return contextptr->globalptr->_angle_mode_ == 0;
965     else
966       return _angle_mode_ == 0;
967   }
968 
angle_radian(bool b,GIAC_CONTEXT)969   void angle_radian(bool b,GIAC_CONTEXT){
970     if (contextptr && contextptr->globalptr )
971       contextptr->globalptr->_angle_mode_=(b?0:1);
972     else
973       _angle_mode_=(b?0:1);
974   }
975 
angle_degree(GIAC_CONTEXT)976   bool angle_degree(GIAC_CONTEXT)
977   {
978     if(contextptr && contextptr->globalptr)
979       return contextptr->globalptr->_angle_mode_ == 1;
980     else
981       return _angle_mode_ == 1;
982   }
983 
get_mode_set_radian(GIAC_CONTEXT)984   int get_mode_set_radian(GIAC_CONTEXT)
985   {
986     int mode;
987     if(contextptr && contextptr->globalptr)
988     {
989       mode = contextptr->globalptr->_angle_mode_;
990       contextptr->globalptr->_angle_mode_ = 0;
991     }
992     else
993     {
994       mode = _angle_mode_;
995       _angle_mode_ = 0;
996     }
997     return mode;
998   }
999 
angle_mode(int b,GIAC_CONTEXT)1000   void angle_mode(int b, GIAC_CONTEXT)
1001   {
1002     if(contextptr && contextptr->globalptr)
1003       contextptr->globalptr->_angle_mode_ = b;
1004     else
1005       _angle_mode_ = b;
1006   }
1007 
angle_mode(GIAC_CONTEXT)1008   int & angle_mode(GIAC_CONTEXT)
1009   {
1010     if (contextptr && contextptr->globalptr )
1011       return contextptr->globalptr->_angle_mode_;
1012     else
1013       return _angle_mode_;
1014   }
1015 
1016   static bool _show_point_=true;
show_point(GIAC_CONTEXT)1017   bool & show_point(GIAC_CONTEXT){
1018     if (contextptr && contextptr->globalptr )
1019       return contextptr->globalptr->_show_point_;
1020     else
1021       return _show_point_;
1022   }
1023 
show_point(bool b,GIAC_CONTEXT)1024   void show_point(bool b,GIAC_CONTEXT){
1025     if (contextptr && contextptr->globalptr )
1026       contextptr->globalptr->_show_point_=b;
1027     else
1028       _show_point_=b;
1029   }
1030 
1031   static int _show_axes_=1;
show_axes(GIAC_CONTEXT)1032   int & show_axes(GIAC_CONTEXT){
1033     if (contextptr && contextptr->globalptr )
1034       return contextptr->globalptr->_show_axes_;
1035     else
1036       return _show_axes_;
1037   }
1038 
show_axes(int b,GIAC_CONTEXT)1039   void show_axes(int b,GIAC_CONTEXT){
1040     if (contextptr && contextptr->globalptr )
1041       contextptr->globalptr->_show_axes_=b;
1042     else
1043       _show_axes_=b;
1044   }
1045 
1046   static bool _io_graph_=false;
1047   // DO NOT SET TO true WITH non-zero contexts or fix symadd when points are added
io_graph(GIAC_CONTEXT)1048   bool & io_graph(GIAC_CONTEXT){
1049     if (contextptr && contextptr->globalptr )
1050       return contextptr->globalptr->_io_graph_;
1051     else
1052       return _io_graph_;
1053   }
1054 
io_graph(bool b,GIAC_CONTEXT)1055   void io_graph(bool b,GIAC_CONTEXT){
1056     if (contextptr && contextptr->globalptr )
1057       contextptr->globalptr->_io_graph_=b;
1058     else
1059       _io_graph_=b;
1060   }
1061 
1062   static bool _variables_are_files_=false;
variables_are_files(GIAC_CONTEXT)1063   bool & variables_are_files(GIAC_CONTEXT){
1064     if (contextptr && contextptr->globalptr )
1065       return contextptr->globalptr->_variables_are_files_;
1066     else
1067       return _variables_are_files_;
1068   }
1069 
variables_are_files(bool b,GIAC_CONTEXT)1070   void variables_are_files(bool b,GIAC_CONTEXT){
1071     if (contextptr && contextptr->globalptr )
1072       contextptr->globalptr->_variables_are_files_=b;
1073     else
1074       _variables_are_files_=b;
1075   }
1076 
1077   static int _bounded_function_no_=0;
bounded_function_no(GIAC_CONTEXT)1078   int & bounded_function_no(GIAC_CONTEXT){
1079     if (contextptr && contextptr->globalptr )
1080       return contextptr->globalptr->_bounded_function_no_;
1081     else
1082       return _bounded_function_no_;
1083   }
1084 
bounded_function_no(int b,GIAC_CONTEXT)1085   void bounded_function_no(int b,GIAC_CONTEXT){
1086     if (contextptr && contextptr->globalptr )
1087       contextptr->globalptr->_bounded_function_no_=b;
1088     else
1089       _bounded_function_no_=b;
1090   }
1091 
1092   static int _series_flags_=0x3;
series_flags(GIAC_CONTEXT)1093   int & series_flags(GIAC_CONTEXT){
1094     if (contextptr && contextptr->globalptr )
1095       return contextptr->globalptr->_series_flags_;
1096     else
1097       return _series_flags_;
1098   }
1099 
series_flags(int b,GIAC_CONTEXT)1100   void series_flags(int b,GIAC_CONTEXT){
1101     if (contextptr && contextptr->globalptr )
1102       contextptr->globalptr->_series_flags_=b;
1103     else
1104       _series_flags_=b;
1105   }
1106 
1107   static int _step_infolevel_=0;
step_infolevel(GIAC_CONTEXT)1108   int & step_infolevel(GIAC_CONTEXT){
1109     if (contextptr && contextptr->globalptr )
1110       return contextptr->globalptr->_step_infolevel_;
1111     else
1112       return _step_infolevel_;
1113   }
1114 
step_infolevel(int b,GIAC_CONTEXT)1115   void step_infolevel(int b,GIAC_CONTEXT){
1116     if (contextptr && contextptr->globalptr )
1117       contextptr->globalptr->_step_infolevel_=b;
1118     else
1119       _step_infolevel_=b;
1120   }
1121 
1122   static bool _local_eval_=true;
local_eval(GIAC_CONTEXT)1123   bool & local_eval(GIAC_CONTEXT){
1124     if (contextptr && contextptr->globalptr )
1125       return contextptr->globalptr->_local_eval_;
1126     else
1127       return _local_eval_;
1128   }
1129 
local_eval(bool b,GIAC_CONTEXT)1130   void local_eval(bool b,GIAC_CONTEXT){
1131     if (contextptr && contextptr->globalptr )
1132       contextptr->globalptr->_local_eval_=b;
1133     else
1134       _local_eval_=b;
1135   }
1136 
1137   static bool _withsqrt_=true;
withsqrt(GIAC_CONTEXT)1138   bool & withsqrt(GIAC_CONTEXT){
1139     if (contextptr && contextptr->globalptr )
1140       return contextptr->globalptr->_withsqrt_;
1141     else
1142       return _withsqrt_;
1143   }
1144 
withsqrt(bool b,GIAC_CONTEXT)1145   void withsqrt(bool b,GIAC_CONTEXT){
1146     if (contextptr && contextptr->globalptr )
1147       contextptr->globalptr->_withsqrt_=b;
1148     else
1149       _withsqrt_=b;
1150   }
1151 
1152 #ifdef WITH_MYOSTREAM
1153   my_ostream my_cerr (&CERR);
1154   static my_ostream * _logptr_= &my_cerr;
1155 
logptr(GIAC_CONTEXT)1156   my_ostream * logptr(GIAC_CONTEXT){
1157     my_ostream * res;
1158     if (contextptr && contextptr->globalptr )
1159       res=contextptr->globalptr->_logptr_;
1160     else
1161       res= _logptr_;
1162     return res?res:&my_cerr;
1163   }
1164 #else
1165 #ifdef NSPIRE
1166   static nio::console * _logptr_=&CERR;
logptr(GIAC_CONTEXT)1167   nio::console * logptr(GIAC_CONTEXT){
1168     return &CERR;
1169   }
1170 #else
1171 #ifdef FXCG
1172   static ostream * _logptr_=0;
1173 #else
1174 #ifdef KHICAS
1175   stdostream os_cerr;
1176   static my_ostream * _logptr_=&os_cerr;
1177 #else
1178   static my_ostream * _logptr_=&CERR;
1179 #endif
1180 #endif
logptr(GIAC_CONTEXT)1181   my_ostream * logptr(GIAC_CONTEXT){
1182     my_ostream * res;
1183     if (contextptr && contextptr->globalptr )
1184       res=contextptr->globalptr->_logptr_;
1185     else
1186       res= _logptr_;
1187 #ifdef EMCC
1188     return res?res:&COUT;
1189 #else
1190 #ifdef FXCG
1191     return 0;
1192 #else
1193 #ifdef KHICAS
1194     return res?res:&os_cerr;
1195 #else
1196     return res?res:&CERR;
1197 #endif
1198 #endif
1199 #endif
1200   }
1201 #endif
1202 #endif
1203 
logptr(my_ostream * b,GIAC_CONTEXT)1204   void logptr(my_ostream * b,GIAC_CONTEXT){
1205 #ifdef NSPIRE
1206 #else
1207     if (contextptr && contextptr->globalptr )
1208       contextptr->globalptr->_logptr_=b;
1209     else
1210       _logptr_=b;
1211 #endif
1212   }
1213 
thread_param()1214   thread_param::thread_param(): _kill_thread(false), thread_eval_status(-1), v(6)
1215 #ifdef HAVE_LIBPTHREAD
1216 #ifdef __MINGW_H
1217 			      ,eval_thread(),stackaddr(0)
1218 #else
1219 			      ,eval_thread(0),stackaddr(0)
1220 #endif
1221 #endif
1222   {
1223   }
1224 
context0_thread_param_ptr()1225   thread_param * & context0_thread_param_ptr(){
1226     static thread_param * ans=0;
1227     if (!ans)
1228       ans=new thread_param();
1229     return ans;
1230   }
1231 
1232 #if 0
1233   static thread_param & context0_thread_param(){
1234     return *context0_thread_param_ptr();
1235   }
1236 #endif
1237 
thread_param_ptr(const context * contextptr)1238   thread_param * thread_param_ptr(const context * contextptr){
1239     return (contextptr && contextptr->globalptr)?contextptr->globalptr->_thread_param_ptr:context0_thread_param_ptr();
1240   }
1241 
kill_thread(GIAC_CONTEXT)1242   bool kill_thread(GIAC_CONTEXT){
1243     thread_param * ptr= (contextptr && contextptr->globalptr )?contextptr->globalptr->_thread_param_ptr:0;
1244     return ptr?ptr->_kill_thread:context0_thread_param_ptr()->_kill_thread;
1245   }
1246 
kill_thread(bool b,GIAC_CONTEXT)1247   void kill_thread(bool b,GIAC_CONTEXT){
1248     thread_param * ptr= (contextptr && contextptr->globalptr )?contextptr->globalptr->_thread_param_ptr:0;
1249     if (!ptr)
1250       ptr=context0_thread_param_ptr();
1251     ptr->_kill_thread=b;
1252   }
1253 
1254 
1255 #ifdef HAVE_LIBPTHREAD
1256   pthread_mutex_t _mutexptr = PTHREAD_MUTEX_INITIALIZER,_mutex_eval_status= PTHREAD_MUTEX_INITIALIZER;
mutexptr(GIAC_CONTEXT)1257   pthread_mutex_t * mutexptr(GIAC_CONTEXT){
1258     if (contextptr && contextptr->globalptr)
1259       return contextptr->globalptr->_mutexptr;
1260     return &_mutexptr;
1261   }
1262 
is_context_busy(GIAC_CONTEXT)1263   bool is_context_busy(GIAC_CONTEXT){
1264     int concurrent=pthread_mutex_trylock(mutexptr(contextptr));
1265     bool res=concurrent==EBUSY;
1266     if (!res)
1267       pthread_mutex_unlock(mutexptr(contextptr));
1268     return res;
1269   }
1270 
thread_eval_status(GIAC_CONTEXT)1271   int thread_eval_status(GIAC_CONTEXT){
1272     int res;
1273     if (contextptr && contextptr->globalptr){
1274       pthread_mutex_lock(contextptr->globalptr->_mutex_eval_status_ptr);
1275       res=contextptr->globalptr->_thread_param_ptr->thread_eval_status;
1276       pthread_mutex_unlock(contextptr->globalptr->_mutex_eval_status_ptr);
1277     }
1278     else {
1279       pthread_mutex_lock(&_mutex_eval_status);
1280       res=context0_thread_param_ptr()->thread_eval_status;
1281       pthread_mutex_unlock(&_mutex_eval_status);
1282     }
1283     return res;
1284   }
1285 
thread_eval_status(int val,GIAC_CONTEXT)1286   void thread_eval_status(int val,GIAC_CONTEXT){
1287     if (contextptr && contextptr->globalptr){
1288       pthread_mutex_lock(contextptr->globalptr->_mutex_eval_status_ptr);
1289       contextptr->globalptr->_thread_param_ptr->thread_eval_status=val;
1290       pthread_mutex_unlock(contextptr->globalptr->_mutex_eval_status_ptr);
1291     }
1292     else {
1293       pthread_mutex_lock(&_mutex_eval_status);
1294       context0_thread_param_ptr()->thread_eval_status=val;
1295       pthread_mutex_unlock(&_mutex_eval_status);
1296     }
1297   }
1298 
1299 #else
is_context_busy(GIAC_CONTEXT)1300   bool is_context_busy(GIAC_CONTEXT){
1301     return false;
1302   }
1303 
thread_eval_status(GIAC_CONTEXT)1304   int thread_eval_status(GIAC_CONTEXT){
1305     return -1;
1306   }
1307 
thread_eval_status(int val,GIAC_CONTEXT)1308   void thread_eval_status(int val,GIAC_CONTEXT){
1309   }
1310 
1311 #endif
1312 
1313   static int _eval_level=DEFAULT_EVAL_LEVEL;
eval_level(GIAC_CONTEXT)1314   int & eval_level(GIAC_CONTEXT){
1315     if (contextptr && contextptr->globalptr )
1316       return contextptr->globalptr->_eval_level;
1317     else
1318       return _eval_level;
1319   }
1320 
eval_level(int b,GIAC_CONTEXT)1321   void eval_level(int b,GIAC_CONTEXT){
1322     if (contextptr && contextptr->globalptr )
1323       contextptr->globalptr->_eval_level=b;
1324     else
1325       _eval_level=b;
1326   }
1327 
1328 #ifdef FXCG // defined(GIAC_HAS_STO_38) || defined(ConnectivityKit)
1329   static unsigned int _rand_seed=123457;
1330 #else
1331   static tinymt32_t _rand_seed;
1332 #endif
1333 
1334 #ifdef FXCG // defined(GIAC_HAS_STO_38) || defined(ConnectivityKit)
rand_seed(GIAC_CONTEXT)1335   unsigned int & rand_seed(GIAC_CONTEXT){
1336     if (contextptr && contextptr->globalptr )
1337       return contextptr->globalptr->_rand_seed;
1338     else
1339       return _rand_seed;
1340   }
1341 #else
rand_seed(GIAC_CONTEXT)1342   tinymt32_t * rand_seed(GIAC_CONTEXT){
1343     if (contextptr && contextptr->globalptr )
1344       return &contextptr->globalptr->_rand_seed;
1345     else
1346       return &_rand_seed;
1347   }
1348 #endif
1349 
rand_seed(unsigned int b,GIAC_CONTEXT)1350   void rand_seed(unsigned int b,GIAC_CONTEXT){
1351     if (contextptr && contextptr->globalptr )
1352       contextptr->globalptr->_rand_seed=b;
1353     else
1354       _rand_seed=b;
1355   }
1356 
std_rand()1357   int std_rand(){
1358 #if 1 // def NSPIRE
1359     static unsigned int r = 0;
1360     r = unsigned ((1664525*ulonglong(r)+1013904223)%(ulonglong(1)<<31));
1361     return r;
1362 #else
1363     return std::rand();
1364 #endif
1365   }
1366 
giac_rand(GIAC_CONTEXT)1367   int giac_rand(GIAC_CONTEXT){
1368 #ifdef FXCG // defined(GIAC_HAS_STO_38) || defined(ConnectivityKit)
1369     unsigned int & r = rand_seed(contextptr);
1370     // r = (2147483629*ulonglong(r)+ 2147483587)% 2147483647;
1371     r = unsigned ((1664525*ulonglong(r)+1013904223)%(ulonglong(1)<<31));
1372     return r;
1373 #else
1374     for (;;){
1375       unsigned r=tinymt32_generate_uint32(rand_seed(contextptr)) >> 1;
1376       if (!(r>>31))
1377 	return r;
1378     }
1379 #endif // tinymt32
1380   }
1381 
1382   static int _prog_eval_level_val=1;
prog_eval_level_val(GIAC_CONTEXT)1383   int & prog_eval_level_val(GIAC_CONTEXT){
1384     if (contextptr && contextptr->globalptr )
1385       return contextptr->globalptr->_prog_eval_level_val;
1386     else
1387       return _prog_eval_level_val;
1388   }
1389 
prog_eval_level_val(int b,GIAC_CONTEXT)1390   void prog_eval_level_val(int b,GIAC_CONTEXT){
1391     if (contextptr && contextptr->globalptr )
1392       contextptr->globalptr->_prog_eval_level_val=b;
1393     else
1394       _prog_eval_level_val=b;
1395   }
1396 
cleanup_context(GIAC_CONTEXT)1397   void cleanup_context(GIAC_CONTEXT){
1398     if (contextptr && contextptr->globalptr ){
1399       contextptr->globalptr->_eval_level=DEFAULT_EVAL_LEVEL;
1400     }
1401     eval_level(contextptr)=DEFAULT_EVAL_LEVEL;
1402     if (!contextptr)
1403       protection_level=0;
1404     local_eval(true,contextptr);
1405   }
1406 
1407 
_pl()1408   static parser_lexer & _pl(){
1409     static parser_lexer * ans = 0;
1410     if (!ans)
1411       ans=new parser_lexer();
1412     ans->_i_sqrt_minus1_=1;
1413     return * ans;
1414   }
lexer_column_number(GIAC_CONTEXT)1415   int & lexer_column_number(GIAC_CONTEXT){
1416     if (contextptr && contextptr->globalptr )
1417       return contextptr->globalptr->_pl._lexer_column_number_;
1418     else
1419       return _pl()._lexer_column_number_;
1420   }
lexer_line_number(GIAC_CONTEXT)1421   int & lexer_line_number(GIAC_CONTEXT){
1422     if (contextptr && contextptr->globalptr )
1423       return contextptr->globalptr->_pl._lexer_line_number_;
1424     else
1425       return _pl()._lexer_line_number_;
1426   }
lexer_line_number(int b,GIAC_CONTEXT)1427   void lexer_line_number(int b,GIAC_CONTEXT){
1428     if (contextptr && contextptr->globalptr )
1429       contextptr->globalptr->_pl._lexer_line_number_=b;
1430     else
1431       _pl()._lexer_line_number_=b;
1432   }
increment_lexer_line_number(GIAC_CONTEXT)1433   void increment_lexer_line_number(GIAC_CONTEXT){
1434     if (contextptr && contextptr->globalptr )
1435       ++contextptr->globalptr->_pl._lexer_line_number_;
1436     else
1437       ++_pl()._lexer_line_number_;
1438   }
1439 
index_status(GIAC_CONTEXT)1440   int & index_status(GIAC_CONTEXT){
1441     if (contextptr && contextptr->globalptr )
1442       return contextptr->globalptr->_pl._index_status_;
1443     else
1444       return _pl()._index_status_;
1445   }
index_status(int b,GIAC_CONTEXT)1446   void index_status(int b,GIAC_CONTEXT){
1447     if (contextptr && contextptr->globalptr )
1448       contextptr->globalptr->_pl._index_status_=b;
1449     else
1450       _pl()._index_status_=b;
1451   }
1452 
i_sqrt_minus1(GIAC_CONTEXT)1453   int & i_sqrt_minus1(GIAC_CONTEXT){
1454     if (contextptr && contextptr->globalptr )
1455       return contextptr->globalptr->_pl._i_sqrt_minus1_;
1456     else
1457       return _pl()._i_sqrt_minus1_;
1458   }
i_sqrt_minus1(int b,GIAC_CONTEXT)1459   void i_sqrt_minus1(int b,GIAC_CONTEXT){
1460     if (contextptr && contextptr->globalptr )
1461       contextptr->globalptr->_pl._i_sqrt_minus1_=b;
1462     else
1463       _pl()._i_sqrt_minus1_=b;
1464   }
1465 
opened_quote(GIAC_CONTEXT)1466   int & opened_quote(GIAC_CONTEXT){
1467     if (contextptr && contextptr->globalptr )
1468       return contextptr->globalptr->_pl._opened_quote_;
1469     else
1470       return _pl()._opened_quote_;
1471   }
opened_quote(int b,GIAC_CONTEXT)1472   void opened_quote(int b,GIAC_CONTEXT){
1473     if (contextptr && contextptr->globalptr )
1474       contextptr->globalptr->_pl._opened_quote_=b;
1475     else
1476       _pl()._opened_quote_=b;
1477   }
1478 
in_rpn(GIAC_CONTEXT)1479   int & in_rpn(GIAC_CONTEXT){
1480     if (contextptr && contextptr->globalptr )
1481       return contextptr->globalptr->_pl._in_rpn_;
1482     else
1483       return _pl()._in_rpn_;
1484   }
in_rpn(int b,GIAC_CONTEXT)1485   void in_rpn(int b,GIAC_CONTEXT){
1486     if (contextptr && contextptr->globalptr )
1487       contextptr->globalptr->_pl._in_rpn_=b;
1488     else
1489       _pl()._in_rpn_=b;
1490   }
1491 
spread_formula(GIAC_CONTEXT)1492   int & spread_formula(GIAC_CONTEXT){
1493     if (contextptr && contextptr->globalptr )
1494       return contextptr->globalptr->_pl._spread_formula_;
1495     else
1496       return _pl()._spread_formula_;
1497   }
spread_formula(int b,GIAC_CONTEXT)1498   void spread_formula(int b,GIAC_CONTEXT){
1499     if (contextptr && contextptr->globalptr )
1500       contextptr->globalptr->_pl._spread_formula_=b;
1501     else
1502       _pl()._spread_formula_=b;
1503   }
1504 
initialisation_done(GIAC_CONTEXT)1505   int & initialisation_done(GIAC_CONTEXT){
1506     if (contextptr && contextptr->globalptr )
1507       return contextptr->globalptr->_pl._initialisation_done_;
1508     else
1509       return _pl()._initialisation_done_;
1510   }
initialisation_done(int b,GIAC_CONTEXT)1511   void initialisation_done(int b,GIAC_CONTEXT){
1512     if (contextptr && contextptr->globalptr )
1513       contextptr->globalptr->_pl._initialisation_done_=b;
1514     else
1515       _pl()._initialisation_done_=b;
1516   }
1517 
1518   static int _calc_mode_=0;
calc_mode(GIAC_CONTEXT)1519   int & calc_mode(GIAC_CONTEXT){
1520     if (contextptr && contextptr->globalptr )
1521       return contextptr->globalptr->_calc_mode_;
1522     else
1523       return _calc_mode_;
1524   }
abs_calc_mode(GIAC_CONTEXT)1525   int abs_calc_mode(GIAC_CONTEXT){
1526     if (contextptr && contextptr->globalptr )
1527       return absint(contextptr->globalptr->_calc_mode_);
1528     else
1529       return absint(_calc_mode_);
1530   }
_autoname_()1531   static std::string & _autoname_(){
1532     static string * ans = 0;
1533     if (!ans){
1534 #ifdef GIAC_HAS_STO_38
1535       ans= new string("GA");
1536 #else
1537       ans = new string("A");
1538 #endif
1539     }
1540     return *ans;
1541   }
calc_mode(int b,GIAC_CONTEXT)1542   void calc_mode(int b,GIAC_CONTEXT){
1543     if ( (b==38 || b==-38) && strcmp(_autoname_().c_str(),"GA")<0)
1544       autoname("GA",contextptr);
1545     if (contextptr && contextptr->globalptr )
1546       contextptr->globalptr->_calc_mode_=b;
1547     else
1548       _calc_mode_=b;
1549   }
1550 
array_start(GIAC_CONTEXT)1551   int array_start(GIAC_CONTEXT){
1552     if (contextptr && contextptr->globalptr){
1553       bool hp38=absint(contextptr->globalptr->_calc_mode_)==38;
1554       return (!contextptr->globalptr->_python_compat_ && (contextptr->globalptr->_xcas_mode_ || hp38))?1:0;
1555     }
1556     return (!_python_compat_ && (_xcas_mode_ || absint(_calc_mode_)==38))?1:0;
1557   }
1558 
autoname(GIAC_CONTEXT)1559   std::string autoname(GIAC_CONTEXT){
1560     std::string res;
1561     if (contextptr && contextptr->globalptr )
1562       res=contextptr->globalptr->_autoname_;
1563     else
1564       res=_autoname_();
1565     for (;;){
1566       gen tmp(res,contextptr);
1567       if (tmp.type==_IDNT){
1568 	gen tmp1=eval(tmp,1,contextptr);
1569 	if (tmp==tmp1)
1570 	  break;
1571       }
1572       autoname_plus_plus(res);
1573     }
1574     return res;
1575   }
autoname(const std::string & s,GIAC_CONTEXT)1576   std::string autoname(const std::string & s,GIAC_CONTEXT){
1577     if (contextptr && contextptr->globalptr )
1578       contextptr->globalptr->_autoname_=s;
1579     else
1580       _autoname_()=s;
1581     return s;
1582   }
1583 
_autosimplify_()1584   static std::string & _autosimplify_(){
1585     static string * ans = 0;
1586     if (!ans)
1587       ans=new string("regroup");
1588     return *ans;
1589   }
autosimplify(GIAC_CONTEXT)1590   std::string autosimplify(GIAC_CONTEXT){
1591     std::string res;
1592     if (contextptr && contextptr->globalptr )
1593       res=contextptr->globalptr->_autosimplify_;
1594     else
1595       res=_autosimplify_();
1596     return res;
1597   }
autosimplify(const std::string & s,GIAC_CONTEXT)1598   std::string autosimplify(const std::string & s,GIAC_CONTEXT){
1599     if (contextptr && contextptr->globalptr )
1600       contextptr->globalptr->_autosimplify_=s;
1601     else
1602       _autosimplify_()=s;
1603     return s;
1604   }
1605 
_lastprog_name_()1606   static std::string & _lastprog_name_(){
1607     static string * ans = 0;
1608     if (!ans)
1609       ans=new string("lastprog");
1610     return *ans;
1611   }
lastprog_name(GIAC_CONTEXT)1612   std::string lastprog_name(GIAC_CONTEXT){
1613     std::string res;
1614     if (contextptr && contextptr->globalptr )
1615       res=contextptr->globalptr->_lastprog_name_;
1616     else
1617       res=_lastprog_name_();
1618     return res;
1619   }
lastprog_name(const std::string & s,GIAC_CONTEXT)1620   std::string lastprog_name(const std::string & s,GIAC_CONTEXT){
1621     if (contextptr && contextptr->globalptr )
1622       contextptr->globalptr->_lastprog_name_=s;
1623     else
1624       _lastprog_name_()=s;
1625     return s;
1626   }
1627 
_format_double_()1628   static std::string & _format_double_(){
1629     static string * ans = 0;
1630     if (!ans)
1631       ans=new string("");
1632     return * ans;
1633   }
format_double(GIAC_CONTEXT)1634   std::string & format_double(GIAC_CONTEXT){
1635     if (contextptr && contextptr->globalptr )
1636       return contextptr->globalptr->_format_double_;
1637     else
1638       return _format_double_();
1639   }
1640 
comment_s(GIAC_CONTEXT)1641   std::string comment_s(GIAC_CONTEXT){
1642     if (contextptr && contextptr->globalptr )
1643       return contextptr->globalptr->_pl._comment_s_;
1644     else
1645       return _pl()._comment_s_;
1646   }
comment_s(const std::string & b,GIAC_CONTEXT)1647   void comment_s(const std::string & b,GIAC_CONTEXT){
1648     if (contextptr && contextptr->globalptr )
1649       contextptr->globalptr->_pl._comment_s_=b;
1650     else
1651       _pl()._comment_s_=b;
1652   }
1653 
increment_comment_s(const std::string & b,GIAC_CONTEXT)1654   void increment_comment_s(const std::string & b,GIAC_CONTEXT){
1655     if (contextptr && contextptr->globalptr )
1656       contextptr->globalptr->_pl._comment_s_ += b;
1657     else
1658       _pl()._comment_s_ += b;
1659   }
1660 
increment_comment_s(char b,GIAC_CONTEXT)1661   void increment_comment_s(char b,GIAC_CONTEXT){
1662     if (contextptr && contextptr->globalptr )
1663       contextptr->globalptr->_pl._comment_s_ += b;
1664     else
1665       _pl()._comment_s_ += b;
1666   }
1667 
parser_filename(GIAC_CONTEXT)1668   std::string parser_filename(GIAC_CONTEXT){
1669     if (contextptr && contextptr->globalptr )
1670       return contextptr->globalptr->_pl._parser_filename_;
1671     else
1672       return _pl()._parser_filename_;
1673   }
parser_filename(const std::string & b,GIAC_CONTEXT)1674   void parser_filename(const std::string & b,GIAC_CONTEXT){
1675     if (contextptr && contextptr->globalptr )
1676       contextptr->globalptr->_pl._parser_filename_=b;
1677     else
1678       _pl()._parser_filename_=b;
1679   }
1680 
parser_error(GIAC_CONTEXT)1681   std::string parser_error(GIAC_CONTEXT){
1682     if (contextptr && contextptr->globalptr )
1683       return contextptr->globalptr->_pl._parser_error_;
1684     else
1685       return _pl()._parser_error_;
1686   }
parser_error(const std::string & b,GIAC_CONTEXT)1687   void parser_error(const std::string & b,GIAC_CONTEXT){
1688 #ifndef GIAC_HAS_STO_38
1689     if (!first_error_line(contextptr))
1690       alert(b,contextptr);
1691     else
1692       *logptr(contextptr) << b << '\n';
1693 #endif
1694     if (contextptr && contextptr->globalptr )
1695       contextptr->globalptr->_pl._parser_error_=b;
1696     else
1697       _pl()._parser_error_=b;
1698   }
1699 
error_token_name(GIAC_CONTEXT)1700   std::string error_token_name(GIAC_CONTEXT){
1701     if (contextptr && contextptr->globalptr )
1702       return contextptr->globalptr->_pl._error_token_name_;
1703     else
1704       return _pl()._error_token_name_;
1705   }
error_token_name(const std::string & b0,GIAC_CONTEXT)1706   void error_token_name(const std::string & b0,GIAC_CONTEXT){
1707     string b(b0);
1708     if (b0.size()==2 && b0[0]==-61 && b0[1]==-65)
1709       b="end of input";
1710     if (contextptr && contextptr->globalptr )
1711       contextptr->globalptr->_pl._error_token_name_=b;
1712     else
1713       _pl()._error_token_name_=b;
1714   }
1715 
first_error_line(GIAC_CONTEXT)1716   int & first_error_line(GIAC_CONTEXT){
1717     if (contextptr && contextptr->globalptr )
1718       return contextptr->globalptr->_pl._first_error_line_;
1719     else
1720       return _pl()._first_error_line_;
1721   }
first_error_line(int b,GIAC_CONTEXT)1722   void first_error_line(int b,GIAC_CONTEXT){
1723     if (contextptr && contextptr->globalptr )
1724       contextptr->globalptr->_pl._first_error_line_=b;
1725     else
1726       _pl()._first_error_line_=b;
1727   }
1728 
_parsed_gen_()1729   static gen & _parsed_gen_(){
1730     static gen * ans = 0;
1731     if (!ans)
1732       ans=new gen;
1733     return * ans;
1734   }
parsed_gen(GIAC_CONTEXT)1735   gen parsed_gen(GIAC_CONTEXT){
1736     if (contextptr && contextptr->globalptr )
1737       return *contextptr->globalptr->_parsed_genptr_;
1738     else
1739       return _parsed_gen_();
1740   }
parsed_gen(const gen & b,GIAC_CONTEXT)1741   void parsed_gen(const gen & b,GIAC_CONTEXT){
1742     if (contextptr && contextptr->globalptr )
1743       *contextptr->globalptr->_parsed_genptr_=b;
1744     else
1745       _parsed_gen_()=b;
1746   }
1747 
_turtle_()1748   static logo_turtle & _turtle_(){
1749     static logo_turtle * ans = 0;
1750     if (!ans)
1751       ans=new logo_turtle;
1752     return *ans;
1753   }
turtle(GIAC_CONTEXT)1754   logo_turtle & turtle(GIAC_CONTEXT){
1755     if (contextptr && contextptr->globalptr )
1756       return contextptr->globalptr->_turtle_;
1757     else
1758       return _turtle_();
1759   }
1760 
1761 #ifndef KHICAS
1762   // protect turtle access by a lock
1763   // turtle changes are mutually exclusive even in different contexts
1764 #ifdef HAVE_LIBPTHREAD
1765   pthread_mutex_t turtle_mutex = PTHREAD_MUTEX_INITIALIZER;
1766 #endif
_turtle_stack_()1767   std::vector<logo_turtle> & _turtle_stack_(){
1768     static std::vector<logo_turtle> * ans = 0;
1769     if (!ans)
1770       ans=new std::vector<logo_turtle>(1,_turtle_());
1771 #ifdef HAVE_LIBPTHREAD
1772     ans->reserve(20000);
1773 #endif
1774     return *ans;
1775   }
turtle_stack(GIAC_CONTEXT)1776   std::vector<logo_turtle> & turtle_stack(GIAC_CONTEXT){
1777 #ifdef HAVE_LIBPTHREAD
1778     pthread_mutex_lock(&turtle_mutex);
1779 #endif
1780     std::vector<logo_turtle> * ans=0;
1781     if (contextptr && contextptr->globalptr )
1782       ans=&contextptr->globalptr->_turtle_stack_;
1783     else
1784       ans=&_turtle_stack_();
1785 #ifdef HAVE_LIBPTHREAD
1786     pthread_mutex_unlock(&turtle_mutex);
1787 #endif
1788     return *ans;
1789   }
1790 #endif
1791 
1792   // Other global variables
1793 #ifdef NSPIRE
1794   bool secure_run=false;
1795 #else
1796   bool secure_run=true;
1797 #endif
1798   bool center_history=false;
1799   bool in_texmacs=false;
1800   bool block_signal=false;
1801   bool CAN_USE_LAPACK = true;
1802   bool simplify_sincosexp_pi=true;
1803   int history_begin_level=0;
1804   // variable used to avoid copying the whole history between processes
1805 #ifdef WIN32 // Temporary
1806   int debug_infolevel=0;
1807 #else
1808   int debug_infolevel=0;
1809 #endif
1810   int printprog=0;
1811 #if defined __APPLE__ || defined VISUALC || defined __MINGW_H || defined BESTA_OS || defined NSPIRE || defined FXCG || defined NSPIRE_NEWLIB || defined KHICAS
1812   int threads=1;
1813 #else
1814   int threads=sysconf (_SC_NPROCESSORS_ONLN);
1815 #endif
1816   unsigned max_pairs_by_iteration=32768;
1817   // gbasis max number of pairs by F4 iteration
1818   // setting to 2000 accelerates cyclic9mod but cyclic9 would be slower
1819   // 32768 is enough for cyclic10mod without truncation and not too large for yang1
1820   unsigned simult_primes=16,simult_primes2=16,simult_primes3=16,simult_primes_seuil2=-1,simult_primes_seuil3=-1;
1821   // gbasis modular algorithm on Q: simultaneous primes (more primes means more parallel threads but also more memory required)
1822   double gbasis_reinject_ratio=0.2;
1823   // gbasis modular algo on Q: if new basis element exceed this ratio, new elements are reinjected in the ideal generators for the remaining computations
1824   double gbasis_reinject_speed_ratio=1/6.;
1825   // gbasis modular algo on Q: new basis elements are reinjected if the 2nd run with learning CPU speed / 1st run without learning CPU speed is >=
1826   int gbasis_logz_age_sort=0,gbasis_stop=0;
1827   unsigned short int GIAC_PADIC=50;
1828   const char cas_suffixe[]=".cas";
1829 #if defined RTOS_THREADX || defined BESTA_OS || defined(KHICAS)
1830 #ifdef BESTA_OS
1831   int LIST_SIZE_LIMIT = 100000 ;
1832   int FACTORIAL_SIZE_LIMIT = 1000 ;
1833   int CALL_LAPACK = 1111;
1834 #else
1835   int LIST_SIZE_LIMIT = 1000 ;
1836   int FACTORIAL_SIZE_LIMIT = 254 ;
1837   int CALL_LAPACK = 1111;
1838 #endif
1839   int GAMMA_LIMIT = 100 ;
1840   int NEWTON_DEFAULT_ITERATION=40;
1841   int TEST_PROBAB_PRIME=25;
1842   int GCDHEU_MAXTRY=5;
1843   int GCDHEU_DEGREE=100;
1844   int DEFAULT_EVAL_LEVEL=5;
1845   int MODFACTOR_PRIMES =5;
1846   int NTL_MODGCD=1<<30; // default: ntl gcd disabled
1847   int NTL_RESULTANT=382;
1848   int NTL_XGCD=50;
1849   int HGCD=128;//16384;
1850   int HENSEL_QUADRATIC_POWER=25;
1851   int KARAMUL_SIZE=13;
1852   int INT_KARAMUL_SIZE=300;
1853   int FFTMUL_SIZE=100;
1854   int FFTMUL_INT_MAXBITS=1024;
1855   int MAX_ALG_EXT_ORDER_SIZE = 4;
1856   int MAX_COMMON_ALG_EXT_ORDER_SIZE = 16;
1857   int TRY_FU_UPRIME=5;
1858   int SOLVER_MAX_ITERATE=25;
1859   int MAX_PRINTABLE_ZINT=10000;
1860   int MAX_RECURSION_LEVEL=9;
1861   int GBASIS_DETERMINISTIC=20;
1862   int GBASISF4_MAX_TOTALDEG=1024;
1863   int GBASISF4_MAXITER=256;
1864   // int GBASISF4_BUCHBERGER=5;
1865   const int BUFFER_SIZE=512;
1866 #else
1867   int CALL_LAPACK=1111;
1868 #ifdef EMCC
1869   int LIST_SIZE_LIMIT = 10000000 ;
1870 #else
1871   int LIST_SIZE_LIMIT = 500000000 ;
1872 #endif
1873 #ifdef USE_GMP_REPLACEMENTS
1874   int FACTORIAL_SIZE_LIMIT = 10000 ;
1875 #else
1876   int FACTORIAL_SIZE_LIMIT = 10000000 ;
1877 #endif
1878   int GAMMA_LIMIT = 100 ;
1879   int NEWTON_DEFAULT_ITERATION=60;
1880   int TEST_PROBAB_PRIME=25;
1881   int GCDHEU_MAXTRY=5;
1882   int GCDHEU_DEGREE=100;
1883   int DEFAULT_EVAL_LEVEL=25;
1884   int MODFACTOR_PRIMES =5;
1885   int NTL_MODGCD=1<<30; // default: ntl gcd disabled
1886   int NTL_RESULTANT=382;
1887   int NTL_XGCD=50;
1888   int HGCD=128;//16384;
1889   int HENSEL_QUADRATIC_POWER=25;
1890   int KARAMUL_SIZE=13;
1891   int INT_KARAMUL_SIZE=300;
1892   int FFTMUL_SIZE=100;
1893   int FFTMUL_INT_MAXBITS=1024;
1894 #ifdef GIAC_GGB
1895   int MAX_ALG_EXT_ORDER_SIZE = 3;
1896 #else
1897   int MAX_ALG_EXT_ORDER_SIZE = 6;
1898 #endif
1899 #if defined EMCC || defined NO_TEMPLATE_MULTGCD || defined GIAC_HAS_STO_38
1900   int MAX_COMMON_ALG_EXT_ORDER_SIZE = 16;
1901 #else
1902   int MAX_COMMON_ALG_EXT_ORDER_SIZE = 64;
1903 #endif
1904   int TRY_FU_UPRIME=5;
1905   int SOLVER_MAX_ITERATE=25;
1906   int MAX_PRINTABLE_ZINT=1000000;
1907   int MAX_RECURSION_LEVEL=100;
1908   int GBASIS_DETERMINISTIC=50;
1909   int GBASISF4_MAX_TOTALDEG=16384;
1910   int GBASISF4_MAXITER=1024;
1911   // int GBASISF4_BUCHBERGER=5;
1912   const int BUFFER_SIZE=16384;
1913 #endif
1914   volatile bool ctrl_c=false,interrupted=false,kbd_interrupted=false;
1915 #ifdef GIAC_HAS_STO_38
1916   double powlog2float=1e4;
1917   int MPZ_MAXLOG2=8600; // max 2^8600 about 1K
1918 #else
1919   double powlog2float=1e8;
1920   int MPZ_MAXLOG2=80000000; // 100 millions bits
1921 #endif
1922 #ifdef HAVE_LIBNTL
1923   int PROOT_FACTOR_MAXDEG=300;
1924 #else
1925   int PROOT_FACTOR_MAXDEG=30;
1926 #endif
1927   int MODRESULTANT=20;
1928   int ABS_NBITS_EVALF=1000;
1929 
1930   // used by WIN32 for the path to the xcas directory
xcasroot()1931   string & xcasroot(){
1932     static string * ans=0;
1933     if (!ans)
1934       ans=new string;
1935     return * ans;
1936   }
xcasrc()1937   string & xcasrc(){
1938 #ifdef WIN32
1939     static string * ans=0;
1940     if (!ans) ans=new string("xcas.rc");
1941 #else
1942     static string * ans=0;
1943     if (!ans) ans=new string(".xcasrc");
1944 #endif
1945     return *ans;
1946   }
1947 
1948 #if defined HAVE_SIGNAL_H && !defined HAVE_NO_SIGNAL_H
1949   pid_t parent_id=getpid();
1950 #else
1951   pid_t parent_id=0;
1952 #endif
1953   pid_t child_id=0; // child process (to replace by a vector of childs?)
1954 
ctrl_c_signal_handler(int signum)1955   void ctrl_c_signal_handler(int signum){
1956     ctrl_c=true;
1957 #if !defined KHICAS && !defined NSPIRE_NEWLIB && !defined WIN32 && !defined BESTA_OS && !defined NSPIRE && !defined FXCG && !defined POCKETCAS
1958     if (child_id)
1959       kill(child_id,SIGINT);
1960 #endif
1961 #if defined HAVE_SIGNAL_H && !defined HAVE_NO_SIGNAL_H
1962     cerr << "Ctrl-C pressed (pid " << getpid() << ")" << '\n';
1963 #endif
1964   }
1965 #if !defined NSPIRE && !defined FXCG
catch_err(const std::runtime_error & error)1966   gen catch_err(const std::runtime_error & error){
1967     cerr << error.what() << '\n';
1968     debug_ptr(0)->sst_at_stack.clear();
1969     debug_ptr(0)->current_instruction_stack.clear();
1970     debug_ptr(0)->args_stack.clear();
1971     protection_level=0;
1972     debug_ptr(0)->debug_mode=false;
1973     return string2gen(string(error.what()),false);
1974   }
1975 #endif
1976 
1977 #if 0
1978   static vecteur subvect(const vecteur & v,int i){
1979     int s=v.size();
1980     if (i<0)
1981       i=-i;
1982     vecteur res(v);
1983     for (;s<i;++s)
1984       res.push_back(undef);
1985     return vecteur(res.begin(),res.begin()+i);
1986   }
1987 #endif
1988 
1989 #if defined HAVE_SIGNAL_H_OLD
1990   static bool running_file=false;
1991   static int run_modif_pos;
1992   bool synchronize_history=true;
1993   char buf[BUFFER_SIZE];
1994 
1995   // at the beginning the parent process calls make_child
1996   // this forks, the child process then waits for a SIGUSR1 from
1997   // the parent that indicate data to evaluate is ready in #cas_entree#
1998   // When finished the child kills the parent with SIGUSR1
1999   // The answer is in #cas_sortie#
2000   // Parent: child_busy is set to true during evaluation
2001   // and reset to false by SIGUSR1
2002   // Child uses signal_child for signal trapping and parent uses
2003   // data_ready
2004   // SIGUSR2 is used by the child process for intermediate data
2005   // [Typically a plot instruction]
2006   // The child kills the parent with SIGUSR2,
2007   // child_busy remains true but data ready is set
2008   // Then the child waits for a parent SIGUSR2 signal
2009   // signal_plot_parent is true for intermediate data, false otherwise
2010   volatile bool signal_child=true; // true if busy
2011   volatile bool signal_plot_child=false; // true if child can continue
2012   volatile bool signal_plot_parent=false;
2013   volatile bool child_busy=false,data_ready=false;
2014   // child sends a SIGUSR1
data_signal_handler(int signum)2015   void data_signal_handler(int signum){
2016           // cerr << "Parent called" << '\n';
2017     signal_plot_parent=false;
2018     child_busy=false;
2019     data_ready=true;
2020   }
2021 
2022   /*
2023   void control_c(){
2024     if (ctrl_c){
2025       ctrl_c=false;
2026       interrupted=true;
2027       cerr << "Throwing exception" << '\n';
2028       throw(std::runtime_error("Stopped by Ctrl-C"));
2029     }
2030   }
2031   */
2032 
2033   // child sends a SIGUSR2 (intermediate data)
plot_signal_handler(int signum)2034   void plot_signal_handler(int signum){
2035           // cerr << "Plot_signal_handler Parent called" << '\n';
2036     signal_plot_parent=true;
2037     child_busy=false;
2038     data_ready=true;
2039   }
2040 
child_signal_handler(int signum)2041   void child_signal_handler(int signum){
2042     // cerr << "Child called" << '\n';
2043     signal_child=true;
2044   }
2045 
child_plot_done(int signum)2046   void child_plot_done(int signum){
2047     signal_plot_child=true;
2048   }
2049 
kill_and_wait_sigusr2()2050   void kill_and_wait_sigusr2(){
2051     sigset_t mask, oldmask;
2052     sigemptyset (&mask);
2053     sigaddset (&mask, SIGUSR2);
2054     /* Wait for a signal to arrive. */
2055     sigprocmask (SIG_BLOCK, &mask, &oldmask);
2056     signal_plot_child=false;
2057 #ifndef WIN32
2058     kill(parent_id,SIGUSR2);
2059 #endif
2060     // cerr << "Child ready" << '\n';
2061 #ifndef WIN32
2062     while (!signal_plot_child)
2063       sigsuspend (&oldmask);
2064     sigprocmask (SIG_UNBLOCK, &mask, NULL);
2065 #endif
2066   }
2067 
wait_parent()2068   gen wait_parent(){
2069     kill_and_wait_sigusr2();
2070     ifstream child_in(cas_entree_name().c_str());
2071     gen res;
2072     try {
2073       res=unarchive(child_in,context0);
2074     }
2075     catch (std::runtime_error & e){
2076       res=string2gen(e.what(),false);
2077     }
2078     child_in.close();
2079     return res;
2080   }
2081 
make_child()2082   static pid_t make_child(){ // forks and return child id
2083 #if defined HAVE_NO_SIGNAL_H || defined(DONT_FORK)
2084 #ifdef DONT_FORK
2085 	  child_id = 1;
2086 	  return 1;
2087 #endif // DONT_FORK
2088 	return -1;
2089 #else // HAVE_NO_SIGNAL_H
2090     running_file=false;
2091     child_busy=false;
2092     ctrl_c=false;
2093     signal(SIGINT,ctrl_c_signal_handler);
2094     signal(SIGUSR1,data_signal_handler);
2095     signal(SIGUSR2,plot_signal_handler);
2096     if (child_id>(pid_t) 0)
2097       return child_id; // exists
2098     child_id=fork();
2099     if (child_id<(pid_t) 0)
2100       throw(std::runtime_error("Make_child error: Unable to fork"));
2101     if (!child_id){ // child process, redirect input/output
2102       sigset_t mask, oldmask;
2103       sigemptyset (&mask);
2104       sigaddset (&mask, SIGUSR1);
2105       signal(SIGUSR1,child_signal_handler);
2106       signal(SIGUSR2,child_plot_done);
2107       signal_child=false;
2108       gen args;
2109       /* Wait for a signal to arrive. */
2110       sigprocmask (SIG_BLOCK, &mask, &oldmask);
2111       signal_child=false;
2112       for (;;){
2113 	// cerr << "Child ready" << '\n';
2114 #ifndef WIN32
2115 	while (!signal_child)
2116 	  sigsuspend (&oldmask);
2117 	sigprocmask (SIG_UNBLOCK, &mask, NULL);
2118 #endif
2119 	// read and evaluate input
2120 	CLOCK_T start, end;
2121 	double elapsed;
2122 	start = CLOCK();
2123         messages_to_print="";
2124 	ifstream child_in(cas_entree_name().c_str());
2125 	// Unarchive step
2126 	try {
2127 	  child_in >> rpn_mode(context0) >> global_window_ymin >> history_begin_level ;
2128 	  // cerr << args << '\n';
2129 	  if (history_begin_level<0){
2130 	    child_in >> synchronize_history;
2131 	    args=unarchive(child_in,context0);
2132 	    if (!synchronize_history){
2133 	      // cerr << "No sync " << '\n';
2134 	      history_in(0)[-history_begin_level-1]=args;
2135 	      history_out(0)=subvect(history_out(0),-history_begin_level-1);
2136 	    }
2137 	    else {
2138 	      // cerr << " Sync " << '\n';
2139 	      history_in(0)=*args._VECTptr;
2140 	      args=unarchive(child_in,context0);
2141 	      history_out(0)=*args._VECTptr;
2142 	    }
2143 	  }
2144 	  else {
2145 	    args=unarchive(child_in,context0);
2146 	    // cerr << "Lu1 " << args << '\n';
2147 	    if (history_begin_level>signed(history_in(context0).size()))
2148 	      history_begin_level=history_in(context0).size();
2149 	    history_in(0)=mergevecteur(subvect(history_in(context0),history_begin_level),*args._VECTptr);
2150 	    args=unarchive(child_in,context0);
2151 	    // cerr << "Lu2 " << args << '\n';
2152 	    history_out(0)=mergevecteur(subvect(history_out(context0),history_begin_level),*args._VECTptr);
2153 	    args=unarchive(child_in,context0);
2154 	    // cerr << "Lu3 " << args << '\n';
2155 	    history_in(0).push_back(args);
2156 	  }
2157 	}
2158 	catch (std::runtime_error & error ){
2159 	  last_evaled_argptr(contextptr)=NULL;
2160 	  args = string2gen("Child unarchive error:"+string(error.what()),false);
2161 	}
2162 	child_in.close();
2163 	// cerr << args << '\n';
2164 	// output result of evaluation to child_out
2165 	gen args_evaled;
2166 	{ // BEGIN of old try block
2167 	  if (history_begin_level<0){
2168 	    history_begin_level=-history_begin_level-1;
2169 	    int s=history_in(context0).size();
2170 	    block_signal=true;
2171 	    for (int k=history_begin_level;k<s;++k){
2172 	      try {
2173                 if (history_in(context0)[k].is_symb_of_sommet(at_signal) || history_in(context0)[k].is_symb_of_sommet(at_debug))
2174 		  history_out(context0).push_back(eval(history_in(context0)[k]._SYMBptr->feuille,eval_level(context0),context0));
2175                 else
2176 		  history_out(context0).push_back(eval(history_in(context0)[k],eval_level(context0),context0));
2177 	      }
2178 	      catch (std::runtime_error & error){
2179 		last_evaled_argptr(contextptr)=NULL;
2180 		history_out(context0).push_back(catch_err(error));
2181 	      }
2182 	    }
2183 	    args=vecteur(history_in(context0).begin()+history_begin_level,history_in(context0).end());
2184 	    args_evaled=vecteur(history_out(context0).begin()+history_begin_level,history_out(context0).end());
2185 	  }
2186 	  else {
2187 	    if ( (args.type!=_VECT) || (args.subtype!=_RUNFILE__VECT) ){
2188 	      if (debug_infolevel>10)
2189 		cerr << "Child eval " << args << '\n';
2190 	      try {
2191 		args_evaled=args.eval(1,context0);
2192 	      }
2193 	      catch (std::runtime_error & error){
2194 		last_evaled_argptr(contextptr)=NULL;
2195 		args_evaled=catch_err(error);
2196 	      }
2197 	      history_out(context0).push_back(args_evaled);
2198 	      if (debug_infolevel>10)
2199 		cerr << "Child result " << args_evaled << '\n';
2200 	    }
2201 	    else {
2202 	      vecteur v;
2203 	      history_in(context0).pop_back();
2204 	      const_iterateur it=args._VECTptr->begin(),itend=args._VECTptr->end();
2205 	      for (;it!=itend;++it){
2206 		if (it->is_symb_of_sommet(at_signal) ||it->is_symb_of_sommet(at_debug) )
2207 		  continue;
2208 		history_in(context0).push_back(*it);
2209 		try {
2210 		  if (it->is_symb_of_sommet(at_debug))
2211 		    args_evaled=it->_SYMBptr->feuille.eval(1,context0);
2212 		  else
2213 		    args_evaled=it->eval(1,context0);
2214 		}
2215 		catch (std::runtime_error & error){
2216 		  last_evaled_argptr(contextptr)=NULL;
2217 		  args_evaled=catch_err(error);
2218 		}
2219 		// cerr << args_evaled << '\n';
2220 		history_out(context0).push_back(args_evaled);
2221 		v.push_back(args_evaled);
2222 		ofstream child_out(cas_sortie_name().c_str());
2223 		archive(child_out,*it,context0);
2224 		archive(child_out,args_evaled,context0);
2225 		child_out << messages_to_print << "ÿ" ;
2226 		child_out.close();
2227 		// cerr << "Signal reads " << res << '\n';
2228 		kill_and_wait_sigusr2();
2229 	      }
2230 	      // args_evaled=gen(v,args.subtype);
2231 	      args=0;
2232 	      args_evaled=0;
2233 	    }
2234 	  }
2235 	} // END of old try/catch block
2236 	block_signal=false;
2237 	end = CLOCK();
2238 	elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
2239 	ofstream child_out(cas_sortie_name().c_str());
2240 	archive(child_out,args,context0) ;
2241 	archive(child_out,args_evaled,context0) ;
2242 	child_out << messages_to_print ;
2243 	int mm=messages_to_print.size();
2244 	if (mm && (messages_to_print[mm-1]!='\n'))
2245 	  child_out << '\n';
2246 	child_out << "Time: " << elapsed << "ÿ" ;
2247 	child_out.close();
2248 	// cerr << "Child sending signal to " << parent_id << '\n';
2249 	/* Wait for a signal to arrive. */
2250 	sigprocmask (SIG_BLOCK, &mask, &oldmask);
2251 	signal_child=false;
2252 #ifndef WIN32
2253 	kill(parent_id,SIGUSR1);
2254 #endif
2255       }
2256     }
2257     // cerr << "Forking " << parent_id << " " << child_id << '\n';
2258     return child_id;
2259 #endif // HAVE_NO_SIGNAL_H
2260   }
2261 
archive_write_error()2262   static void archive_write_error(){
2263     cerr << "Archive error on " << cas_entree_name() << '\n';
2264   }
2265 
2266   // return true if entree has been sent to evalation by child process
child_eval(const string & entree,bool numeric,bool is_run_file)2267   static bool child_eval(const string & entree,bool numeric,bool is_run_file){
2268 #if defined(HAVE_NO_SIGNAL_H) || defined(DONT_FORK)
2269     return false;
2270 #else
2271     if (is_run_file || rpn_mode(context0))
2272       history_begin_level=0;
2273     // added signal re-mapping because PARI seems to mess signal on the ipaq
2274     signal(SIGUSR1,data_signal_handler);
2275     signal(SIGUSR2,plot_signal_handler);
2276     if (!child_id)
2277       child_id=make_child();
2278     if (child_busy || data_ready)
2279       return false;
2280     gen entr;
2281     CLOCK_T start, end;
2282     start = CLOCK();
2283     try {
2284       ofstream parent_out(cas_entree_name().c_str());
2285       if (!signal_plot_parent){
2286 	parent_out << rpn_mode(context0) << " " << global_window_ymin << " " << history_begin_level << '\n';
2287 	archive(parent_out,vecteur(history_in(context0).begin()+history_begin_level,history_in(context0).end()),context0);
2288 	archive(parent_out,vecteur(history_out(context0).begin()+history_begin_level,history_out(context0).end()),context0);
2289       }
2290       if (is_run_file){
2291 	ifstream infile(entree.c_str());
2292 	char c;
2293 	string s;
2294 	while (!infile.eof()){
2295 	  infile.get(c);
2296 	  s += c;
2297 	}
2298 	entr = gen(s,context0);
2299 	if (entr.type!=_VECT)
2300 	  entr=gen(makevecteur(entr),_RUNFILE__VECT);
2301 	else
2302 	  entr.subtype=_RUNFILE__VECT;
2303       }
2304       else {
2305 	entr = gen(entree,context0);
2306 	if (numeric)
2307 	  entr = symbolic(at_evalf,gen(entree,context0));
2308       }
2309       archive(parent_out,entr,context0);
2310       if (!parent_out)
2311 	setsizeerr();
2312       parent_out.close();
2313       if (!parent_out)
2314 	setsizeerr();
2315     } catch (std::runtime_error & e){
2316       last_evaled_argptr(contextptr)=NULL;
2317       archive_write_error();
2318       return false;
2319     }
2320     child_busy=true;
2321     if (signal_plot_parent){
2322       // cerr << "child_eval: Sending SIGUSR2 to child" << '\n';
2323       signal_plot_parent=false;
2324 #ifndef WIN32
2325       kill(child_id,SIGUSR2);
2326 #endif
2327       return true;
2328     }
2329     // cerr << "Sending SIGUSR1 to " << child_id << '\n';
2330 #ifndef WIN32
2331     kill(child_id,SIGUSR1);
2332 #endif
2333     running_file=is_run_file;
2334     end = CLOCK();
2335     // cerr << "# Save time" << double(end-start)/CLOCKS_PER_SEC << '\n';
2336     return true;
2337 #endif /// HAVE_NO_SIGNAL_H
2338   }
2339 
child_reeval(int history_begin_level)2340   static bool child_reeval(int history_begin_level){
2341 #if defined(HAVE_NO_SIGNAL_H) || defined(DONT_FORK)
2342     return false;
2343 #else
2344     signal(SIGUSR1,data_signal_handler);
2345     signal(SIGUSR2,plot_signal_handler);
2346     if (!child_id)
2347       child_id=make_child();
2348     if (child_busy || data_ready)
2349       return false;
2350     messages_to_print="";
2351     try {
2352       ofstream parent_out(cas_entree_name().c_str());
2353       parent_out << rpn_mode(context0) << " " << global_window_ymin << " " << -1-history_begin_level << " " << synchronize_history << '\n';
2354       if (synchronize_history){
2355 	archive(parent_out,history_in(context0),context0);
2356 	archive(parent_out,vecteur(history_out(context0).begin(),history_out(context0).begin()+history_begin_level),context0);
2357       }
2358       else
2359 	archive(parent_out,history_in(context0)[history_begin_level],context0);
2360       if (!parent_out)
2361 	setsizeerr();
2362       parent_out.close();
2363       if (!parent_out)
2364 	setsizeerr();
2365     } catch (std::runtime_error & e){
2366       last_evaled_argptr(contextptr)=NULL;
2367       archive_write_error();
2368       return false;
2369     }
2370     child_busy=true;
2371     running_file=true;
2372     // erase the part of the history that we are computing again
2373     if (run_modif_pos<signed(history_in(context0).size()))
2374       history_in(context0).erase(history_in(context0).begin()+run_modif_pos,history_in(context0).end());
2375     if (run_modif_pos<signed(history_out(context0).size()))
2376       history_out(context0).erase(history_out(context0).begin()+run_modif_pos,history_out(context0).end());
2377 #ifndef WIN32
2378     kill(child_id,SIGUSR1);
2379 #endif
2380     return true;
2381 #endif /// HAVE_NO_SIGNAL_H
2382   }
2383 
updatePICT(const vecteur & args)2384   static void updatePICT(const vecteur & args){
2385     const_iterateur it=args.begin(),itend=args.end();
2386     gen sortie;
2387     for (;it!=itend;++it){
2388       sortie=*it;
2389       if (sortie.type==_POINTER_ && sortie.subtype==_FL_WIDGET_POINTER && fl_widget_updatepict_function){
2390 	sortie = fl_widget_updatepict_function(sortie);
2391 	// cerr << "updatepict" << sortie << '\n';
2392       }
2393       if ( (sortie.type==_SYMB) && equalposcomp(plot_sommets,sortie._SYMBptr->sommet)){
2394 #ifdef WITH_GNUPLOT
2395 	plot_instructions.push_back(sortie);
2396 #endif
2397 	if ((sortie._SYMBptr->feuille.type==_VECT) && (sortie._SYMBptr->feuille._VECTptr->size()==3) && (sortie._SYMBptr->feuille._VECTptr->back().type==_STRNG) && ( ((*sortie._SYMBptr->feuille._VECTptr)[1].type==_VECT) || is_zero((*sortie._SYMBptr->feuille._VECTptr)[1])) ){
2398 	  string lab=*(sortie._SYMBptr->feuille._VECTptr->back()._STRNGptr);
2399 #ifdef WITH_GNUPLOT
2400 	  if (lab.size() && (lab>=PICTautoname)){
2401 	    PICTautoname=lab;
2402 	    PICTautoname_plus_plus();
2403 	  }
2404 #endif
2405 	}
2406       }
2407       else {
2408 	if ( ((sortie.type==_SYMB) && (sortie._SYMBptr->sommet==at_erase)) ||
2409              ((sortie.type==_FUNC) && (*sortie._FUNCptr==at_erase)) ){
2410 #ifdef WITH_GNUPLOT
2411 	  plot_instructions.clear();
2412 #endif
2413 	}
2414 	else {
2415 	  if ( (sortie.type==_VECT) && (sortie._VECTptr->size()) && (sortie._VECTptr->back().type==_SYMB) && (equalposcomp(plot_sommets,sortie._VECTptr->back()._SYMBptr->sommet))){
2416 #ifdef WITH_GNUPLOT
2417 	    plot_instructions.push_back(sortie);
2418 #endif
2419 	    sortie=sortie._VECTptr->back();
2420 	    if ((sortie._SYMBptr->feuille.type==_VECT) && (sortie._SYMBptr->feuille._VECTptr->size()==3) && (sortie._SYMBptr->feuille._VECTptr->back().type==_STRNG)  ){
2421 	      string lab=*(sortie._SYMBptr->feuille._VECTptr->back()._STRNGptr);
2422 #ifdef WITH_GNUPLOT
2423 	      if (lab.size() && (lab>=PICTautoname)){
2424 		PICTautoname=lab;
2425 		PICTautoname_plus_plus();
2426 	      }
2427 #endif
2428 	    }
2429 	  }
2430 	  else {
2431 #ifdef WITH_GNUPLOT
2432 	    plot_instructions.push_back(zero);
2433 #endif
2434 	  }
2435 	}
2436       }
2437     } // end for (;it!=itend;++it)
2438   }
2439 
signal_child_ok()2440   static void signal_child_ok(){
2441     child_busy=true;
2442     data_ready=false;
2443     signal_plot_parent=false;
2444 #ifndef WIN32
2445     kill(child_id,SIGUSR2);
2446 #endif // WIN32
2447   }
2448 
2449   static const unary_function_eval * parent_evalonly_sommets_alias[]={*(const unary_function_eval **) &at_widget_size,*(const unary_function_eval **) &at_keyboard,*(const unary_function_eval **) &at_current_sheet,*(const unary_function_eval **) &at_Row,*(const unary_function_eval **) &at_Col,0};
2450   static const unary_function_ptr & parent_evalonly_sommets=(const unary_function_ptr *) parent_evalonly_sommets_alias;
update_data(gen & entree,gen & sortie,GIAC_CONTEXT)2451   static bool update_data(gen & entree,gen & sortie,GIAC_CONTEXT){
2452     // if (entree.type==_IDNT)
2453     //   entree=symbolic(at_sto,makevecteur(sortie,entree));
2454     // discarded sto autoadd otherwise files with many definitions
2455     // are overwritten
2456     debug_ptr(contextptr)->debug_mode=false;
2457     if (signal_plot_parent){
2458       // cerr << "Child signaled " << entree << " " << sortie << '\n';
2459       if ( entree.type==_SYMB ){
2460 	if ( (entree._SYMBptr->sommet==at_click && entree._SYMBptr->feuille.type==_VECT && entree._SYMBptr->feuille._VECTptr->empty() )
2461 	     || (entree._SYMBptr->sommet==at_debug)
2462 	     ) {
2463 	  debug_ptr(contextptr)->debug_mode=(entree._SYMBptr->sommet==at_debug);
2464 	  // cerr << "Child waiting" << '\n';
2465 	  data_ready=false;
2466 	  *debug_ptr(contextptr)->debug_info_ptr=entree._SYMBptr->feuille;
2467 	  debug_ptr(contextptr)->debug_refresh=true;
2468 	  return true;
2469 	}
2470 	if ( entree._SYMBptr->sommet==at_click || entree._SYMBptr->sommet==at_inputform || entree._SYMBptr->sommet==at_interactive ){
2471 	  // cerr << entree << '\n';
2472 	  gen res=entree.eval(1,contextptr);
2473 	  // cerr << res << '\n';
2474 	  ofstream parent_out(cas_entree_name().c_str());
2475 	  archive(parent_out,res,contextptr);
2476 	  parent_out.close();
2477 	  signal_child_ok();
2478 	  return true;
2479 	}
2480 	// cerr << "Child signaled " << entree << " " << sortie << '\n';
2481       }
2482       if (sortie.type==_SYMB){
2483 	if (sortie._SYMBptr->sommet==at_SetFold){
2484 	  current_folder_name=sortie._SYMBptr->feuille;
2485 	  signal_child_ok();
2486 	  return false;
2487 	}
2488 	if (sortie._SYMBptr->sommet==at_sto && sortie._SYMBptr->feuille.type==_VECT){
2489 	  vecteur & v=*sortie._SYMBptr->feuille._VECTptr;
2490 	  // cerr << v << '\n';
2491 	  if ((v.size()==2) && (v[1].type==_IDNT)){
2492 	    if (v[1]._IDNTptr->value)
2493 	      delete v[1]._IDNTptr->value;
2494 	    v[1]._IDNTptr->value = new gen(v[0]);
2495 	  }
2496 	  signal_child_ok();
2497 	  return false;
2498 	}
2499 	if (sortie._SYMBptr->sommet==at_purge){
2500 	  gen & g=sortie._SYMBptr->feuille;
2501 	  if ((g.type==_IDNT) && (g._IDNTptr->value) ){
2502 	    delete g._IDNTptr->value;
2503 	    g._IDNTptr->value=0;
2504 	  }
2505 	  signal_child_ok();
2506 	  return false;
2507 	}
2508 	if ((sortie._SYMBptr->sommet==at_cd) && (sortie._SYMBptr->feuille.type==_STRNG)){
2509 #ifndef HAVE_NO_CWD
2510 	  chdir(sortie._SYMBptr->feuille._STRNGptr->c_str());
2511 #endif
2512 	  signal_child_ok();
2513 	  return false;
2514 	}
2515 	if ( sortie._SYMBptr->sommet==at_insmod || sortie._SYMBptr->sommet==at_rmmod || sortie._SYMBptr->sommet==at_user_operator ){
2516 	  protecteval(sortie,DEFAULT_EVAL_LEVEL,contextptr);
2517 	  signal_child_ok();
2518 	  return false;
2519 	}
2520 	if (sortie._SYMBptr->sommet==at_xyztrange){
2521 	  gen f=sortie._SYMBptr->feuille;
2522 	  if ( (f.type==_VECT) && (f._VECTptr->size()>=12)){
2523 	    protecteval(sortie,2,contextptr);
2524             signal_child_ok();
2525 	    return false;
2526 	  }
2527 	}
2528 	if (sortie._SYMBptr->sommet==at_cas_setup){
2529 	  gen f=sortie._SYMBptr->feuille;
2530 	  if ( (f.type==_VECT) && (f._VECTptr->size()>=7)){
2531 	    vecteur v=*f._VECTptr;
2532 	    cas_setup(v,contextptr);
2533             signal_child_ok();
2534 	    return false;
2535 	  }
2536 	}
2537       }
2538       if (entree.type==_SYMB && entree._SYMBptr->sommet==at_signal && sortie.type==_SYMB && equalposcomp(parent_evalonly_sommets,sortie._SYMBptr->sommet) ) {
2539 	gen res=sortie.eval(1,contextptr);
2540 	ofstream parent_out(cas_entree_name().c_str());
2541 	archive(parent_out,res,contextptr);
2542 	parent_out.close();
2543 	signal_child_ok();
2544 	return false;
2545       }
2546     } // end signal_plot_parent
2547     // cerr << "# Parse time" << double(end-start)/CLOCKS_PER_SEC << '\n';
2548     // see if it's a PICT update
2549     vecteur args;
2550     // update history
2551     if (rpn_mode(contextptr)) {
2552       if ((sortie.type==_VECT)&& (sortie.subtype==_RPN_STACK__VECT)){
2553 	history_out(contextptr)=*sortie._VECTptr;
2554 	history_in(contextptr)=vecteur(history_out(contextptr).size(),undef);
2555 	int i=erase_pos(contextptr);
2556 	args=vecteur(history_out(contextptr).begin()+i,history_out(contextptr).end());
2557 #ifdef WITH_GNUPLOT
2558 	plot_instructions.clear();
2559 #endif
2560       }
2561       else {
2562 	if (entree.type==_FUNC){
2563 	  int s=min(max(entree.subtype,0),(int)history_out(contextptr).size());
2564 	  vecteur v(s);
2565 	  for (int k=s-1;k>=0;--k){
2566 	    v[k]=history_out(contextptr).back();
2567 	    history_out(contextptr).pop_back();
2568 	    history_in(contextptr).pop_back();
2569 	  }
2570 	  entree=symbolic(*entree._FUNCptr,v);
2571 	}
2572 	history_in(contextptr).push_back(entree);
2573 	history_out(contextptr).push_back(sortie);
2574 	int i=erase_pos(contextptr);
2575 	args=vecteur(history_out(contextptr).begin()+i,history_out(contextptr).end());
2576 #ifdef WITH_GNUPLOT
2577 	plot_instructions.clear();
2578 #endif
2579       }
2580     }
2581     else {
2582       bool fait=false;
2583       if (running_file) {
2584 	if (entree.type==_VECT && sortie.type==_VECT) {
2585 	  history_in(contextptr)=mergevecteur(history_in(contextptr),*entree._VECTptr);
2586 	  history_out(contextptr)=mergevecteur(history_out(contextptr),*sortie._VECTptr);
2587 	  fait=true;
2588 	}
2589 	if (is_zero(entree) && is_zero(sortie))
2590 	  fait=true;
2591       }
2592       if (!fait){
2593 	if (in_texmacs){
2594 	  COUT << GIAC_DATA_BEGIN << "verbatim:";
2595 	  COUT << "ans(" << history_out(contextptr).size() << ") " << sortie << "\n";
2596 
2597 	  COUT << GIAC_DATA_BEGIN << "latex:$$ " << gen2tex(entree,contextptr) << "\\quad = \\quad " << gen2tex(sortie,contextptr) << "$$" << GIAC_DATA_END;
2598 	  COUT << "\n";
2599 	  COUT << GIAC_DATA_BEGIN << "channel:prompt" << GIAC_DATA_END;
2600           COUT << "quest(" << history_out(contextptr).size()+1 << ") ";
2601           COUT << GIAC_DATA_END;
2602           fflush (stdout);
2603 	}
2604 	history_in(contextptr).push_back(entree);
2605 	history_out(contextptr).push_back(sortie);
2606 	// for PICT update
2607 	args=vecteur(1,sortie);
2608       }
2609       if (running_file){
2610 	// for PICT update
2611 	int i=erase_pos(contextptr);
2612 	args=vecteur(history_out(contextptr).begin()+i,history_out(contextptr).end());
2613 	// CERR << "PICT clear" << '\n';
2614 #ifdef WITH_GNUPLOT
2615 	plot_instructions.clear();
2616 #endif
2617         //running_file=false;
2618       }
2619       // now do the update
2620     }
2621     updatePICT(args);
2622     data_ready=false;
2623     if (signal_plot_parent)
2624         signal_child_ok();
2625     return true;
2626   }
2627 
archive_read_error()2628   static void archive_read_error(){
2629     CERR << "Read error on " << cas_sortie_name() << '\n';
2630     data_ready=false;
2631 #ifndef WIN32
2632     if (child_id)
2633       kill(child_id,SIGKILL);
2634 #endif
2635     child_id=0;
2636   }
2637 
read_data(gen & entree,gen & sortie,string & message,GIAC_CONTEXT)2638   static bool read_data(gen & entree,gen & sortie,string & message,GIAC_CONTEXT){
2639     if (!data_ready)
2640       return false;
2641     message="";
2642     try {
2643       ifstream parent_in(cas_sortie_name().c_str());
2644       if (!parent_in)
2645 	setsizeerr();
2646       CLOCK_T start, end;
2647       start = CLOCK();
2648       entree=unarchive(parent_in,contextptr);
2649       sortie=unarchive(parent_in,contextptr);
2650       end = CLOCK();
2651       parent_in.getline(buf,BUFFER_SIZE,'¿');
2652       if (buf[0]=='\n')
2653 	message += (buf+1);
2654       else
2655 	message += buf;
2656       if (!parent_in)
2657 	setsizeerr();
2658     } catch (std::runtime_error & ){
2659       last_evaled_argptr(contextptr)=NULL;
2660       archive_read_error();
2661       return false;
2662     }
2663     return update_data(entree,sortie,contextptr);
2664   }
2665 #endif // HAVE_SIGNAL_H_OLD
2666 
home_directory()2667   string home_directory(){
2668     string s("/");
2669 #ifdef FXCG
2670     return s;
2671 #else
2672     if (getenv("GIAC_HOME"))
2673       s=getenv("GIAC_HOME");
2674     else {
2675       if (getenv("XCAS_HOME"))
2676 	s=getenv("XCAS_HOME");
2677     }
2678     if (!s.empty() && s[s.size()-1]!='/')
2679       s += '/';
2680     if (s.size()!=1)
2681       return s;
2682 #ifdef HAVE_NO_HOME_DIRECTORY
2683     return s;
2684 #else
2685     if (access("/etc/passwd",R_OK))
2686       return "";
2687     uid_t u=getuid();
2688     passwd * p=getpwuid(u);
2689     if (p) s=p->pw_dir;
2690     return s+"/";
2691 #endif
2692 #endif
2693   }
2694 
2695 #ifndef FXCG
cas_entree_name()2696   string cas_entree_name(){
2697     if (getenv("XCAS_TMP"))
2698       return getenv("XCAS_TMP")+("/#cas_entree#"+print_INT_(parent_id));
2699 #ifdef IPAQ
2700     return "/tmp/#cas_entree#"+print_INT_(parent_id);
2701 #else
2702     return home_directory()+"#cas_entree#"+print_INT_(parent_id);
2703 #endif
2704   }
2705 
cas_sortie_name()2706   string cas_sortie_name(){
2707     if (getenv("XCAS_TMP"))
2708       return getenv("XCAS_TMP")+("/#cas_sortie#"+print_INT_(parent_id));
2709 #ifdef IPAQ
2710     return "/tmp/#cas_sortie#"+print_INT_(parent_id);
2711 #else
2712     return home_directory()+"#cas_sortie#"+print_INT_(parent_id);
2713 #endif
2714   }
2715 #endif
2716 
read_config(const string & name,GIAC_CONTEXT,bool verbose)2717   void read_config(const string & name,GIAC_CONTEXT,bool verbose){
2718 #if !defined NSPIRE && !defined FXCG && !defined GIAC_HAS_STO_38
2719 #if !defined __MINGW_H
2720     if (access(name.c_str(),R_OK)) {
2721       if (verbose)
2722 	CERR << "// Unable to find config file " << name << '\n';
2723       return;
2724     }
2725 #endif
2726     ifstream inf(name.c_str());
2727     if (!inf)
2728       return;
2729     vecteur args;
2730     if (verbose)
2731       CERR << "// Reading config file " << name << '\n';
2732     readargs_from_stream(inf,args,contextptr);
2733     gen g(args);
2734     if (debug_infolevel || verbose)
2735       CERR << g << '\n';
2736     g.eval(1,contextptr);
2737     if (verbose){
2738       CERR << "// User configuration done" << '\n';
2739       CERR << "// Maximum number of parallel threads " << threads << '\n';
2740       CERR << "Threads allowed " << threads_allowed << '\n';
2741     }
2742     if (debug_infolevel){
2743 #ifdef HASH_MAP_NAMESPACE
2744       CERR << "Using hash_map_namespace"<< '\n';
2745 #endif
2746       CERR << "Mpz_class allowed " << mpzclass_allowed << '\n';
2747       // CERR << "Heap multiplication " << heap_mult << '\n';
2748     }
2749 #endif
2750   }
2751 
2752   // Unix: configuration is read from xcas.rc in the giac_aide_location dir
2753   // then from the user ~/.xcasrc
2754   // Win: configuration from $XCAS_ROOT/xcas.rc then from home_dir()+xcasrc
2755   // or if not available from current dir xcasrc
protected_read_config(GIAC_CONTEXT,bool verbose)2756   void protected_read_config(GIAC_CONTEXT,bool verbose){
2757 #ifndef NO_STDEXCEPT
2758     try {
2759 #endif
2760       string s;
2761 #ifdef WIN32
2762       s=home_directory();
2763 #ifdef GNUWINCE
2764 	  s = xcasroot();
2765 #else
2766       if (s.size()<2 && getenv("XCAS_ROOT")){
2767 	s=getenv("XCAS_ROOT");
2768 	if (debug_infolevel || verbose)
2769 	  CERR << "Found XCAS_ROOT " << s << '\n';
2770       }
2771 #endif // GNUWINCE
2772 #else
2773       s=giac_aide_location;
2774       s=s.substr(0,s.size()-8);
2775 #endif
2776       if (s.size())
2777 	read_config(s+"/xcas.rc",contextptr,verbose);
2778       s=home_directory();
2779       if (s.size()<2)
2780 	s="";
2781       read_config(s+xcasrc(),contextptr,verbose);
2782 #ifndef NO_STDEXCEPT
2783     }
2784     catch (std::runtime_error & e){
2785       last_evaled_argptr(contextptr)=NULL;
2786       CERR << "Error in config file " << xcasrc() << " " << e.what() << '\n';
2787     }
2788 #endif
2789   }
2790 
giac_aide_dir()2791   string giac_aide_dir(){
2792 #if defined __MINGW_H || defined NSPIRE || defined FXCG
2793     return xcasroot();
2794 #else
2795     if (!access((xcasroot()+"aide_cas").c_str(),R_OK)){
2796       return xcasroot();
2797     }
2798     if (getenv("XCAS_ROOT")){
2799       string s=getenv("XCAS_ROOT");
2800       return s;
2801     }
2802     if (xcasroot().size()>4 && xcasroot().substr(xcasroot().size()-4,4)=="bin/"){
2803       string s(xcasroot().substr(0,xcasroot().size()-4));
2804       s+="share/giac/";
2805       if (!access((s+"aide_cas").c_str(),R_OK)){
2806 	return s;
2807       }
2808     }
2809 #ifdef __APPLE__
2810     if (!access("/Applications/usr/share/giac/",R_OK))
2811       return "/Applications/usr/share/giac/";
2812     return "/Applications/usr/share/giac/";
2813 #endif
2814 #ifdef WIN32
2815     return "/cygdrive/c/xcas/";
2816 #endif
2817     string s(giac_aide_location); // ".../aide_cas"
2818     // test if aide_cas is there, if not test at xcasroot() return ""
2819     if (!access(s.c_str(),R_OK)){
2820       s=s.substr(0,s.size()-8);
2821       CERR << "// Giac share root-directory:" << s << '\n';
2822       return s;
2823     }
2824     return "";
2825 #endif // __MINGW_H
2826   }
2827 
absolute_path(const std::string & orig_file)2828   std::string absolute_path(const std::string & orig_file){
2829 #ifdef BESTA_OS
2830     // BP: FIXME
2831     return orig_file;
2832 #else
2833 #if (!defined WIN32) || (defined VISUALC)
2834     if (orig_file[0]=='/')
2835       return orig_file;
2836     else
2837       return giac_aide_dir()+orig_file;
2838 #else
2839 #if !defined GNUWINCE && !defined __MINGW_H
2840      string res=orig_file;
2841      const char *_epath;
2842      _epath = orig_file.c_str()  ;
2843      /* If we have a POSIX path list, convert to win32 path list */
2844      if (_epath != NULL && *_epath != 0
2845          && cygwin_posix_path_list_p (_epath)){
2846 #ifdef x86_64
2847        int s = cygwin_conv_path (CCP_POSIX_TO_WIN_A , _epath, NULL, 0);
2848        char * _win32path = (char *) malloc(s);
2849        cygwin_conv_path(CCP_POSIX_TO_WIN_A,_epath, _win32path,s);
2850        s=strlen(_win32path);
2851 #else
2852        char * _win32path = (char *) malloc
2853 	 (cygwin_posix_to_win32_path_list_buf_size (_epath));
2854        cygwin_posix_to_win32_path_list (_epath, _win32path);
2855        int s=strlen(_win32path);
2856 #endif
2857        res.clear();
2858        for (int i=0;i<s;++i){
2859 	 char ch=_win32path[i];
2860 	 if (ch=='\\' || ch==' ')
2861 	   res += '\\';
2862 	 res += ch;
2863        }
2864        free(_win32path);
2865      }
2866      return res;
2867 #else
2868     string file=orig_file,s;
2869     if (file[0]!='/'){
2870       file=giac_aide_dir()+file;
2871     }
2872     if (file.substr(0,10)=="/cygdrive/" || (file[0]!='/' && file[1]!=':')){
2873       string s1=xcasroot();
2874       if (file.substr(0,10)=="/cygdrive/")
2875 	s1=file[10]+(":"+file.substr(11,file.size()-11));
2876       else {
2877 	// remove /cygdrive/
2878 	if (s1.substr(0,10)=="/cygdrive/")
2879 	  s1=s1[10]+(":"+s1.substr(11,s1.size()-11));
2880 	else
2881 	  s1="c:/xcas/";
2882 	s1 += file;
2883       }
2884       string s2;
2885       int t=s1.size();
2886       for (int i=0;i<t;++i){
2887 	if (s1[i]=='/')
2888 	  s2+="\\\\";
2889 	else {
2890 	  if (s1[i]==' ')
2891 	    s2+='\\';
2892 	  s2+=s1[i];
2893 	}
2894       }
2895       return s2;
2896     }
2897 #endif // GNUWINCE
2898 #endif // WIN32
2899     return orig_file;
2900 #endif // BESTA_OS
2901   }
2902 
is_file_available(const char * ch)2903   bool is_file_available(const char * ch){
2904     if (!ch)
2905       return false;
2906 #if !defined __MINGW_H && !defined NSPIRE && !defined FXCG
2907     if (access(ch,R_OK))
2908       return false;
2909 #endif
2910     return true;
2911   }
2912 
file_not_available(const char * ch)2913   bool file_not_available(const char * ch){
2914     return !is_file_available(ch);
2915   }
2916 
add_slash(string & path)2917   static void add_slash(string & path){
2918     if (!path.empty() && path[path.size()-1]!='/')
2919       path += '/';
2920   }
2921 #ifdef FXCG
getenv(const char *)2922   const char * getenv(const char *){
2923     return "";
2924   }
2925 #endif
2926 
check_file_path(const string & s)2927   bool check_file_path(const string & s){
2928     int ss=int(s.size()),i;
2929     for (i=0;i<ss;++i){
2930       if (s[i]==' ')
2931 	break;
2932     }
2933     string name=s.substr(0,i);
2934 #ifdef FXCG
2935     const char ch[]="/";
2936 #else
2937     const char * ch=getenv("PATH");
2938 #endif
2939     if (!ch || name[0]=='/')
2940       return is_file_available(name.c_str());
2941     string path;
2942     int l=int(strlen(ch));
2943     for (i=0;i<l;++i){
2944       if (ch[i]==':'){
2945 	if (!path.empty()){
2946 	  add_slash(path);
2947 	  if (is_file_available((path+name).c_str()))
2948 	    return true;
2949 	}
2950 	path="";
2951       }
2952       else
2953 	path += ch[i];
2954     }
2955     add_slash(path);
2956     return path.empty()?false:is_file_available((path+name).c_str());
2957   }
2958 
browser_command(const string & orig_file)2959   string browser_command(const string & orig_file){
2960 #if defined __MINGW_H || defined NSPIRE || defined FXCG
2961     return "";
2962 #else
2963     string file=orig_file;
2964     string s;
2965     bool url=false;
2966     if (file.substr(0,4)=="http"){
2967       url=true;
2968       s="'"+file+"'";
2969     }
2970     else {
2971       if (file[0]!='/'){
2972 #ifdef WIN32
2973 	file=giac_aide_dir()+file;
2974 #else
2975 	s=giac_aide_dir();
2976 #endif
2977       }
2978       s="file:"+s+file;
2979     }
2980     if (debug_infolevel)
2981       CERR << s << '\n';
2982 #ifdef WIN32
2983     bool with_firefox=false;
2984     /*
2985     string firefox="/cygdrive/c/Program Files/Mozilla Firefox/firefox.exe";
2986     if (getenv("BROWSER")){
2987       string tmp=getenv("BROWSER");
2988       if (tmp=="firefox" || tmp=="mozilla"){
2989 	with_firefox=!access(firefox.c_str(),R_OK);
2990 	if (!with_firefox){
2991 	  firefox="/cygdrive/c/Program Files/mozilla.org/Mozilla/mozilla.exe";
2992 	  with_firefox=!access(firefox.c_str(),R_OK);
2993 	}
2994       }
2995     }
2996     */
2997     if (!url && (file.substr(0,10)=="/cygdrive/" || (file[0]!='/' && file[1]!=':')) ){
2998       string s1=xcasroot();
2999       if (file.substr(0,10)=="/cygdrive/")
3000 	s1=file[10]+(":"+file.substr(11,file.size()-11));
3001       else {
3002 	// remove /cygdrive/
3003 	if (s1.substr(0,10)=="/cygdrive/")
3004 	  s1=s1[10]+(":"+s1.substr(11,s1.size()-11));
3005 	else
3006 	  s1="c:/xcas/";
3007 	s1 += s.substr(5,s.size()-5);
3008       }
3009       CERR << "s1=" << s1 << '\n';
3010       string s2;
3011       if (with_firefox)
3012 	s2=s1;
3013       else {
3014 	int t=int(s1.size());
3015 	for (int i=0;i<t;++i){
3016 	  if (s1[i]=='/')
3017 	    s2+="\\";
3018 	  else
3019 	    s2+=s1[i];
3020 	}
3021       }
3022       CERR << "s2=" << s2 << '\n';
3023       s=s2;
3024       // s="file:"+s2;
3025       // s = s.substr(0,5)+"C:\\\\xcas\\\\"+s2;
3026     }
3027     // Remove # trailing part of URL
3028     int ss=int(s.size());
3029     for (--ss;ss>0;--ss){
3030       if (s[ss]=='#' || s[ss]=='.' || s[ss]=='/' )
3031 	break;
3032     }
3033     if (ss && s[ss]!='.')
3034       s=s.substr(0,ss);
3035     s=xcasroot()+"cygstart.exe '"+s+"' &";
3036     /*
3037     if (with_firefox){
3038       s="'"+firefox+"' '"+s+"' &";
3039     }
3040     else {
3041       if (getenv("BROWSER"))
3042 	s=getenv("BROWSER")+(" '"+s+"' &");
3043       else
3044 	s="'/cygdrive/c/Program Files/Internet Explorer/IEXPLORE.EXE' '"+s+"' &";
3045     }
3046     */
3047 #else
3048     string browser;
3049     if (getenv("BROWSER"))
3050       browser=getenv("BROWSER");
3051     else {
3052 #ifdef __APPLE__
3053       browser="open" ; // browser="/Applications/Safari.app/Contents/MacOS/Safari";
3054       // Remove file: that seems not supported by Safari
3055       if (!url)
3056 	s = s.substr(5,s.size()-5);
3057       // Remove # trailing part of URL
3058       int ss=s.size();
3059       for (--ss;ss>0;--ss){
3060 	if (s[ss]=='#' || s[ss]=='.' || s[ss]=='/' )
3061 	  break;
3062       }
3063       if (ss && s[ss]!='.')
3064 	s=s.substr(0,ss);
3065 #else
3066       browser="xdg-open";
3067       if (!access("/usr/bin/dillo",R_OK))
3068 	browser="dillo";
3069       if (!access("/usr/bin/chromium",R_OK))
3070 	browser="chromium";
3071       if (!access("/usr/bin/firefox",R_OK))
3072 	browser="firefox";
3073 #endif
3074     }
3075     // find binary name
3076     int bs=browser.size(),i;
3077     for (i=bs-1;i>=0;--i){
3078       if (browser[i]=='/')
3079 	break;
3080     }
3081     ++i;
3082     string browsersub=browser.substr(i,bs-i);
3083     if (s[0]!='\'') s='\''+s+'\'';
3084     if (browsersub=="mozilla" || browsersub=="mozilla-bin" || browsersub=="firefox" || browsersub=="chromium"){
3085       s="if ! "+browser+" -remote \"openurl("+s+")\" ; then "+browser+" "+s+" & fi &";
3086     }
3087     else
3088       s=browser+" "+s+" &";
3089 #endif
3090     //if (debug_infolevel)
3091       CERR << "// Running command:"+ s<<'\n';
3092     return s;
3093 #endif // __MINGW_H
3094   }
3095 
system_browser_command(const string & file)3096   bool system_browser_command(const string & file){
3097 #if defined BESTA_OS || defined POCKETCAS
3098     return false;
3099 #else
3100 #ifdef WIN32
3101     string res=file;
3102     if (file.size()>4 && file.substr(0,4)!="http" && file.substr(0,4)!="file"){
3103       if (res[0]!='/')
3104 	res=giac_aide_dir()+res;
3105       // Remove # trailing part of URL
3106       int ss=int(res.size());
3107       for (--ss;ss>0;--ss){
3108 	if (res[ss]=='#' || res[ss]=='.' || res[ss]=='/' )
3109 	  break;
3110       }
3111       if (ss && res[ss]!='.')
3112 	res=res.substr(0,ss);
3113       CERR << res << '\n';
3114 #if !defined VISUALC && !defined __MINGW_H && !defined NSPIRE && !defined FXCG
3115       /* If we have a POSIX path list, convert to win32 path list */
3116       const char *_epath;
3117       _epath = res.c_str()  ;
3118       if (_epath != NULL && *_epath != 0
3119 	  && cygwin_posix_path_list_p (_epath)){
3120 #ifdef x86_64
3121 	int s = cygwin_conv_path (CCP_POSIX_TO_WIN_A , _epath, NULL, 0);
3122 	char * _win32path = (char *) malloc(s);
3123 	cygwin_conv_path(CCP_POSIX_TO_WIN_A,_epath, _win32path,s);
3124 #else
3125 	char * _win32path = (char *) malloc (cygwin_posix_to_win32_path_list_buf_size (_epath));
3126 	cygwin_posix_to_win32_path_list (_epath, _win32path);
3127 #endif
3128 	res = _win32path;
3129 	free(_win32path);
3130       }
3131 #endif
3132     }
3133     CERR << res << '\n';
3134 #if !defined VISUALC && !defined __MINGW_H && !defined NSPIRE && !defined FXCG
3135     // FIXME: works under visualc but not using /UNICODE flag
3136     // find correct flag
3137     ShellExecute(NULL,NULL,res.c_str(),NULL,NULL,1);
3138 #endif
3139     return true;
3140 #else
3141 #ifdef BESTA_OS
3142     return false; // return 1;
3143 #else
3144     return !system_no_deprecation(browser_command(file).c_str());
3145 #endif
3146 #endif
3147 #endif
3148   }
3149 
remove_multiples(vecteur & ww)3150   vecteur remove_multiples(vecteur & ww){
3151     vecteur w;
3152     if (!ww.empty()){
3153       islesscomplexthanf_sort(ww.begin(),ww.end());
3154       gen prec=ww[0];
3155       for (unsigned i=1;i<ww.size();++i){
3156 	if (ww[i]==prec)
3157 	  continue;
3158 	w.push_back(prec);
3159 	prec=ww[i];
3160       }
3161       w.push_back(prec);
3162     }
3163     return w;
3164   }
3165 
equalposcomp(const vector<int> v,int i)3166   int equalposcomp(const vector<int> v,int i){
3167     vector<int>::const_iterator it=v.begin(),itend=v.end();
3168     for (;it!=itend;++it)
3169       if (*it==i)
3170 	return int(it-v.begin())+1;
3171     return 0;
3172   }
3173 
equalposcomp(const vector<short int> v,int i)3174   int equalposcomp(const vector<short int> v,int i){
3175     vector<short int>::const_iterator it=v.begin(),itend=v.end();
3176     for (;it!=itend;++it)
3177       if (*it==i)
3178 	return int(it-v.begin())+1;
3179     return 0;
3180   }
3181 
equalposcomp(int tab[],int f)3182   int equalposcomp(int tab[],int f){
3183     for (int i=1;*tab!=0;++tab,++i){
3184       if (*tab==f)
3185 	return i;
3186     }
3187     return 0;
3188   }
3189 
find_lang_prefix(int i)3190   std::string find_lang_prefix(int i){
3191     switch (i){
3192     case 1:
3193       return "fr/";
3194     case 2:
3195       return "en/";
3196     case 3:
3197       return "es/";
3198     case 4:
3199       return "el/";
3200     case 9:
3201       return "pt/";
3202     case 6:
3203       return "it/";
3204       /*
3205     case 7:
3206       return "tr/";
3207       break;
3208       */
3209     case 8:
3210       return "zh/";
3211     case 5:
3212       return "de/";
3213       break;
3214     default:
3215       return "local/";
3216     }
3217   }
3218 
find_doc_prefix(int i)3219   std::string find_doc_prefix(int i){
3220     switch (i){
3221     case 1:
3222       return "doc/fr/";
3223       break;
3224     case 2:
3225       return "doc/en/";
3226       break;
3227     case 3:
3228       return "doc/es/";
3229       break;
3230     case 4:
3231       return "doc/el/";
3232       break;
3233     case 9:
3234       return "doc/pt/";
3235       break;
3236     case 6:
3237       return "doc/it/";
3238       break;
3239       /*
3240     case 7:
3241       return "doc/tr/";
3242       break;
3243       */
3244     case 8:
3245       return "doc/zh/";
3246       break;
3247     case 5:
3248       return "doc/de/";
3249       break;
3250     default:
3251       return "doc/local/";
3252     }
3253   }
3254 
update_completions()3255   void update_completions(){
3256     if (vector_completions_ptr()){
3257       vector_completions_ptr()->clear();
3258       int n=int(vector_aide_ptr()->size());
3259       for (int k=0;k<n;++k){
3260 	if (debug_infolevel>10)
3261 	  CERR << "+ " << (*vector_aide_ptr())[k].cmd_name  << '\n';
3262 	vector_completions_ptr()->push_back((*vector_aide_ptr())[k].cmd_name);
3263       }
3264     }
3265   }
3266 
add_language(int i,GIAC_CONTEXT)3267   void add_language(int i,GIAC_CONTEXT){
3268 #ifdef FXCG
3269     return;
3270 #else
3271     if (!equalposcomp(lexer_localization_vector(),i)){
3272       lexer_localization_vector().push_back(i);
3273       update_lexer_localization(lexer_localization_vector(),lexer_localization_map(),back_lexer_localization_map(),contextptr);
3274 #ifndef EMCC
3275       if (vector_aide_ptr()){
3276 	// add locale command description
3277 	int count;
3278 	string filename=giac_aide_dir()+find_doc_prefix(i)+"aide_cas";
3279 	readhelp(*vector_aide_ptr(),filename.c_str(),count,true);
3280 	// add synonyms
3281 	multimap<string,localized_string>::iterator it,backend=back_lexer_localization_map().end(),itend;
3282 	vector<aide>::iterator jt = vector_aide_ptr()->begin(),jtend=vector_aide_ptr()->end();
3283 	for (;jt!=jtend;++jt){
3284 	  it=back_lexer_localization_map().find(jt->cmd_name);
3285 	  itend=back_lexer_localization_map().upper_bound(jt->cmd_name);
3286 	  if (it!=backend){
3287 	    for (;it!=itend;++it){
3288 	      if (it->second.language==i)
3289 		jt->synonymes.push_back(it->second);
3290 	    }
3291 	  }
3292 	}
3293 	int s = int(vector_aide_ptr()->size());
3294 	for (int j=0;j<s;++j){
3295 	  aide a=(*vector_aide_ptr())[j];
3296 	  it=back_lexer_localization_map().find(a.cmd_name);
3297 	  itend=back_lexer_localization_map().upper_bound(a.cmd_name);
3298 	  if (it!=backend){
3299 	    for (;it!=itend;++it){
3300 	      if (it->second.language==i){
3301 		a.cmd_name=it->second.chaine;
3302 		a.language=it->second.language;
3303 		vector_aide_ptr()->push_back(a);
3304 	      }
3305 	    }
3306 	  }
3307 	}
3308 	CERR << "Added " << vector_aide_ptr()->size()-s << " synonyms" << '\n';
3309 	sort(vector_aide_ptr()->begin(),vector_aide_ptr()->end(),alpha_order);
3310 	update_completions();
3311       }
3312 #endif
3313     }
3314 #endif // FXCG
3315   }
3316 
remove_language(int i,GIAC_CONTEXT)3317   void remove_language(int i,GIAC_CONTEXT){
3318 #ifdef FXCG
3319     return;
3320 #else
3321     if (int pos=equalposcomp(lexer_localization_vector(),i)){
3322       if (vector_aide_ptr()){
3323 	vector<aide> nv;
3324 	int s=int(vector_aide_ptr()->size());
3325 	for (int j=0;j<s;++j){
3326 	  if ((*vector_aide_ptr())[j].language!=i)
3327 	    nv.push_back((*vector_aide_ptr())[j]);
3328 	}
3329 	*vector_aide_ptr() = nv;
3330 	update_completions();
3331 	vector<aide>::iterator jt = vector_aide_ptr()->begin(),jtend=vector_aide_ptr()->end();
3332 	for (;jt!=jtend;++jt){
3333 	  vector<localized_string> syno;
3334 	  vector<localized_string>::const_iterator kt=jt->synonymes.begin(),ktend=jt->synonymes.end();
3335 	  for (;kt!=ktend;++kt){
3336 	    if (kt->language!=i)
3337 	      syno.push_back(*kt);
3338 	  }
3339 	  jt->synonymes=syno;
3340 	}
3341       }
3342       --pos;
3343       lexer_localization_vector().erase(lexer_localization_vector().begin()+pos);
3344       update_lexer_localization(lexer_localization_vector(), lexer_localization_map(), back_lexer_localization_map(), contextptr);
3345 	}
3346 #endif
3347   }
3348 
string2lang(const string & s)3349   int string2lang(const string & s){
3350     if (s=="fr")
3351       return 1;
3352     if (s=="en")
3353       return 2;
3354     if (s=="sp" || s=="es")
3355       return 3;
3356     if (s=="el")
3357       return 4;
3358     if (s=="pt")
3359       return 9;
3360     if (s=="it")
3361       return 6;
3362     if (s=="tr")
3363       return 7;
3364     if (s=="zh")
3365       return 8;
3366     if (s=="de")
3367       return 5;
3368     return 0;
3369   }
3370 
set_language(int i,GIAC_CONTEXT)3371   std::string set_language(int i,GIAC_CONTEXT){
3372 #ifdef EMCC
3373     if (language(contextptr)!=i){
3374       language(i,contextptr);
3375       add_language(i,contextptr);
3376     }
3377 #else
3378     language(i,contextptr);
3379     add_language(i,contextptr);
3380 #endif
3381 #ifdef KHICAS
3382     lang=i;
3383 #endif
3384     return find_doc_prefix(i);
3385   }
3386 
read_env(GIAC_CONTEXT,bool verbose)3387   std::string read_env(GIAC_CONTEXT,bool verbose){
3388 #ifndef RTOS_THREADX
3389 #ifndef BESTA_OS
3390     if (getenv("GIAC_LAPACK")){
3391       CALL_LAPACK=atoi(getenv("GIAC_LAPACK"));
3392       if (verbose)
3393 	CERR << "// Will call lapack if dimension is >=" << CALL_LAPACK << '\n';
3394     }
3395     if (getenv("GIAC_PADIC")){
3396       GIAC_PADIC=atoi(getenv("GIAC_PADIC"));
3397       if (verbose)
3398 	CERR << "// Will use p-adic algorithm if dimension is >=" << GIAC_PADIC << '\n';
3399     }
3400 #endif
3401 #endif
3402     if (getenv("XCAS_RPN")){
3403       if (verbose)
3404 	CERR << "// Setting RPN mode" << '\n';
3405       rpn_mode(contextptr)=true;
3406     }
3407     if (getenv("GIAC_XCAS_MODE")){
3408       xcas_mode(contextptr)=atoi(getenv("GIAC_XCAS_MODE"));
3409       if (verbose)
3410 	CERR << "// Setting maple mode " << xcas_mode(contextptr) << '\n';
3411     }
3412     if (getenv("GIAC_C")){
3413       xcas_mode(contextptr)=0;
3414       if (verbose)
3415 	CERR << "// Setting giac C mode" << '\n';
3416     }
3417     if (getenv("GIAC_MAPLE")){
3418       xcas_mode(contextptr)=1;
3419       if (verbose)
3420 	CERR << "// Setting giac maple mode" << '\n';
3421     }
3422     if (getenv("GIAC_MUPAD")){
3423       xcas_mode(contextptr)=2;
3424       if (verbose)
3425 	CERR << "// Setting giac mupad mode" << '\n';
3426     }
3427     if (getenv("GIAC_TI")){
3428       xcas_mode(contextptr)=3;
3429       if (verbose)
3430 	CERR << "// Setting giac TI mode" << '\n';
3431     }
3432     if (getenv("GIAC_MONO")){
3433       if (verbose)
3434 	CERR << "// Threads polynomial * disabled" << '\n';
3435       threads_allowed=false;
3436     }
3437     if (getenv("GIAC_MPZCLASS")){
3438       if (verbose)
3439 	CERR << "// mpz_class enabled" << '\n';
3440       mpzclass_allowed=true;
3441     }
3442     if (getenv("GIAC_DEBUG")){
3443       debug_infolevel=atoi(getenv("GIAC_DEBUG"));
3444       CERR << "// Setting debug_infolevel to " << debug_infolevel << '\n';
3445     }
3446     if (getenv("GIAC_PRINTPROG")){
3447       // force print of prog at parse, 256 for python compat mode print
3448       printprog=atoi(getenv("GIAC_PRINTPROG"));
3449       CERR << "// Setting printprog to " << printprog << '\n';
3450     }
3451     string s;
3452     if (getenv("LANG"))
3453       s=getenv("LANG");
3454     else { // __APPLE__ workaround
3455 #if !defined VISUALC && !defined __MINGW_H && !defined NSPIRE && !defined FXCG
3456       if (!strcmp(gettext("File"),"Fich")){
3457 	setenv("LANG","fr_FR.UTF8",1);
3458 	s="fr_FR.UTF8";
3459       }
3460       else {
3461 	s="en_US.UTF8";
3462 	setenv("LANG",s.c_str(),1);
3463       }
3464 #endif
3465     }
3466     if (s.size()>=2){
3467       s=s.substr(0,2);
3468       int i=string2lang(s);
3469       if (i){
3470 	language(i,contextptr);
3471 	return find_doc_prefix(i);
3472       }
3473     }
3474     language(0,contextptr);
3475     return find_doc_prefix(0);
3476   }
3477 
cas_setup_string(GIAC_CONTEXT)3478   string cas_setup_string(GIAC_CONTEXT){
3479     string s("cas_setup(");
3480     s += print_VECT(cas_setup(contextptr),_SEQ__VECT,contextptr);
3481     s += "),";
3482     s += "xcas_mode(";
3483     s += print_INT_(xcas_mode(contextptr)+python_compat(contextptr)*256);
3484     s += ")";
3485     return s;
3486   }
3487 
geo_setup_string()3488   string geo_setup_string(){
3489     return xyztrange(gnuplot_xmin,gnuplot_xmax,gnuplot_ymin,gnuplot_ymax,gnuplot_zmin,gnuplot_zmax,gnuplot_tmin,gnuplot_tmax,global_window_xmin,global_window_xmax,global_window_ymin,global_window_ymax,_show_axes_,class_minimum,class_size,
3490 #ifdef WITH_GNUPLOT
3491 		     gnuplot_hidden3d,gnuplot_pm3d
3492 #else
3493 		     1,1
3494 #endif
3495 		     ).print(context0);
3496   }
3497 
add_extension(const string & s,const string & ext,const string & def)3498   string add_extension(const string & s,const string & ext,const string & def){
3499     if (s.empty())
3500       return def+"."+ext;
3501     int i=int(s.size());
3502     for (--i;i>0;--i){
3503       if (s[i]=='.')
3504 	break;
3505     }
3506     if (i<=0)
3507       return s+"."+ext;
3508     return s.substr(0,i)+"."+ext;
3509   }
3510 
3511 #ifdef HAVE_LIBPTHREAD
3512   pthread_mutex_t context_list_mutex = PTHREAD_MUTEX_INITIALIZER;
3513 #endif
3514 
context_list()3515   vector<context *> & context_list(){
3516     static vector<context *> * ans=0;
3517     if (!ans) ans=new vector<context *>(1,(context *) 0);
3518     return *ans;
3519   }
context()3520   context::context() {
3521     // CERR << "new context " << this << '\n';
3522     parent=0;
3523     tabptr=new sym_tab;
3524     globalcontextptr=this; previous=0; globalptr=new global;
3525     quoted_global_vars=new vecteur;
3526     rootofs=new vecteur;
3527     history_in_ptr=new vecteur;
3528     history_out_ptr=new vecteur;
3529     history_plot_ptr=new vecteur;
3530 #ifdef HAVE_LIBPTHREAD
3531     pthread_mutex_lock(&context_list_mutex);
3532 #endif
3533     context_list().push_back(this);
3534 #ifdef HAVE_LIBPTHREAD
3535     pthread_mutex_unlock(&context_list_mutex);
3536 #endif
3537   }
3538 
3539 #ifndef RTOS_THREADX
3540 #if !defined BESTA_OS && !defined NSPIRE && !defined FXCG && !defined(KHICAS)
3541   std::map<std::string,context *> * context_names = new std::map<std::string,context *> ;
3542 
context(const string & name)3543   context::context(const string & name) {
3544     // CERR << "new context " << this << '\n';
3545     parent=0;
3546     tabptr=new sym_tab;
3547     globalcontextptr=this; previous=0; globalptr=new global;
3548     quoted_global_vars=new vecteur;
3549     rootofs=new vecteur;
3550     history_in_ptr=new vecteur;
3551     history_out_ptr=new vecteur;
3552     history_plot_ptr=new vecteur;
3553 #ifdef HAVE_LIBPTHREAD
3554     pthread_mutex_lock(&context_list_mutex);
3555 #endif
3556     context_list().push_back(this);
3557     if (context_names)
3558       (*context_names)[name]=this;
3559 #ifdef HAVE_LIBPTHREAD
3560     pthread_mutex_unlock(&context_list_mutex);
3561 #endif
3562   }
3563 #endif
3564 #endif
3565 
context(const context & c)3566   context::context(const context & c) {
3567     *this = c;
3568   }
3569 
clone() const3570   context * context::clone() const{
3571     context * ptr = new context;
3572     *ptr->globalptr = *globalptr;
3573     return ptr;
3574   }
3575 
init_context(context * ptr)3576   void init_context(context * ptr){
3577     if (!ptr){
3578       CERR << "init_context on null context" << '\n';
3579       return;
3580     }
3581      ptr->globalptr->_xcas_mode_=_xcas_mode_;
3582 #ifdef GIAC_HAS_STO_38
3583      ptr->globalptr->_calc_mode_=-38;
3584 #else
3585      ptr->globalptr->_calc_mode_=_calc_mode_;
3586 #endif
3587      ptr->globalptr->_decimal_digits_=_decimal_digits_;
3588      ptr->globalptr->_minchar_for_quote_as_string_=_minchar_for_quote_as_string_;
3589      ptr->globalptr->_scientific_format_=_scientific_format_;
3590      ptr->globalptr->_integer_format_=_integer_format_;
3591      ptr->globalptr->_integer_mode_=_integer_mode_;
3592      ptr->globalptr->_latex_format_=_latex_format_;
3593 #ifdef BCD
3594      ptr->globalptr->_bcd_decpoint_=_bcd_decpoint_;
3595      ptr->globalptr->_bcd_mantissa_=_bcd_mantissa_;
3596      ptr->globalptr->_bcd_flags_=_bcd_flags_;
3597      ptr->globalptr->_bcd_printdouble_=_bcd_printdouble_;
3598 #endif
3599      ptr->globalptr->_expand_re_im_=_expand_re_im_;
3600      ptr->globalptr->_do_lnabs_=_do_lnabs_;
3601      ptr->globalptr->_eval_abs_=_eval_abs_;
3602      ptr->globalptr->_eval_equaltosto_=_eval_equaltosto_;
3603      ptr->globalptr->_complex_mode_=_complex_mode_;
3604      ptr->globalptr->_escape_real_=_escape_real_;
3605      ptr->globalptr->_try_parse_i_=_try_parse_i_;
3606      ptr->globalptr->_specialtexprint_double_=_specialtexprint_double_;
3607      ptr->globalptr->_atan_tan_no_floor_=_atan_tan_no_floor_;
3608      ptr->globalptr->_keep_acosh_asinh_=_keep_acosh_asinh_;
3609      ptr->globalptr->_keep_algext_=_keep_algext_;
3610      ptr->globalptr->_python_compat_=_python_compat_;
3611      ptr->globalptr->_complex_variables_=_complex_variables_;
3612      ptr->globalptr->_increasing_power_=_increasing_power_;
3613      ptr->globalptr->_approx_mode_=_approx_mode_;
3614      ptr->globalptr->_series_variable_name_=_series_variable_name_;
3615      ptr->globalptr->_series_default_order_=_series_default_order_;
3616      ptr->globalptr->_autosimplify_=_autosimplify_();
3617      ptr->globalptr->_lastprog_name_=_lastprog_name_();
3618      ptr->globalptr->_angle_mode_=_angle_mode_;
3619      ptr->globalptr->_variables_are_files_=_variables_are_files_;
3620      ptr->globalptr->_bounded_function_no_=_bounded_function_no_;
3621      ptr->globalptr->_series_flags_=_series_flags_; // bit1= full simplify, bit2=1 for truncation
3622      ptr->globalptr->_step_infolevel_=_step_infolevel_; // bit1= full simplify, bit2=1 for truncation
3623      ptr->globalptr->_local_eval_=_local_eval_;
3624      ptr->globalptr->_default_color_=_default_color_;
3625      ptr->globalptr->_epsilon_=_epsilon_<=0?1e-12:_epsilon_;
3626      ptr->globalptr->_proba_epsilon_=_proba_epsilon_;
3627      ptr->globalptr->_withsqrt_=_withsqrt_;
3628      ptr->globalptr->_show_point_=_show_point_; // show 3-d point
3629      ptr->globalptr->_io_graph_=_io_graph_; // show 2-d point in io
3630      ptr->globalptr->_show_axes_=_show_axes_;
3631      ptr->globalptr->_spread_Row_=_spread_Row_;
3632      ptr->globalptr->_spread_Col_=_spread_Col_;
3633      ptr->globalptr->_printcell_current_row_=_printcell_current_row_;
3634      ptr->globalptr->_printcell_current_col_=_printcell_current_col_;
3635      ptr->globalptr->_all_trig_sol_=_all_trig_sol_;
3636      ptr->globalptr->_lexer_close_parenthesis_=_lexer_close_parenthesis_;
3637      ptr->globalptr->_rpn_mode_=_rpn_mode_;
3638      ptr->globalptr->_ntl_on_=_ntl_on_;
3639      ptr->globalptr->_prog_eval_level_val =_prog_eval_level_val ;
3640      ptr->globalptr->_eval_level=_eval_level;
3641      ptr->globalptr->_rand_seed=_rand_seed;
3642      ptr->globalptr->_language_=_language_;
3643      ptr->globalptr->_last_evaled_argptr_=_last_evaled_argptr_;
3644      ptr->globalptr->_last_evaled_function_name_=_last_evaled_function_name_;
3645      ptr->globalptr->_currently_scanned_="";
3646      ptr->globalptr->_max_sum_sqrt_=_max_sum_sqrt_;
3647      ptr->globalptr->_max_sum_add_=_max_sum_add_;
3648 
3649   }
3650 
clone_context(const context * contextptr)3651   context * clone_context(const context * contextptr) {
3652     context * ptr = new context;
3653     if (contextptr){
3654       *ptr->globalptr = *contextptr->globalptr;
3655       *ptr->tabptr = *contextptr->tabptr;
3656     }
3657     else {
3658       init_context(ptr);
3659     }
3660     return ptr;
3661   }
3662 
~context()3663   context::~context(){
3664     // CERR << "delete context " << this << '\n';
3665     if (!previous){
3666       if (history_in_ptr)
3667 	delete history_in_ptr;
3668       if (history_out_ptr)
3669 	delete history_out_ptr;
3670       if (history_plot_ptr)
3671 	delete history_plot_ptr;
3672       if (quoted_global_vars)
3673 	delete quoted_global_vars;
3674       if (rootofs)
3675 	delete rootofs;
3676       if (globalptr)
3677 	delete globalptr;
3678       if (tabptr)
3679 	delete tabptr;
3680 #ifdef HAVE_LIBPTHREAD
3681       pthread_mutex_lock(&context_list_mutex);
3682 #endif
3683       int s=int(context_list().size());
3684       for (int i=s-1;i>0;--i){
3685 	if (context_list()[i]==this){
3686 	  context_list().erase(context_list().begin()+i);
3687 	  break;
3688 	}
3689       }
3690 #ifndef RTOS_THREADX
3691 #if !defined BESTA_OS && !defined NSPIRE && !defined FXCG && !defined(KHICAS)
3692       if (context_names){
3693 	map<string,context *>::iterator it=context_names->begin(),itend=context_names->end();
3694 	for (;it!=itend;++it){
3695 	  if (it->second==this){
3696 	    context_names->erase(it);
3697 	    break;
3698 	  }
3699 	}
3700       }
3701 #endif
3702 #endif
3703 #ifdef HAVE_LIBPTHREAD
3704       pthread_mutex_unlock(&context_list_mutex);
3705 #endif
3706     }
3707   }
3708 
3709 #ifndef CLK_TCK
3710 #define CLK_TCK 1
3711 #endif
3712 
3713 #ifndef HAVE_NO_SYS_TIMES_H
delta_tms(struct tms tmp1,struct tms tmp2)3714    double delta_tms(struct tms tmp1,struct tms tmp2){
3715 #if defined(HAVE_SYSCONF) && !defined(EMCC)
3716      return double( tmp2.tms_utime+tmp2.tms_stime+tmp2.tms_cutime+tmp2.tms_cstime-(tmp1.tms_utime+tmp1.tms_stime+tmp1.tms_cutime+tmp1.tms_cstime) )/sysconf(_SC_CLK_TCK);
3717 #else
3718     return double( tmp2.tms_utime+tmp2.tms_stime+tmp2.tms_cutime+tmp2.tms_cstime-(tmp1.tms_utime+tmp1.tms_stime+tmp1.tms_cutime+tmp1.tms_cstime) )/CLK_TCK;
3719 #endif
3720    }
3721 #endif /// HAVE_NO_SYS_TIMES_H
3722 
remove_filename(const string & s)3723   string remove_filename(const string & s){
3724     int l=int(s.size());
3725     for (;l;--l){
3726       if (s[l-1]=='/')
3727 	break;
3728     }
3729     return s.substr(0,l);
3730   }
3731 
3732 #ifdef HAVE_LIBPTHREAD
in_thread_eval(void * arg)3733   static void * in_thread_eval(void * arg){
3734     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
3735     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
3736     vecteur *v = (vecteur *) arg;
3737     context * contextptr=(context *) (*v)[2]._POINTER_val;
3738     thread_param * ptr =thread_param_ptr(contextptr);
3739     pthread_attr_getstacksize(&ptr->attr,&ptr->stacksize);
3740     ptr->stackaddr=(void *) ((uintptr_t) &ptr-ptr->stacksize);
3741 #ifndef __MINGW_H
3742     struct tms tmp1,tmp2;
3743     times(&tmp1);
3744 #else
3745     int beg=CLOCK();
3746 #endif
3747     gen g = (*v)[0];
3748     g = protecteval(g,(*v)[1].val,contextptr);
3749 #ifndef NO_STDEXCEPT
3750     try {
3751 #endif
3752 #ifndef __MINGW_H
3753       times(&tmp2);
3754       double dt=delta_tms(tmp1,tmp2);
3755       total_time(contextptr) += dt;
3756       (*v)[4]=dt;
3757 #else
3758       int end=CLOCK();
3759       (*v)[4]=end-beg;
3760 #endif
3761       (*v)[5]=g;
3762 #ifndef NO_STDEXCEPT
3763     } catch (std::runtime_error & e){
3764       last_evaled_argptr(contextptr)=NULL;
3765     }
3766 #endif
3767     ptr->stackaddr=0;
3768     thread_eval_status(0,contextptr);
3769     pthread_exit(0);
3770     return 0;
3771   }
3772 
3773   // create a new thread for evaluation of g at level level in context
make_thread(const gen & g,int level,const giac_callback & f,void * f_param,const context * contextptr)3774   bool make_thread(const gen & g,int level,const giac_callback & f,void * f_param,const context * contextptr){
3775     if (is_context_busy(contextptr))
3776       return false;
3777     thread_param * ptr =thread_param_ptr(contextptr);
3778     if (!ptr || ptr->v.size()!=6)
3779       return false;
3780     pthread_mutex_lock(mutexptr(contextptr));
3781     ptr->v[0]=g;
3782     ptr->v[1]=level;
3783     ptr->v[2]=gen((void *)contextptr,_CONTEXT_POINTER);
3784     ptr->f=f;
3785     ptr->f_param=f_param;
3786     thread_eval_status(1,contextptr);
3787     pthread_attr_init(&ptr->attr);
3788     int cres=pthread_create (&ptr->eval_thread, &ptr->attr, in_thread_eval,(void *)&ptr->v);
3789     if (cres){
3790       thread_eval_status(0,contextptr);
3791       pthread_mutex_unlock(mutexptr(contextptr));
3792     }
3793     return !cres;
3794   }
3795 
3796   // check if contextptr has a running evaluation thread
3797   // if not returns -1
3798   // if evaluation is not finished return 1
3799   // if evaluation is finished, clear mutex lock and
3800   // call the thread_param_ptr callback function with the evaluation value
3801   // and returns 0
3802   // otherwise returns status, 2=debug, 3=wait click
check_thread(context * contextptr)3803   int check_thread(context * contextptr){
3804     if (!is_context_busy(contextptr))
3805       return -1;
3806     int status=thread_eval_status(contextptr);
3807     if (status!=0 && !kill_thread(contextptr))
3808       return status;
3809     thread_param tp = *thread_param_ptr(contextptr);
3810     if (status==0){
3811       // unsigned thread_return_value=0;
3812       // void * ptr_return=&thread_return_value;
3813       // pthread_join(eval_thread,&ptr_return);
3814       if (
3815 #ifdef __MINGW_H
3816 	  1
3817 #else
3818 	  tp.eval_thread
3819 #endif
3820 	  ){
3821 	giac_callback f=tp.f;
3822 	gen arg_callback=tp.v[5];
3823 	void * param_callback=tp.f_param;
3824 	double tt=tp.v[4]._DOUBLE_val;
3825 	pthread_join(tp.eval_thread,0);
3826 	pthread_mutex_unlock(mutexptr(contextptr));
3827 	// double tt=double(tp.v[4].val)/CLOCKS_PER_SEC;
3828 	if (tt>0.4)
3829 	  (*logptr(contextptr)) << gettext("\nEvaluation time: ") << tt << '\n';
3830 	if (f)
3831 	  f(arg_callback,param_callback);
3832 	else
3833 	  (*logptr(contextptr)) << arg_callback << '\n';
3834 	return 0;
3835       }
3836     }
3837     if (kill_thread(contextptr)){
3838       kill_thread(false,contextptr);
3839       thread_eval_status(0,contextptr);
3840       clear_prog_status(contextptr);
3841       cleanup_context(contextptr);
3842       if (tp.f)
3843 	tp.f(string2gen("Aborted",false),tp.f_param);
3844 #if !defined __MINGW_H && !defined KHICAS
3845       *logptr(contextptr) << gettext("Thread ") << tp.eval_thread << " has been cancelled" << '\n';
3846 #endif
3847 #ifdef NO_STDEXCEPT
3848       pthread_cancel(tp.eval_thread) ;
3849 #else
3850       try {
3851 	pthread_cancel(tp.eval_thread) ;
3852       } catch (...){
3853       }
3854 #endif
3855       pthread_mutex_unlock(mutexptr(contextptr));
3856       return -1;
3857     }
3858     return status;
3859   }
3860 
3861   // check contexts in context_list starting at index i,
3862   // returns at first context with status >= 2
3863   // return value is -2 (invalid range), -1 (ok) or context number
check_threads(int i)3864   int check_threads(int i){
3865     int s,ans=-1;
3866     context * cptr;
3867     if (// i>=s ||
3868 	i<0)
3869       return -2;
3870     for (;;++i){
3871       pthread_mutex_lock(&context_list_mutex);
3872       s=context_list().size();
3873       if (i<s)
3874 	cptr=context_list()[i];
3875       pthread_mutex_unlock(&context_list_mutex);
3876       if (i>=s)
3877 	break;
3878       int res=check_thread(cptr);
3879       if (res>1){
3880 	ans=i;
3881 	break;
3882       }
3883     }
3884     return ans;
3885   }
3886 
thread_eval(const gen & g_,int level,context * contextptr,void (* wait_0001)(context *))3887   gen thread_eval(const gen & g_,int level,context * contextptr,void (* wait_0001)(context *) ){
3888     gen g=equaltosto(g_,contextptr);
3889     /* launch a new thread for evaluation only,
3890        no more readqueue, readqueue is done by the "parent" thread
3891        Ctrl-C will kill the "child" thread
3892        wait_001 is a function that should wait 0.001 s and update thinks
3893        for example it could remove idle callback of a GUI
3894        then call the wait function of the GUI and readd callbacks
3895     */
3896     pthread_t eval_thread;
3897     vecteur v(6);
3898     v[0]=g;
3899     v[1]=level;
3900     v[2]=gen(contextptr,_CONTEXT_POINTER);
3901     pthread_mutex_lock(mutexptr(contextptr));
3902     thread_eval_status(1,contextptr);
3903     int cres=pthread_create (&eval_thread, (pthread_attr_t *) NULL, in_thread_eval,(void *)&v);
3904     if (!cres){
3905       for (;;){
3906 	int eval_status=thread_eval_status(contextptr);
3907 	if (!eval_status)
3908 	  break;
3909 	wait_0001(contextptr);
3910 	if (kill_thread(contextptr)){
3911 	  kill_thread(false,contextptr);
3912 	  clear_prog_status(contextptr);
3913 	  cleanup_context(contextptr);
3914 #if !defined __MINGW_H && !defined KHICAS
3915 	  *logptr(contextptr) << gettext("Cancel thread ") << eval_thread << '\n';
3916 #endif
3917 #ifdef NO_STDEXCEPT
3918 	  pthread_cancel(eval_thread) ;
3919 #else
3920 	  try {
3921 	    pthread_cancel(eval_thread) ;
3922 	  } catch (...){
3923 	  }
3924 #endif
3925 	  pthread_mutex_unlock(mutexptr(contextptr));
3926 	  return undef;
3927 	}
3928       }
3929       // unsigned thread_return_value=0;
3930       // void * ptr=&thread_return_value;
3931       pthread_join(eval_thread,0); // pthread_join(eval_thread,&ptr);
3932       // Restore pointers and return v[3]
3933       pthread_mutex_unlock(mutexptr(contextptr));
3934       // double tt=double(v[4].val)/CLOCKS_PER_SEC;
3935       double tt=v[4]._DOUBLE_val;
3936       if (tt>0.1)
3937 	(*logptr(contextptr)) << gettext("Evaluation time: ") << tt << '\n';
3938       return v[5];
3939     }
3940     pthread_mutex_unlock(mutexptr(contextptr));
3941     return protecteval(g,level,contextptr);
3942   }
3943 #else
3944 
make_thread(const gen & g,int level,const giac_callback & f,void * f_param,context * contextptr)3945   bool make_thread(const gen & g,int level,const giac_callback & f,void * f_param,context * contextptr){
3946     return false;
3947   }
3948 
check_thread(context * contextptr)3949   int check_thread(context * contextptr){
3950     return -1;
3951   }
3952 
check_threads(int i)3953   int check_threads(int i){
3954     return -1;
3955   }
3956 
thread_eval(const gen & g,int level,context * contextptr,void (* wait_001)(context *))3957   gen thread_eval(const gen & g,int level,context * contextptr,void (* wait_001)(context * )){
3958     return protecteval(g,level,contextptr);
3959   }
3960 #endif // HAVE_LIBPTHREAD
3961 
debug_struct()3962   debug_struct::debug_struct():indent_spaces(0),debug_mode(false),sst_mode(false),sst_in_mode(false),debug_allowed(true),current_instruction(-1),debug_refresh(false){
3963     debug_info_ptr=new gen;
3964     fast_debug_info_ptr=new gen;
3965     debug_prog_name=new gen;
3966     debug_localvars=new gen;
3967     debug_contextptr=0;
3968   }
3969 
~debug_struct()3970   debug_struct::~debug_struct(){
3971     delete debug_info_ptr;
3972     delete fast_debug_info_ptr;
3973     delete debug_prog_name;
3974     delete debug_localvars;
3975   }
3976 
operator =(const debug_struct & dbg)3977   debug_struct & debug_struct::operator =(const debug_struct & dbg){
3978     indent_spaces=dbg.indent_spaces;
3979     args_stack=dbg.args_stack;
3980     debug_breakpoint=dbg.debug_breakpoint;
3981     debug_watch=dbg.debug_watch ;
3982     debug_mode=dbg.debug_mode;
3983     sst_mode=dbg.sst_mode ;
3984     sst_in_mode=dbg.sst_in_mode ;
3985     debug_allowed=dbg.debug_allowed;
3986     current_instruction_stack=dbg.current_instruction_stack;
3987     current_instruction=dbg.current_instruction;
3988     sst_at_stack=dbg.sst_at_stack;
3989     sst_at=dbg.sst_at;
3990     if (debug_info_ptr)
3991       delete debug_info_ptr;
3992     debug_info_ptr=new gen(dbg.debug_info_ptr?*dbg.debug_info_ptr:0) ;
3993     if (fast_debug_info_ptr)
3994       delete fast_debug_info_ptr;
3995     fast_debug_info_ptr= new gen(dbg.fast_debug_info_ptr?*dbg.fast_debug_info_ptr:0);
3996     if (debug_prog_name)
3997       delete debug_prog_name;
3998     debug_prog_name=new gen(dbg.debug_prog_name?*dbg.debug_prog_name:0);
3999     if (debug_localvars)
4000       delete debug_localvars;
4001     debug_localvars=new gen(dbg.debug_localvars?*dbg.debug_localvars:0);
4002     debug_refresh=dbg.debug_refresh;
4003     debug_contextptr=dbg.debug_contextptr;
4004     return *this;
4005   }
4006 
_debug_data()4007   static debug_struct & _debug_data(){
4008     static debug_struct * ans = 0;
4009     if (!ans) ans=new debug_struct;
4010     return *ans;
4011   }
4012 
debug_ptr(GIAC_CONTEXT)4013   debug_struct * debug_ptr(GIAC_CONTEXT){
4014     if (contextptr && contextptr->globalptr)
4015       return contextptr->globalptr->_debug_ptr;
4016     return &_debug_data();
4017   }
4018 
clear_prog_status(GIAC_CONTEXT)4019   void clear_prog_status(GIAC_CONTEXT){
4020     debug_struct * ptr=debug_ptr(contextptr);
4021     if (ptr){
4022       ptr->args_stack.clear();
4023       ptr->debug_mode=false;
4024       ptr->sst_at_stack.clear();
4025       if (!contextptr)
4026 	protection_level=0;
4027     }
4028   }
4029 
4030 
global()4031   global::global() : _xcas_mode_(0),
4032 		     _calc_mode_(0),_decimal_digits_(12),_minchar_for_quote_as_string_(1),
4033 		     _scientific_format_(0), _integer_format_(0), _latex_format_(0),
4034 #ifdef BCD
4035 		     _bcd_decpoint_('.'|('E'<<16)|(' '<<24)),_bcd_mantissa_(12+(15<<8)), _bcd_flags_(0),_bcd_printdouble_(false),
4036 #endif
4037 		     _expand_re_im_(true), _do_lnabs_(true), _eval_abs_(true),_eval_equaltosto_(true),_integer_mode_(true),_complex_mode_(false), _escape_real_(true),_complex_variables_(false), _increasing_power_(false), _approx_mode_(false), _variables_are_files_(false), _local_eval_(true),
4038 		     _withsqrt_(true),
4039 		     _show_point_(true),  _io_graph_(true),
4040 		     _all_trig_sol_(false),
4041 #ifdef WITH_MYOSTREAM
4042 		     _ntl_on_(true),
4043 		     _lexer_close_parenthesis_(true),_rpn_mode_(false),_try_parse_i_(true),_specialtexprint_double_(false),_atan_tan_no_floor_(false),_keep_acosh_asinh_(false),_keep_algext_(false),
4044 #ifdef KHICAS
4045 		     _python_compat_(true),
4046 #else
4047 		     _python_compat_(false),
4048 #endif
4049 		     _angle_mode_(0), _bounded_function_no_(0), _series_flags_(0x3),_step_infolevel_(0),_default_color_(FL_BLACK), _epsilon_(1e-12), _proba_epsilon_(1e-15),  _show_axes_(1),_spread_Row_ (-1), _spread_Col_ (-1),_logptr_(&my_CERR),_prog_eval_level_val(1), _eval_level(DEFAULT_EVAL_LEVEL), _rand_seed(123457),_last_evaled_function_name_(0),_currently_scanned_(""),_last_evaled_argptr_(0),_max_sum_sqrt_(3),
4050 #ifdef GIAC_HAS_STO_38 // Prime sum(x^2,x,0,100000) crash on hardware
4051 		     _max_sum_add_(10000),
4052 #else
4053 		     _max_sum_add_(100000),
4054 #endif
4055 		     _total_time_(0),_evaled_table_(0),_extra_ptr_(0),_series_variable_name_('h'),_series_default_order_(5),
4056 #else
4057 		     _ntl_on_(true),
4058 		     _lexer_close_parenthesis_(true),_rpn_mode_(false),_try_parse_i_(true),_specialtexprint_double_(false),_atan_tan_no_floor_(false),_keep_acosh_asinh_(false),_keep_algext_(false),
4059 #ifdef KHICAS
4060 		     _python_compat_(true),
4061 #else
4062 		     _python_compat_(false),
4063 #endif
4064 		     _angle_mode_(0), _bounded_function_no_(0), _series_flags_(0x3),_step_infolevel_(0),_default_color_(FL_BLACK), _epsilon_(1e-12), _proba_epsilon_(1e-15),  _show_axes_(1),_spread_Row_ (-1), _spread_Col_ (-1),
4065 #ifdef EMCC
4066 		     _logptr_(&COUT),
4067 #else
4068 #ifdef FXCG
4069 		     _logptr_(0),
4070 #else
4071 #ifdef KHICAS
4072 		     _logptr_(&os_cerr),
4073 #else
4074 		     _logptr_(&CERR),
4075 #endif
4076 #endif
4077 #endif
4078 		     _prog_eval_level_val(1), _eval_level(DEFAULT_EVAL_LEVEL), _rand_seed(123457),_last_evaled_function_name_(0),_currently_scanned_(""),_last_evaled_argptr_(0),_max_sum_sqrt_(3),
4079 #ifdef GIAC_HAS_STO_38 // Prime sum(x^2,x,0,100000) crash on hardware
4080 		     _max_sum_add_(10000),
4081 #else
4082 		     _max_sum_add_(100000),
4083 #endif
4084 		     _total_time_(0),_evaled_table_(0),_extra_ptr_(0),_series_variable_name_('h'),_series_default_order_(5)
4085 #endif
4086   {
4087     _pl._i_sqrt_minus1_=1;
4088 #ifndef KHICAS
4089     _turtle_stack_.push_back(_turtle_);
4090 #endif
4091     _debug_ptr=new debug_struct;
4092     _thread_param_ptr=new thread_param;
4093     _parsed_genptr_=new gen;
4094 #ifdef GIAC_HAS_STO_38
4095     _autoname_="GA";
4096 #else
4097     _autoname_="A";
4098 #endif
4099     _autosimplify_="regroup";
4100     _lastprog_name_="lastprog";
4101     _format_double_="";
4102 #ifdef HAVE_LIBPTHREAD
4103     _mutexptr = new pthread_mutex_t;
4104     pthread_mutex_init(_mutexptr,0);
4105     _mutex_eval_status_ptr = new pthread_mutex_t;
4106     pthread_mutex_init(_mutex_eval_status_ptr,0);
4107 #endif
4108   }
4109 
operator =(const global & g)4110   global & global::operator = (const global & g){
4111      _xcas_mode_=g._xcas_mode_;
4112      _calc_mode_=g._calc_mode_;
4113      _decimal_digits_=g._decimal_digits_;
4114      _minchar_for_quote_as_string_=g._minchar_for_quote_as_string_;
4115      _scientific_format_=g._scientific_format_;
4116      _integer_format_=g._integer_format_;
4117      _integer_mode_=g._integer_mode_;
4118      _latex_format_=g._latex_format_;
4119 #ifdef BCD
4120      _bcd_decpoint_=g._bcd_decpoint_;
4121      _bcd_mantissa_=g._bcd_mantissa_;
4122      _bcd_flags_=g._bcd_flags_;
4123      _bcd_printdouble_=g._bcd_printdouble_;
4124 #endif
4125      _expand_re_im_=g._expand_re_im_;
4126      _do_lnabs_=g._do_lnabs_;
4127      _eval_abs_=g._eval_abs_;
4128      _eval_equaltosto_=g._eval_equaltosto_;
4129      _complex_mode_=g._complex_mode_;
4130      _escape_real_=g._escape_real_;
4131      _complex_variables_=g._complex_variables_;
4132      _increasing_power_=g._increasing_power_;
4133      _approx_mode_=g._approx_mode_;
4134      _series_variable_name_=g._series_variable_name_;
4135      _series_default_order_=g._series_default_order_;
4136      _angle_mode_=g._angle_mode_;
4137      _atan_tan_no_floor_=g._atan_tan_no_floor_;
4138      _keep_acosh_asinh_=g._keep_acosh_asinh_;
4139      _keep_algext_=g._keep_algext_;
4140      _python_compat_=g._python_compat_;
4141      _variables_are_files_=g._variables_are_files_;
4142      _bounded_function_no_=g._bounded_function_no_;
4143      _series_flags_=g._series_flags_; // bit1= full simplify, bit2=1 for truncation, bit3=?, bit4=1 do not convert back SPOL1 to symbolic expression
4144      _step_infolevel_=g._step_infolevel_; // bit1= full simplify, bit2=1 for truncation
4145      _local_eval_=g._local_eval_;
4146      _default_color_=g._default_color_;
4147      _epsilon_=g._epsilon_;
4148      _proba_epsilon_=g._proba_epsilon_;
4149      _withsqrt_=g._withsqrt_;
4150      _show_point_=g._show_point_; // show 3-d point
4151      _io_graph_=g._io_graph_; // show 2-d point in io
4152      _show_axes_=g._show_axes_;
4153      _spread_Row_=g._spread_Row_;
4154      _spread_Col_=g._spread_Col_;
4155      _printcell_current_row_=g._printcell_current_row_;
4156      _printcell_current_col_=g._printcell_current_col_;
4157      _all_trig_sol_=g._all_trig_sol_;
4158      _ntl_on_=g._ntl_on_;
4159      _prog_eval_level_val =g._prog_eval_level_val ;
4160      _eval_level=g._eval_level;
4161      _rand_seed=g._rand_seed;
4162      _language_=g._language_;
4163      _last_evaled_argptr_=g._last_evaled_argptr_;
4164      _last_evaled_function_name_=g._last_evaled_function_name_;
4165      _currently_scanned_=g._currently_scanned_;
4166      _max_sum_sqrt_=g._max_sum_sqrt_;
4167      _max_sum_add_=g._max_sum_add_;
4168      _turtle_=g._turtle_;
4169 #ifndef KHICAS
4170      _turtle_stack_=g._turtle_stack_;
4171 #endif
4172      _autoname_=g._autoname_;
4173      _format_double_=g._format_double_;
4174      _extra_ptr_=g._extra_ptr_;
4175      return *this;
4176   }
4177 
~global()4178   global::~global(){
4179     delete _parsed_genptr_;
4180     delete _thread_param_ptr;
4181     delete _debug_ptr;
4182 #ifdef HAVE_LIBPTHREAD
4183     pthread_mutex_destroy(_mutexptr);
4184     delete _mutexptr;
4185     pthread_mutex_destroy(_mutex_eval_status_ptr);
4186     delete _mutex_eval_status_ptr;
4187 #endif
4188   }
4189 
4190 #ifdef FXCG
my_isinf(double d)4191   bool my_isinf(double d){
4192     return 1/d==0.0;
4193   }
my_isnan(double d)4194   bool my_isnan(double d){
4195     return d==d+1 && !my_isinf(d);
4196   }
4197 #else // FXCG
4198 #ifdef __APPLE__
my_isnan(double d)4199   bool my_isnan(double d){
4200 #if 1 // TARGET_OS_IPHONE
4201     return isnan(d);
4202 #else
4203     return __isnand(d);
4204 #endif
4205   }
4206 
my_isinf(double d)4207   bool my_isinf(double d){
4208 #if 1  // TARGET_OS_IPHONE
4209     return isinf(d);
4210 #else
4211     return __isinfd(d);
4212 #endif
4213   }
4214 
4215 #else // __APPLE__
my_isnan(double d)4216   bool my_isnan(double d){
4217 #if defined VISUALC || defined BESTA_OS
4218 #if !defined RTOS_THREADX && !defined FREERTOS
4219     return _isnan(d)!=0;
4220 #else
4221     return isnan(d);
4222 #endif
4223 #else
4224 #if defined(FIR_LINUX) || defined(FIR_ANDROID)
4225     return std::isnan(d);
4226 #else
4227     return isnan(d);
4228 #endif
4229 #endif
4230   }
4231 
my_isinf(double d)4232   bool my_isinf(double d){
4233 #if defined VISUALC || defined BESTA_OS
4234     double x=0.0;
4235     return d==1.0/x || d==-1.0/x;
4236 #else
4237 #if defined(FIR_LINUX) || defined(FIR_ANDROID)
4238     return std::isinf(d);
4239 #else
4240     return isinf(d);
4241 #endif
4242 #endif
4243   }
4244 
4245 #endif // __APPLE__
4246 #endif // FXCG
4247 
giac_floor(double d)4248   double giac_floor(double d){
4249     double maxdouble=longlong(1)<<30;
4250     if (d>=maxdouble || d<=-maxdouble)
4251       return std::floor(d);
4252     if (d>0)
4253       return int(d);
4254     double k=int(d);
4255     if (k==d)
4256       return k;
4257     else
4258       return k-1;
4259   }
giac_ceil(double d)4260   double giac_ceil(double d){
4261     double maxdouble=longlong(1)<<54;
4262     if (d>=maxdouble || d<=-maxdouble)
4263       return d;
4264     if (d<0)
4265       return double(longlong(d));
4266     double k=double(longlong(d));
4267     if (k==d)
4268       return k;
4269     else
4270       return k+1;
4271   }
4272 
4273 
4274 
4275 /* --------------------------------------------------------------------- */
4276 /*
4277  * Copyright 2001-2004 Unicode, Inc.
4278  *
4279  * Disclaimer
4280  *
4281  * This source code is provided as is by Unicode, Inc. No claims are
4282  * made as to fitness for any particular purpose. No warranties of any
4283  * kind are expressed or implied. The recipient agrees to determine
4284  * applicability of information provided. If this file has been
4285  * purchased on magnetic or optical media from Unicode, Inc., the
4286  * sole remedy for any claim will be exchange of defective media
4287  * within 90 days of receipt.
4288  *
4289  * Limitations on Rights to Redistribute This Code
4290  *
4291  * Unicode, Inc. hereby grants the right to freely use the information
4292  * supplied in this file in the creation of products supporting the
4293  * Unicode Standard, and to make copies of this file in any form
4294  * for internal or external distribution as long as this notice
4295  * remains attached.
4296  */
4297 
4298 /* ---------------------------------------------------------------------
4299 
4300     Conversions between UTF-16 and UTF-8. Source code file.
4301     Author: Mark E. Davis, 1994.
4302     Rev History: Rick McGowan, fixes & updates May 2001.
4303     Sept 2001: fixed const & error conditions per
4304     mods suggested by S. Parent & A. Lillich.
4305     June 2002: Tim Dodd added detection and handling of incomplete
4306     source sequences, enhanced error detection, added casts
4307     to eliminate compiler warnings.
4308     July 2003: slight mods to back out aggressive FFFE detection.
4309     Jan 2004: updated switches in from-UTF8 conversions.
4310     Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
4311     Jan 2013: Jean-Yves Avenard adapted to only calculate size if
4312     destination pointer are null
4313 
4314 ------------------------------------------------------------------------ */
4315 
4316 
4317 static const int halfShift  = 10; /* used for shifting by 10 bits */
4318 
4319 static const UTF32 halfBase = 0x0010000UL;
4320 static const UTF32 halfMask = 0x3FFUL;
4321 
4322 #define UNI_SUR_HIGH_START  (UTF32)0xD800
4323 #define UNI_SUR_HIGH_END    (UTF32)0xDBFF
4324 #define UNI_SUR_LOW_START   (UTF32)0xDC00
4325 #define UNI_SUR_LOW_END     (UTF32)0xDFFF
4326 
4327 /* --------------------------------------------------------------------- */
4328 
4329 /*
4330  * Index into the table below with the first byte of a UTF-8 sequence to
4331  * get the number of trailing bytes that are supposed to follow it.
4332  * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
4333  * left as-is for anyone who may want to do such conversion, which was
4334  * allowed in earlier algorithms.
4335  */
4336 static const char trailingBytesForUTF8[256] = {
4337     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4338     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4339     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4340     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4341     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4342     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4343     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
4344     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
4345 };
4346 
4347 /*
4348  * Magic values subtracted from a buffer value during UTF8 conversion.
4349  * This table contains as many values as there might be trailing bytes
4350  * in a UTF-8 sequence.
4351  */
4352 static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
4353              0x03C82080UL, 0xFA082080UL, 0x82082080UL };
4354 
4355 /*
4356  * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
4357  * into the first byte, depending on how many bytes follow.  There are
4358  * as many entries in this table as there are UTF-8 sequence types.
4359  * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
4360  * for *legal* UTF-8 will be 4 or fewer bytes total.
4361  */
4362 static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
4363 
4364 /* --------------------------------------------------------------------- */
4365 
4366 /* The interface converts a whole buffer to avoid function-call overhead.
4367  * Constants have been gathered. Loops & conditionals have been removed as
4368  * much as possible for efficiency, in favor of drop-through switches.
4369  * (See "Note A" at the bottom of the file for equivalent code.)
4370  * If your compiler supports it, the "isLegalUTF8" call can be turned
4371  * into an inline function.
4372  */
4373 
4374 /* --------------------------------------------------------------------- */
4375 
ConvertUTF16toUTF8(const UTF16 * sourceStart,const UTF16 * sourceEnd,UTF8 * targetStart,UTF8 * targetEnd,ConversionFlags flags)4376 unsigned int ConvertUTF16toUTF8 (
4377     const UTF16* sourceStart, const UTF16* sourceEnd,
4378     UTF8* targetStart, UTF8* targetEnd, ConversionFlags flags) {
4379     ConversionResult result = conversionOK;
4380     const UTF16* source = sourceStart;
4381     UTF8* target = targetStart;
4382     UTF32 ch;
4383     while ((source < sourceEnd) && (ch = *source)) {
4384     unsigned short bytesToWrite = 0;
4385     const UTF32 byteMask = 0xBF;
4386     const UTF32 byteMark = 0x80;
4387     const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
4388     source++;
4389     /* If we have a surrogate pair, convert to UTF32 first. */
4390     if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
4391         /* If the 16 bits following the high surrogate are in the source buffer... */
4392         UTF32 ch2;
4393         if ((source < sourceEnd) && (ch2 = *source)) {
4394         /* If it's a low surrogate, convert to UTF32. */
4395         if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
4396             ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
4397             + (ch2 - UNI_SUR_LOW_START) + halfBase;
4398             ++source;
4399         } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
4400             --source; /* return to the illegal value itself */
4401             result = sourceIllegal;
4402             break;
4403         }
4404         } else { /* We don't have the 16 bits following the high surrogate. */
4405         --source; /* return to the high surrogate */
4406         result = sourceExhausted;
4407         break;
4408         }
4409     } else if (flags == strictConversion) {
4410         /* UTF-16 surrogate values are illegal in UTF-32 */
4411         if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
4412         --source; /* return to the illegal value itself */
4413         result = sourceIllegal;
4414         break;
4415         }
4416     }
4417     /* Figure out how many bytes the result will require */
4418     if (ch < (UTF32)0x80) {      bytesToWrite = 1;
4419     } else if (ch < (UTF32)0x800) {     bytesToWrite = 2;
4420     } else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;
4421     } else if (ch < (UTF32)0x110000) {  bytesToWrite = 4;
4422     } else {       bytesToWrite = 3;
4423                         ch = UNI_REPLACEMENT_CHAR;
4424     }
4425 
4426     target += bytesToWrite;
4427     if ((uintptr_t)target > (uintptr_t)targetEnd) {
4428         source = oldSource; /* Back up source pointer! */
4429         target -= bytesToWrite; result = targetExhausted; break;
4430     }
4431     switch (bytesToWrite) { /* note: everything falls through. */
4432         case 4: target--; if (targetStart) { *target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; }
4433         case 3: target--; if (targetStart) { *target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; }
4434         case 2: target--; if (targetStart) { *target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; }
4435         case 1: target--; if (targetStart) { *target =  (UTF8)(ch | firstByteMark[bytesToWrite]); }
4436     }
4437     target += bytesToWrite;
4438     }
4439 
4440     unsigned int length = int(target - targetStart);
4441     return length;
4442 }
4443 
4444 /* --------------------------------------------------------------------- */
4445 
4446 /*
4447  * Utility routine to tell whether a sequence of bytes is legal UTF-8.
4448  * This must be called with the length pre-determined by the first byte.
4449  * If not calling this from ConvertUTF8to*, then the length can be set by:
4450  *  length = trailingBytesForUTF8[*source]+1;
4451  * and the sequence is illegal right away if there aren't that many bytes
4452  * available.
4453  * If presented with a length > 4, this returns false.  The Unicode
4454  * definition of UTF-8 goes up to 4-byte sequences.
4455  */
4456 
isLegalUTF8(const UTF8 * source,int length)4457 static Boolean isLegalUTF8(const UTF8 *source, int length) {
4458     UTF8 a;
4459     const UTF8 *srcptr = source+length;
4460     switch (length) {
4461     default: return false;
4462     /* Everything else falls through when "true"... */
4463     case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
4464     case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
4465     case 2: if ((a = (*--srcptr)) > 0xBF) return false;
4466 
4467     switch (*source) {
4468         /* no fall-through in this inner switch */
4469         case 0xE0: if (a < 0xA0) return false; break;
4470         case 0xED: if (a > 0x9F) return false; break;
4471         case 0xF0: if (a < 0x90) return false; break;
4472         case 0xF4: if (a > 0x8F) return false; break;
4473         default:   if (a < 0x80) return false;
4474     }
4475 
4476     case 1: if (*source >= 0x80 && *source < 0xC2) return false;
4477     }
4478     if (*source > 0xF4) return false;
4479     return true;
4480 }
4481 
4482 /* --------------------------------------------------------------------- */
4483 
4484 /*
4485  * Exported function to return whether a UTF-8 sequence is legal or not.
4486  * This is not used here; it's just exported.
4487  */
isLegalUTF8Sequence(const UTF8 * source,const UTF8 * sourceEnd)4488 Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
4489     int length = trailingBytesForUTF8[*source]+1;
4490     if (source+length > sourceEnd) {
4491     return false;
4492     }
4493     return isLegalUTF8(source, length);
4494 }
4495 
4496 /* --------------------------------------------------------------------- */
4497 
ConvertUTF8toUTF16(const UTF8 * sourceStart,const UTF8 * sourceEnd,UTF16 * targetStart,UTF16 * targetEnd,ConversionFlags flags)4498 unsigned int ConvertUTF8toUTF16 (const UTF8* sourceStart, const UTF8* sourceEnd, UTF16* targetStart, UTF16* targetEnd, ConversionFlags flags)
4499 #if 0 //def GIAC_HAS_STO_38
4500 {
4501     wchar_t *d= targetStart;
4502 #define read(a) if (sourceStart>=sourceEnd) break; a= *sourceStart++
4503     while (sourceStart<sourceEnd && d!=targetEnd)
4504     {
4505         read(uint8_t c);
4506         if ((c&0x80)==0) { *d++= c; continue; }
4507         if ((c&0xe0)==0xc0) { read(uint8_t c2); if ((c2&0xc0)!=0x80) continue; *d++= ((c&0x1f)<<6)+(c2&0x3f); continue; }
4508         if ((c&0xf0)==0xe0) { read(uint8_t c2); if ((c2&0xc0)!=0x80) continue; read(uint8_t c3); if ((c3&0xc0)!=0x80) continue; *d++= ((((c&0xf)<<6)+(c2&0x3f))<<6)+(c3&0x3f); continue; }
4509         if ((c&0xf8)==0xf0) { read(uint8_t c2); if ((c2&0xc0)!=0x80) continue; read(uint8_t c3); if ((c3&0xc0)!=0x80) continue; read(uint8_t c4); if ((c4&0xc0)!=0x80) continue; *d++= ((((((c&0xf)<<6)+(c2&0x3f))<<6)+(c3&0x3f))<<6)+(c4&0x3f); continue; }
4510         while (sourceStart<sourceEnd) { c= *sourceEnd; if ((c&0x80)==0 || (c&0xc0)!=0x80) break; sourceEnd++; }
4511     }
4512 #undef read
4513     return d-targetStart;
4514 }
4515 
4516 unsigned int ConvertUTF8toUTF162 (
4517     const UTF8* sourceStart, const UTF8* sourceEnd,
4518     UTF16* targetStart, UTF16* targetEnd, ConversionFlags flags)
4519 #endif
4520 {
4521     ConversionResult result = conversionOK;
4522     const UTF8* source = sourceStart;
4523     UTF16* target = targetStart;
4524     while (source < sourceEnd && *source) {
4525     UTF32 ch = 0;
4526     unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
4527     if (source + extraBytesToRead >= sourceEnd) {
4528         result = sourceExhausted; break;
4529     }
4530     /* Do this check whether lenient or strict */
4531     if (! isLegalUTF8(source, extraBytesToRead+1)) {
4532         result = sourceIllegal;
4533         break;
4534     }
4535     /*
4536      * The cases all fall through. See "Note A" below.
4537      */
4538     switch (extraBytesToRead) {
4539         case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
4540         case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
4541         case 3: ch += *source++; ch <<= 6;
4542         case 2: ch += *source++; ch <<= 6;
4543         case 1: ch += *source++; ch <<= 6;
4544         case 0: ch += *source++;
4545     }
4546     ch -= offsetsFromUTF8[extraBytesToRead];
4547 
4548     if ((uintptr_t)target >= (uintptr_t)targetEnd) {
4549         source -= (extraBytesToRead+1); /* Back up source pointer! */
4550         result = targetExhausted; break;
4551     }
4552     if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
4553         /* UTF-16 surrogate values are illegal in UTF-32 */
4554         if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
4555         if (flags == strictConversion) {
4556             source -= (extraBytesToRead+1); /* return to the illegal value itself */
4557             result = sourceIllegal;
4558             break;
4559         } else {
4560           if (targetStart)
4561             *target = UNI_REPLACEMENT_CHAR;
4562           target++;
4563         }
4564         } else {
4565           if (targetStart)
4566             *target = (UTF16)ch; /* normal case */
4567           target++;
4568         }
4569     } else if (ch > UNI_MAX_UTF16) {
4570         if (flags == strictConversion) {
4571         result = sourceIllegal;
4572         source -= (extraBytesToRead+1); /* return to the start */
4573         break; /* Bail out; shouldn't continue */
4574         } else {
4575         *target++ = UNI_REPLACEMENT_CHAR;
4576         }
4577     } else {
4578         /* target is a character in range 0xFFFF - 0x10FFFF. */
4579         if ((uintptr_t)target + 1 >= (uintptr_t)targetEnd) {
4580         source -= (extraBytesToRead+1); /* Back up source pointer! */
4581         result = targetExhausted; break;
4582         }
4583         ch -= halfBase;
4584         if (targetStart)
4585         {
4586           *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
4587           *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
4588         }
4589         else
4590           target += 2;
4591     }
4592     }
4593 
4594     unsigned int length = unsigned(target - targetStart);
4595     return length;
4596 }
4597 
utf82unicode(const char * line,wchar_t * wline,unsigned int n)4598   unsigned int utf82unicode(const char * line, wchar_t * wline, unsigned int n){
4599     if (!line){
4600       if (wline) wline[0]=0;
4601       return 0;
4602     }
4603 
4604     unsigned int j = ConvertUTF8toUTF16 (
4605       (const UTF8*) line,((line + n) < line) ? (const UTF8*)~0 : (const UTF8*)(line + n),
4606       (UTF16*)wline, (UTF16*)~0,
4607       lenientConversion);
4608 
4609     if (wline) wline[j] = 0;
4610 
4611     return j;
4612   }
4613 
4614     // convert position n in utf8-encoded line into the corresponding position
4615   // in the same string encoded with unicode
utf8pos2unicodepos(const char * line,unsigned int n,bool skip_added_spaces)4616   unsigned int utf8pos2unicodepos(const char * line,unsigned int n,bool skip_added_spaces){
4617     if (!line) return 0;
4618     unsigned int i=0,j=0,c;
4619     for (;i<n;i++){
4620       c=line[i];
4621       if (!c)
4622 	return j;
4623       if ( (c & 0xc0) == 0x80)
4624 	continue;
4625       if (c < 128){ // 0/xxxxxxx/
4626 	j++;
4627 	continue;
4628       }
4629       if ( (c & 0xe0) == 0xc0) { // 2 char code 110/xxxxx/ 10/xxxxxx/
4630 	i++;
4631 	c = (c & 0x1f) << 6 | (line[i] & 0x3f);
4632 	j++;
4633 	continue;
4634       }
4635       if ( (c & 0xf0) == 0xe0) { // 3 char 1110/xxxx/ 10/xxxxxx/ 10/xxxxxx/
4636 	i++;
4637 	c = (c & 0x0f) << 6 | (line[i] & 0x3f);
4638 	i++;
4639 	c = c << 6 | (line[i] & 0x3f);
4640 	j++;
4641 	if (skip_added_spaces) {
4642 	  unsigned int masked = c & 0xff00; // take care of spaces that were added
4643 	  if (masked>=0x2000 && masked<0x2c00)
4644 	    j -= 2;
4645 	}
4646 	continue;
4647       }
4648       if ( (c & 0xf8) == 0xf0) { // 4 char 11110/xxx/ 10/xxxxxx/ 10/xxxxxx/ 10/xxxxxx/
4649 	i++;
4650 	c = (c & 0x07) << 6 | (line[i] & 0x3f);
4651 	i++;
4652 	c = c << 6 | (line[i] & 0x3f);
4653 	i++;
4654 	c = c << 6 | (line[i] & 0x3f);
4655 	j++;
4656 	continue;
4657       }
4658       // FIXME complete for 5 and 6 char
4659       c = 0xfffd;
4660       j++;
4661     }
4662     return j;
4663   }
4664 
wstrlen(const char * line,unsigned int n)4665   unsigned int wstrlen(const char * line, unsigned int n){
4666     if (!line) return 0;
4667     return utf82unicode(line, NULL, n);
4668   }
4669 
4670   // convert UTF8 string to unicode, allocate memory with new
utf82unicode(const char * idname)4671   wchar_t * utf82unicode(const char * idname){
4672     if (!idname)
4673       return 0;
4674     int l=int(strlen(idname));
4675     wchar_t * wname=new wchar_t[l+1];
4676     utf82unicode(idname,wname,l);
4677     return wname;
4678   }
4679 
4680 #if defined NSPIRE || defined FXCG
wcslen(const wchar_t * c)4681   unsigned wcslen(const wchar_t * c){
4682     unsigned i=0;
4683     for (;*c;++i)
4684       ++c;
4685     return i;
4686   }
4687 #endif
4688 
unicode2utf8(const wchar_t * idname)4689   char * unicode2utf8(const wchar_t * idname){
4690     if (!idname)
4691       return 0;
4692     int l=int(wcslen(idname));
4693     char * name=new char[4*l+1];
4694     unicode2utf8(idname,name,l);
4695     return name;
4696   }
4697 
wstrlen(const wchar_t * wline)4698   unsigned int wstrlen(const wchar_t * wline){
4699     if (!wline)
4700       return 0;
4701     unsigned int i=0;
4702     for (;*wline;wline++){ i++; }
4703     return i;
4704   }
4705 
4706   // return length required to translate from unicode to UTF8
utf8length(const wchar_t * wline)4707   unsigned int utf8length(const wchar_t * wline){
4708     return unicode2utf8(wline,0,wstrlen(wline));
4709   }
4710 
unicode2utf8(const wchar_t * wline,char * line,unsigned int n)4711   unsigned int unicode2utf8(const wchar_t * wline,char * line,unsigned int n){
4712     if (!wline){
4713       if (line) line[0]=0;
4714       return 0;
4715     }
4716 
4717     unsigned int j = ConvertUTF16toUTF8(
4718       (UTF16*)wline, ((wline + n) < wline) ? (const UTF16*)~0 : (const UTF16*)(wline + n),
4719       (UTF8*)line, (UTF8*)-1,
4720       lenientConversion);
4721 
4722     if (line) line[j]=0;
4723 
4724     return j;
4725   }
4726 
4727   // Binary archive format for a gen:
4728   // 8 bytes=the gen itself (i.e. type, subtype, etc.)
4729   // Additionnally for pointer types
4730   // 4 bytes = total size of additionnal data
4731   // _CPLX: both real and imaginary parts
4732   // _FRAC: numerator and denominator
4733   // _MOD: 2 gens
4734   // _REAL, _ZINT: long int/real binary archive
4735   // _VECT: 4 bytes = #rows #cols (#cols=0 if not a matrix) + list of elements
4736   // _SYMB: feuille + sommet
4737   // _FUNC: 2 bytes = -1 + string or index
4738   // _IDNT or _STRNG: the name
4739   // count number of bytes required to save g in a file
countfunction(void const * p,size_t nbBytes,size_t NbElements,void * file)4740   static size_t countfunction(void const* p, size_t nbBytes,size_t NbElements, void *file)
4741   {
4742     (*(unsigned *)file)+= unsigned(nbBytes*NbElements);
4743     return nbBytes*NbElements;
4744   }
archive_count(const gen & g,GIAC_CONTEXT)4745   unsigned archive_count(const gen & g,GIAC_CONTEXT){
4746     unsigned size= 0;
4747     archive_save((void*)&size, g, countfunction, contextptr, true);
4748     return size;
4749   }
4750 
4751   /*
4752   unsigned archive_count(const gen & g,GIAC_CONTEXT){
4753     if (g.type<=_DOUBLE_ || g.type==_FLOAT_)
4754       return sizeof(gen);
4755     if (g.type==_CPLX)
4756       return sizeof(gen)+sizeof(unsigned)+archive_count(*g._CPLXptr,contextptr)+archive_count(*(g._CPLXptr+1),contextptr);
4757     if (g.type==_REAL || g.type==_ZINT)
4758       return sizeof(gen)+sizeof(unsigned)+g.print(contextptr).size();
4759     if (g.type==_FRAC)
4760       return sizeof(gen)+sizeof(unsigned)+archive_count(g._FRACptr->num,contextptr)+archive_count(g._FRACptr->den,contextptr);
4761     if (g.type==_MOD)
4762       return sizeof(gen)+sizeof(unsigned)+archive_count(*g._MODptr,contextptr)+archive_count(*(g._MODptr+1),contextptr);
4763     if (g.type==_VECT){
4764       unsigned res=sizeof(gen)+sizeof(unsigned)+4;
4765       const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
4766       for (;it!=itend;++it)
4767 	res += archive_count(*it,contextptr);
4768       return res;
4769     }
4770     if (g.type==_SYMB){
4771       if (archive_function_index(g._SYMBptr->sommet)) // ((equalposcomp(archive_function_tab(),g._SYMBptr->sommet))
4772 	return sizeof(gen)+sizeof(unsigned)+sizeof(short)+archive_count(g._SYMBptr->feuille,contextptr);
4773       return sizeof(gen)+sizeof(unsigned)+sizeof(short)+archive_count(g._SYMBptr->feuille,contextptr)+strlen(g._SYMBptr->sommet.ptr()->s);
4774     }
4775     if (g.type==_IDNT)
4776       return sizeof(gen)+sizeof(unsigned)+strlen(g._IDNTptr->id_name);
4777     if (g.type==_FUNC){
4778       if (archive_function_index(*g._FUNCptr)) // (equalposcomp(archive_function_tab(),*g._FUNCptr))
4779 	return sizeof(gen)+sizeof(unsigned)+sizeof(short);
4780       return sizeof(gen)+sizeof(unsigned)+sizeof(short)+strlen(g._FUNCptr->ptr()->s);
4781     }
4782     return sizeof(gen)+sizeof(unsigned)+strlen(g.print().c_str()); // not handled
4783   }
4784   */
4785 
4786 #define DBG_ARCHIVE 0
4787 
archive_save(void * f,const gen & g,size_t writefunc (void const * p,size_t nbBytes,size_t NbElements,void * file),GIAC_CONTEXT,bool noRecurse)4788   bool archive_save(void * f,const gen & g,size_t writefunc(void const* p, size_t nbBytes,size_t NbElements, void *file),GIAC_CONTEXT, bool noRecurse){
4789     // write the gen first
4790     writefunc(&g,sizeof(gen),1,f);
4791     if (g.type<=_DOUBLE_ || g.type==_FLOAT_)
4792       return true;
4793     // heap allocated object, find size
4794     unsigned size=0;
4795     if (!noRecurse) size=archive_count(g,contextptr);
4796     writefunc(&size,sizeof(unsigned),1,f);
4797     if (g.type==_CPLX)
4798       return archive_save(f,*g._CPLXptr,writefunc,contextptr,noRecurse) && archive_save(f,*(g._CPLXptr+1),writefunc,contextptr,noRecurse);
4799     if (g.type==_MOD)
4800       return archive_save(f,*g._MODptr,writefunc,contextptr,noRecurse) && archive_save(f,*(g._MODptr+1),writefunc,contextptr,noRecurse);
4801     if (g.type==_FRAC)
4802       return archive_save(f,g._FRACptr->num,writefunc,contextptr,noRecurse) && archive_save(f,g._FRACptr->den,writefunc,contextptr,noRecurse);
4803     if (g.type==_VECT){
4804       unsigned short rows=g._VECTptr->size(),cols=0;
4805       if (ckmatrix(g))
4806 	cols=g._VECTptr->front()._VECTptr->size();
4807       writefunc(&rows,sizeof(short),1,f);
4808       writefunc(&cols,sizeof(short),1,f);
4809       const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
4810       for (;it!=itend;++it){
4811 	if (!archive_save(f,*it,writefunc,contextptr,noRecurse))
4812 	  return false;
4813       }
4814       return true;
4815     }
4816     if (g.type==_IDNT){
4817 #if DBG_ARCHIVE
4818       std::ofstream ofs;
4819       ofs.open ("e:\\tmp\\logsave", std::ofstream::out | std::ofstream::app);
4820       ofs << "IDNT " << g << '\n';
4821       ofs.close();
4822 #endif
4823       // fprintf(f,"%s",g._IDNTptr->id_name);
4824       writefunc(g._IDNTptr->id_name,1,strlen(g._IDNTptr->id_name),f);
4825       return true;
4826     }
4827     if (g.type==_SYMB){
4828       if (!archive_save(f,g._SYMBptr->feuille,writefunc,contextptr,noRecurse))
4829 	return false;
4830 #if DBG_ARCHIVE
4831       std::ofstream ofs;
4832       ofs.open ("e:\\tmp\\logsave", std::ofstream::out | std::ofstream::app);
4833       ofs << "SYMB " << g << '\n';
4834       ofs.close();
4835 #endif
4836       short i=archive_function_index(g._SYMBptr->sommet); // equalposcomp(archive_function_tab(),g._SYMBptr->sommet);
4837       writefunc(&i,sizeof(short),1,f);
4838       if (i)
4839 	return true;
4840       // fprintf(f,"%s",g._SYMBptr->sommet.ptr()->s);
4841       writefunc(g._SYMBptr->sommet.ptr()->s,1,strlen(g._SYMBptr->sommet.ptr()->s),f);
4842       return true;
4843     }
4844     if (g.type==_FUNC){
4845       short i=archive_function_index(*g._FUNCptr); // equalposcomp(archive_function_tab(),*g._FUNCptr);
4846       writefunc(&i,sizeof(short),1,f);
4847       if (!i){
4848 	// fprintf(f,"%s",g._FUNCptr->ptr()->s);
4849 	writefunc(g._FUNCptr->ptr()->s,1,strlen(g._FUNCptr->ptr()->s),f);
4850       }
4851       return true;
4852     }
4853     string s;
4854     if (g.type==_ZINT)
4855       s=hexa_print_ZINT(*g._ZINTptr);
4856     else
4857       s=g.print(contextptr);
4858     // fprintf(f,"%s",s.c_str());
4859     writefunc(s.c_str(),1,s.size(),f);
4860     return true;
4861     //return false;
4862   }
4863 
4864 
archive_save(void * f,const gen & g,GIAC_CONTEXT)4865   bool archive_save(void * f,const gen & g,GIAC_CONTEXT){
4866     return archive_save(f,g,(size_t (*)(void const* p, size_t nbBytes,size_t NbElements, void *file))fwrite,contextptr);
4867   }
4868 
4869 #ifdef GIAC_HAS_STO_38
4870   // return true/false to tell if s is recognized. return the appropriate gen if true
lexerCompare(void const * a,void const * b)4871   int lexerCompare(void const *a, void const *b) {
4872     charptr_gen_unary const * ptr=(charptr_gen_unary const *)b;
4873     const char * aptr=(const char *) a;
4874     return strcmp(aptr, ptr->s);
4875   }
4876 
casbuiltin(const char * s,gen & g)4877   bool casbuiltin(const char *s, gen &g){
4878     // binary search in builtin_lexer_functions
4879 #if 1 // def SMARTPTR64
4880     int n=builtin_lexer_functions_number;
4881     charptr_gen_unary const * f = (charptr_gen_unary const *)bsearch(s, builtin_lexer_functions, n, sizeof(builtin_lexer_functions[0]), lexerCompare);
4882     if (f != NULL) {
4883       g = 0;
4884       int pos = int(f - builtin_lexer_functions);
4885       size_t val = builtin_lexer_functions_[pos];
4886       unary_function_ptr * at_val = (unary_function_ptr *)val;
4887       g = at_val;
4888       if (builtin_lexer_functions[pos]._FUNC_%2){
4889 #ifdef SMARTPTR64
4890 	unary_function_ptr tmp=*at_val;
4891 	tmp._ptr+=1;
4892 	g=tmp;
4893 #else
4894 	g._FUNC_ +=1;
4895 #endif // SMARTPTR64
4896       }
4897       return true;
4898     }
4899 #else
4900     charptr_gen_unary const * f = (charptr_gen_unary const *)bsearch(s, builtin_lexer_functions, builtin_lexer_functions_number, sizeof(builtin_lexer_functions[0]), lexerCompare);
4901     if (f != NULL) {
4902       g = gen(0);
4903       int pos=f - builtin_lexer_functions;
4904       *(size_t *)(&g) = builtin_lexer_functions_[pos] + f->_FUNC_;
4905       g = gen(*g._FUNCptr);
4906       return true;
4907     }
4908 #endif
4909     if (strlen(s)==1 && s[0]==':'){
4910       g=at_deuxpoints;
4911       return true;
4912     }
4913     return false;
4914   }
4915 
4916 #endif
4917 
4918   // restore a gen from an opened file
archive_restore(void * f,size_t readfunc (void * p,size_t nbBytes,size_t NbElements,void * file),GIAC_CONTEXT)4919   gen archive_restore(void * f,size_t readfunc(void * p, size_t nbBytes,size_t NbElements, void *file),GIAC_CONTEXT){
4920     gen g;
4921     if (!readfunc(&g,sizeof(gen),1,f))
4922       return undef;
4923     if (g.type<=_DOUBLE_ || g.type==_FLOAT_)
4924       return g;
4925     unsigned char t=g.type;
4926     signed char s=g.subtype;
4927     g.type=0; // required to avoid destructor of g to mess up the pointer part
4928     unsigned size;
4929     if (!readfunc(&size,sizeof(unsigned),1,f))
4930       return undef;
4931     if (t==_CPLX || t==_MOD || t==_FRAC){
4932       gen g1=archive_restore(f,readfunc,contextptr);
4933       gen g2=archive_restore(f,readfunc,contextptr);
4934       if (t==_CPLX)
4935 	return g1+cst_i*g2;
4936       if (t==_FRAC)
4937 	return fraction(g1,g2);
4938       if (t==_MOD)
4939 	return makemodquoted(g1,g2);
4940     }
4941     size -= sizeof(gen)+sizeof(unsigned); // adjust for gen size and length
4942     if (t==_VECT){
4943       unsigned short rows,cols;
4944       if (!readfunc(&rows,sizeof(unsigned short),1,f))
4945 	return undef;
4946       if (!readfunc(&cols,sizeof(unsigned short),1,f))
4947 	return undef;
4948 //      if (!rows) return undef;
4949       vecteur v(rows);
4950       for (int i=0;i<rows;++i)
4951 	v[i]=archive_restore(f,readfunc,contextptr);
4952       return gen(v,s);
4953     }
4954     if (t==_IDNT){
4955       char * ch=new char[size+1];
4956       ch[size]=0;
4957       if (readfunc(ch,1,size,f)!=size){
4958 	delete [] ch;
4959 	return undef;
4960       }
4961       string sch(ch); gen res;
4962       delete [] ch;
4963       lock_syms_mutex();
4964       sym_string_tab::const_iterator it=syms().find(sch),itend=syms().end();
4965       if (it!=itend)
4966 	res=it->second;
4967       else {
4968 	res=identificateur(sch);
4969 	syms()[sch]=res;
4970       }
4971       unlock_syms_mutex();
4972 #if DBG_ARCHIVE
4973       std::ofstream ofs;
4974       ofs.open ("e:\\tmp\\logrestore", std::ofstream::out | std::ofstream::app);
4975       ofs << "IDNT " << res << '\n';
4976       ofs.close();
4977 #endif
4978       return res;
4979     }
4980     if (t==_SYMB){
4981       gen fe=archive_restore(f,readfunc,contextptr);
4982       short index;
4983       if (!readfunc(&index,sizeof(short),1,f))
4984 	return undef;
4985       if (index>0){
4986 	const unary_function_ptr * aptr=archive_function_tab();
4987 	if (index<archive_function_tab_length){
4988 	  g=symbolic(aptr[index-1],fe);
4989 	}
4990 	else {
4991 #if DBG_ARCHIVE
4992 	  std::ofstream ofs;
4993 	  ofs.open ("e:\\tmp\\logrestore", std::ofstream::out | std::ofstream::app);
4994 	  ofs << "archive_restore error _SYMB index " << index << '\n';
4995 	  ofs.close();
4996 #endif
4997 	  g=fe; // ERROR
4998 	}
4999       }
5000       else {
5001 	gen res;
5002 	size -= archive_count(fe,contextptr)+sizeof(short);
5003 	char * ch=new char[size+3];
5004 	if (0 && abs_calc_mode(contextptr)==38){
5005 	  ch[0]='\'';
5006 	  ch[size+1]='\'';
5007 	  ch[size+2]=0;
5008 	  if (readfunc(ch+1,1,size,f)!=size){
5009 	    delete [] ch;
5010 	    return undef;
5011 	  }
5012 	}
5013 	else {
5014 	  ch[size]=0;
5015 	  if (readfunc(ch,1,size,f)!=size){
5016 	    delete [] ch;
5017 	    return undef;
5018 	  }
5019 #if defined NSPIRE
5020 	  if (builtin_lexer_functions_()){
5021 	    std::pair<charptr_gen *,charptr_gen *> p=equal_range(builtin_lexer_functions_begin(),builtin_lexer_functions_end(),std::pair<const char *,gen>(ch,0),tri);
5022 	    if (p.first!=p.second && p.first!=builtin_lexer_functions_end()){
5023 	      res = p.first->second;
5024 	      res.subtype=1;
5025 	      res=gen(int((*builtin_lexer_functions_())[p.first-builtin_lexer_functions_begin()]+p.first->second.val));
5026 	      res=gen(*res._FUNCptr);
5027 	    }
5028 	  }
5029 #else
5030 	  if (builtin_lexer_functions_){
5031 #ifdef GIAC_HAS_STO_38
5032 	    if (!casbuiltin(ch,res)){
5033 #if DBG_ARCHIVE
5034 	      std::ofstream ofs;
5035 	      ofs.open ("e:\\tmp\\logrestore", std::ofstream::out | std::ofstream::app);
5036 	      ofs << "archive_restore error _SYMB " << ch << '\n';
5037 	      ofs.close();
5038 #endif
5039 	      res=0;
5040 	    }
5041 #else
5042 	    std::pair<charptr_gen *,charptr_gen *> p=equal_range(builtin_lexer_functions_begin(),builtin_lexer_functions_end(),std::pair<const char *,gen>(ch,0),tri);
5043 	    if (p.first!=p.second && p.first!=builtin_lexer_functions_end()){
5044 	      res = p.first->second;
5045 	      res.subtype=1;
5046 	      res=gen(int(builtin_lexer_functions_[p.first-builtin_lexer_functions_begin()]+p.first->second.val));
5047 	      res=gen(*res._FUNCptr);
5048 	    }
5049 #endif
5050 	  }
5051 #endif
5052 	}
5053 	if (is_zero(res)){
5054 #if DBG_ARCHIVE
5055 	  std::ofstream ofs;
5056 	  ofs.open ("e:\\tmp\\logrestore", std::ofstream::out | std::ofstream::app);
5057 	  ofs << "archive_restore error _SYMB 0 " << ch << '\n';
5058 	  ofs.close();
5059 #endif
5060 	  res=gen(ch,contextptr);
5061 	}
5062 	delete [] ch;
5063 	if (res.type!=_FUNC){
5064 	  return undef;
5065 	}
5066 	g=symbolic(*res._FUNCptr,fe);
5067       }
5068       g.subtype=s;
5069 #if DBG_ARCHIVE
5070       std::ofstream ofs;
5071       ofs.open ("e:\\tmp\\logrestore", std::ofstream::out | std::ofstream::app);
5072       ofs << "SYMB " << g << '\n';
5073       ofs.close();
5074 #endif
5075       return g;
5076     }
5077     if (t==_FUNC){
5078       short index;
5079       if (!readfunc(&index,sizeof(short),1,f))
5080 	return undef;
5081       if (index>0)
5082 	g = archive_function_tab()[index-1];
5083       else {
5084 	size -= sizeof(short);
5085 	char * ch=new char[size+1];
5086 	ch[size]=0;
5087 	if (readfunc(ch,1,size,f)!=size){
5088 	  delete [] ch;
5089 	  return undef;
5090 	}
5091 	g = gen(ch,contextptr);
5092 	delete [] ch;
5093 	if (g.type!=_FUNC)
5094 	  return undef;
5095       }
5096       g.subtype=s;
5097       return g;
5098     }
5099     char * ch=new char[size+1];
5100     ch[size]=0;
5101     if (readfunc(ch,1,size,f)!=size){
5102       delete [] ch;
5103       return undef;
5104     }
5105     gen res;
5106     if (t==_STRNG)
5107       res=string2gen(ch,true);
5108     else
5109       res=gen(ch,contextptr);
5110     delete [] ch;
5111     return res;
5112   }
5113 
archive_restore(FILE * f,GIAC_CONTEXT)5114   gen archive_restore(FILE * f,GIAC_CONTEXT){
5115     return archive_restore(f,(size_t (*)(void * p, size_t nbBytes,size_t NbElements, void *file))fread,contextptr);
5116   }
5117 
init_geogebra(bool on,GIAC_CONTEXT)5118   void init_geogebra(bool on,GIAC_CONTEXT){
5119 #ifndef FXCG
5120     setlocale(LC_NUMERIC,"POSIX");
5121 #endif
5122     _decimal_digits_=on?13:12;
5123     _all_trig_sol_=on;
5124     _withsqrt_=!on;
5125     _calc_mode_=on?1:0;
5126     _eval_equaltosto_=on?0:1;
5127     eval_equaltosto(on?0:1,contextptr);
5128     decimal_digits(on?13:12,contextptr);
5129     all_trig_sol(on,contextptr);
5130     withsqrt(!on,contextptr);
5131     calc_mode(on?1:0,contextptr);
5132     powlog2float=3e4;
5133     MPZ_MAXLOG2=33300;
5134 #ifdef TIMEOUT
5135     //caseval_maxtime=5;
5136     caseval_n=0;
5137     caseval_mod=10;
5138 #endif
5139   }
5140 
giac_current_status(bool save_history,GIAC_CONTEXT)5141   vecteur giac_current_status(bool save_history,GIAC_CONTEXT){
5142     // cas and geo config
5143     vecteur res;
5144     if (abs_calc_mode(contextptr)==38)
5145       res.push_back(cas_setup(contextptr));
5146     else
5147       res.push_back(symbolic(at_cas_setup,cas_setup(contextptr)));
5148     res.push_back(xyztrange(gnuplot_xmin,gnuplot_xmax,gnuplot_ymin,gnuplot_ymax,gnuplot_zmin,gnuplot_zmax,gnuplot_tmin,gnuplot_tmax,global_window_xmin,global_window_xmax,global_window_ymin,global_window_ymax,show_axes(contextptr),class_minimum,class_size,
5149 #ifdef WITH_GNUPLOT
5150 			    gnuplot_hidden3d,gnuplot_pm3d
5151 #else
5152 			    1,1
5153 #endif
5154 			    ));
5155     if (abs_calc_mode(contextptr)==38)
5156       res.back()=res.back()._SYMBptr->feuille;
5157     // session
5158     res.push_back(save_history?history_in(contextptr):vecteur(0));
5159     res.push_back(save_history?history_out(contextptr):vecteur(0));
5160     // user variables
5161     if (contextptr && contextptr->tabptr){
5162       sym_tab::const_iterator jt=contextptr->tabptr->begin(),jtend=contextptr->tabptr->end();
5163       for (;jt!=jtend;++jt){
5164 	gen a=jt->second;
5165 	gen b=identificateur(jt->first);
5166 	res.push_back(symb_sto(a,b));
5167       }
5168     }
5169     else {
5170       lock_syms_mutex();
5171       sym_string_tab::const_iterator it=syms().begin(),itend=syms().end();
5172       for (;it!=itend;++it){
5173 	gen id=it->second;
5174 	if (id.type==_IDNT && id._IDNTptr->value)
5175 	  res.push_back(symb_sto(*id._IDNTptr->value,id));
5176       }
5177       unlock_syms_mutex();
5178     }
5179     int xc=xcas_mode(contextptr);
5180     if (xc==0 && python_compat(contextptr))
5181       xc=256*python_compat(contextptr);
5182     if (abs_calc_mode(contextptr)==38)
5183       res.push_back(xc);
5184     else
5185       res.push_back(symbolic(at_xcas_mode,xc));
5186     return res;
5187   }
5188 
unarchive_session(const gen & g,int level,const gen & replace,GIAC_CONTEXT,bool with_history)5189   bool unarchive_session(const gen & g,int level,const gen & replace,GIAC_CONTEXT,bool with_history){
5190     int l;
5191     if (g.type!=_VECT || (l=int(g._VECTptr->size()))<4)
5192       return false;
5193     vecteur v=*g._VECTptr;
5194     if (v[2].type!=_VECT || v[3].type!=_VECT || (v[2]._VECTptr->size()!=v[3]._VECTptr->size() && v[2]._VECTptr->size()!=v[3]._VECTptr->size()+1))
5195       return false;
5196     if (v[2]._VECTptr->size()==v[3]._VECTptr->size()+1)
5197       v[2]._VECTptr->pop_back();
5198 #ifndef DONT_UNARCHIVE_HISTORY
5199     history_in(contextptr)=*v[2]._VECTptr;
5200     history_out(contextptr)=*v[3]._VECTptr;
5201 #ifndef GNUWINCE
5202     if (v[0].type==_VECT)
5203       _cas_setup(v[0],contextptr);
5204     else
5205       protecteval(v[0],eval_level(contextptr),contextptr);
5206     if (v[1].type==_VECT)
5207       _xyztrange(v[1],contextptr);
5208     else
5209       protecteval(v[1],eval_level(contextptr),contextptr);
5210 #endif
5211 #endif
5212     // restore variables
5213     for (int i=4;i<l;++i)
5214       protecteval(v[i],eval_level(contextptr),contextptr);
5215     // restore xcas_mode
5216     if (v.back().type==_INT_)
5217       xcas_mode(v.back().val,contextptr);
5218     if (!with_history)
5219       return true;
5220     // eval replace if level>=0
5221     if (level<0 || level>=l){
5222       history_in(contextptr).push_back(replace);
5223       history_out(contextptr).push_back(protecteval(replace,eval_level(contextptr),contextptr));
5224     }
5225     else {
5226       history_in(contextptr)[level]=replace;
5227       for (int i=level;i<l;++i)
5228 	history_out(contextptr)[i]=protecteval(history_in(contextptr)[i],eval_level(contextptr),contextptr);
5229     }
5230     return true;
5231   }
5232 
5233   const char * const do_not_autosimplify[]={
5234     "Factor",
5235     "Gcd",
5236     "Int",
5237     "POLYFORM",
5238     "Quo",
5239     "Quorem",
5240     "Rem",
5241     "animate",
5242     "animation",
5243     "archive",
5244     "autosimplify",
5245     "canonical_form",
5246     "cfactor",
5247     "convert",
5248     "cpartfrac",
5249     "curve",
5250     "developper",
5251     "diff",
5252     "domain",
5253     "element",
5254     "evalc",
5255     "expand",
5256     "expexpand",
5257     "factor",
5258     "factoriser",
5259     "factoriser_entier",
5260     "factoriser_sur_C",
5261     "ifactor",
5262     "list2exp",
5263     "lncollect",
5264     "lnexpand",
5265     "mathml",
5266     "mult_c_conjugate",
5267     "mult_conjugate",
5268     "multiplier_conjugue",
5269     "nodisp",
5270     "normal",
5271     "op",
5272     "partfrac",
5273     "plotfield",
5274     "plotfunc",
5275     "plotparam",
5276     "plotpolar",
5277     "pow2exp",
5278     "powexpand",
5279     "propFrac",
5280     "propfrac",
5281     "quote",
5282     "regroup",
5283     "reorder",
5284     "series",
5285     "simplifier",
5286     "simplify",
5287     "tabvar",
5288     "taylor",
5289     "texpand",
5290     "trace",
5291     "trigexpand",
5292     0
5293   };
5294 
dichotomic_search(const char * const * tab,unsigned tab_size,const char * s)5295   int dichotomic_search(const char * const * tab,unsigned tab_size,const char * s){
5296     int beg=0,end=tab_size,cur,test;
5297     // string index is always >= begin and < end
5298     for (;;){
5299       cur=(beg+end)/2;
5300       test=strcmp(s,tab[cur]);
5301       if (!test)
5302 	return cur;
5303       if (cur==beg)
5304 	return -1;
5305       if (test>0)
5306 	beg=cur;
5307       else
5308 	end=cur;
5309     }
5310     return -1;
5311   }
5312 
add_autosimplify(const gen & g,GIAC_CONTEXT)5313   gen add_autosimplify(const gen & g,GIAC_CONTEXT){
5314     if (g.type==_VECT)
5315       return apply(g,add_autosimplify,contextptr);
5316     if (g.type==_SYMB){
5317       if (g._SYMBptr->sommet==at_program)
5318 	return g;
5319 #ifdef GIAC_HAS_STO_38
5320       const char * c=g._SYMBptr->sommet.ptr()->s;
5321 #else
5322       string ss=unlocalize(g._SYMBptr->sommet.ptr()->s);
5323       const char * c=ss.c_str();
5324 #endif
5325 #if 1
5326       if (dichotomic_search(do_not_autosimplify,sizeof(do_not_autosimplify)/sizeof(char*)-1,c)!=-1)
5327 	return g;
5328 #else
5329       const char ** ptr=do_not_autosimplify;
5330       for (;*ptr;++ptr){
5331 	if (!strcmp(*ptr,c))
5332 	  return g;
5333       }
5334 #endif
5335     }
5336     std::string s=autosimplify(contextptr);
5337     if (s.size()<1 || s=="'nop'")
5338       return g;
5339     gen a(s,contextptr);
5340     if (a.type==_FUNC)
5341       return symbolic(*a._FUNCptr,g);
5342     if (a.type>=_IDNT)
5343       return symb_of(a,g);
5344     return g;
5345   }
5346 
csv_guess(const char * data,int count,char & sep,char & nl,char & decsep)5347   bool csv_guess(const char * data,int count,char & sep,char & nl,char & decsep){
5348     bool ans=true;
5349     int nb[256],pointdecsep=0,commadecsep=0;
5350     for (int i=0;i<256;++i)
5351       nb[i]=0;
5352     // count occurence of each char
5353     // and detect decimal separator between . or ,
5354     for (int i=1;i<count-1;++i){
5355       if (data[i]=='[' || data[i]==']')
5356 	ans=false;
5357       ++nb[(unsigned char) data[i]];
5358       if (data[i-1]>='0' && data[i-1]<='9' && data[i+1]>='0' && data[i+1]<='9'){
5359 	if (data[i]=='.')
5360 	  ++pointdecsep;
5361 	if (data[i]==',')
5362 	  ++commadecsep;
5363       }
5364     }
5365     decsep=commadecsep>pointdecsep?',':'.';
5366     // detect nl (ctrl-M or ctrl-J)
5367     nl=nb[10]>nb[13]?10:13;
5368     // find in control characters and : ; the most used (except 10/13)
5369     int nbmax=0,imax=-1;
5370     for (int i=0;i<60;++i){
5371       if (i==10 || i==13 || (i>=' ' && i<='9') )
5372 	continue;
5373       if (nb[i]>nbmax){
5374 	imax=i;
5375 	nbmax=nb[i];
5376       }
5377     }
5378     // compare . with , (44)
5379     if (nb[unsigned(',')] && nb[unsigned(',')]>=nbmax){
5380       imax=',';
5381       nbmax=nb[unsigned(',')];
5382     }
5383     if (nbmax && nbmax>=nb[unsigned(nl)] && imax!=decsep)
5384       sep=imax;
5385     else
5386       sep=' ';
5387     return ans;
5388   }
5389 
5390   void (*my_gprintf)(unsigned special,const string & format,const vecteur & v,GIAC_CONTEXT)=0;
5391 
5392 
5393 #ifdef EMCC
newlinestobr(string & s,const string & add)5394   static void newlinestobr(string &s,const string & add){
5395     int l=int(add.size());
5396     for (int i=0;i<l;++i){
5397       if (add[i]=='\n')
5398 	s+="<br>";
5399       else
5400 	s+=add[i];
5401     }
5402   }
5403 #else
newlinestobr(string & s,const string & add)5404   static void newlinestobr(string &s,const string & add){
5405     s+=add;
5406   }
5407 #endif
5408 
gprintf(unsigned special,const string & format,const vecteur & v,GIAC_CONTEXT)5409   void gprintf(unsigned special,const string & format,const vecteur & v,GIAC_CONTEXT){
5410     return gprintf(special,format,v,step_infolevel(contextptr),contextptr);
5411   }
5412 
gprintf(unsigned special,const string & format,const vecteur & v,int step_info,GIAC_CONTEXT)5413   void gprintf(unsigned special,const string & format,const vecteur & v,int step_info,GIAC_CONTEXT){
5414     if (step_info==0)
5415       return;
5416     if (my_gprintf){
5417       my_gprintf(special,format,v,contextptr);
5418       return;
5419     }
5420     string s;
5421     int pos=0;
5422 #ifdef EMCC
5423     *logptr(contextptr) << char(2) << '\n'; // start mixed text/mathml
5424 #endif
5425     for (unsigned i=0;i<v.size();++i){
5426       int p=int(format.find("%gen",pos));
5427       if (p<0 || p>=int(format.size()))
5428 	break;
5429       newlinestobr(s,format.substr(pos,p-pos));
5430 #ifdef EMCC
5431       gen tmp;
5432       if (v[i].is_symb_of_sommet(at_pnt))
5433 	tmp=_svg(v[i],contextptr);
5434       else
5435 	tmp=_mathml(makesequence(v[i],1),contextptr);
5436       s = s+((tmp.type==_STRNG)?(*tmp._STRNGptr):v[i].print(contextptr));
5437 #else
5438       s += v[i].print(contextptr);
5439 #endif
5440       pos=p+4;
5441     }
5442     newlinestobr(s,format.substr(pos,format.size()-pos));
5443     *logptr(contextptr) << s << '\n';
5444 #ifdef EMCC
5445     *logptr(contextptr) << char(3) << '\n'; // end mixed text/mathml
5446     *logptr(contextptr) << '\n';
5447 #endif
5448   }
5449 
gprintf(const string & format,const vecteur & v,GIAC_CONTEXT)5450   void gprintf(const string & format,const vecteur & v,GIAC_CONTEXT){
5451     gprintf(step_nothing_special,format,v,contextptr);
5452   }
5453 
gprintf(const string & format,const vecteur & v,int step_info,GIAC_CONTEXT)5454   void gprintf(const string & format,const vecteur & v,int step_info,GIAC_CONTEXT){
5455     gprintf(step_nothing_special,format,v,step_info,contextptr);
5456   }
5457 
5458   // moved from input_lexer.ll for easier debug
5459   const char invalid_name[]="Invalid name";
5460 
5461 #if defined USTL || defined GIAC_HAS_STO_38 || defined KHICAS
5462 #if defined GIAC_HAS_STO_38 || defined KHICAS
update_lexer_localization(const std::vector<int> & v,std::map<std::string,std::string> & lexer_map,std::multimap<std::string,localized_string> & back_lexer_map,GIAC_CONTEXT)5463 void update_lexer_localization(const std::vector<int> & v,std::map<std::string,std::string> &lexer_map,std::multimap<std::string,localized_string> &back_lexer_map,GIAC_CONTEXT){}
5464 #endif
5465 #else
keywords_vecteur_ptr()5466   vecteur * keywords_vecteur_ptr(){
5467     static vecteur v;
5468     return &v;
5469   }
5470 
in_update_lexer_localization(istream & f,int lang,const std::vector<int> & v,std::map<std::string,std::string> & lexer_map,std::multimap<std::string,localized_string> & back_lexer_map,GIAC_CONTEXT)5471   static void in_update_lexer_localization(istream & f,int lang,const std::vector<int> & v,std::map<std::string,std::string> &lexer_map,std::multimap<std::string,localized_string> &back_lexer_map,GIAC_CONTEXT){
5472     char * line = (char *)malloc(1024);
5473     std::string giac_kw,local_kw;
5474     size_t l;
5475     for (;;){
5476       f.getline(line,1023,'\n');
5477       l=strlen(line);
5478       if (f.eof()){
5479 	break;
5480       }
5481       if (l>3 && line[0]!='#'){
5482 	if (line[l-1]=='\n')
5483 	  --l;
5484 	// read giac keyword
5485 	size_t j;
5486 	giac_kw="";
5487 	for (j=0;j<l;++j){
5488 	  if (line[j]==' ')
5489 	    break;
5490 	  giac_kw += line[j];
5491 	}
5492 	// read corresponding local keywords
5493 	local_kw="";
5494 	vecteur * keywordsptr=keywords_vecteur_ptr();
5495 	for (++j;j<l;++j){
5496 	  if (line[j]==' '){
5497 	    if (!local_kw.empty()){
5498 #ifdef EMCC
5499 	      gen localgen(gen(local_kw,contextptr));
5500 	      keywordsptr->push_back(localgen);
5501 	      sto(gen(giac_kw,contextptr),localgen,contextptr);
5502 #else
5503 	      lexer_map[local_kw]=giac_kw;
5504 	      back_lexer_map.insert(pair<string,localized_string>(giac_kw,localized_string(lang,local_kw)));
5505 #endif
5506 	    }
5507 	    local_kw="";
5508 	  }
5509 	  else
5510 	    local_kw += line[j];
5511 	}
5512 	if (!local_kw.empty()){
5513 #ifdef EMCC
5514 	  gen localgen(gen(local_kw,contextptr));
5515 	  keywordsptr->push_back(localgen);
5516 	  sto(gen(giac_kw,contextptr),localgen,contextptr);
5517 #else
5518 	  lexer_map[local_kw]=giac_kw;
5519 	  back_lexer_map.insert(pair<string,localized_string>(giac_kw,localized_string(lang,local_kw)));
5520 #endif
5521 	}
5522       }
5523     }
5524     free(line);
5525   }
5526 
update_lexer_localization(const std::vector<int> & v,std::map<std::string,std::string> & lexer_map,std::multimap<std::string,localized_string> & back_lexer_map,GIAC_CONTEXT)5527   void update_lexer_localization(const std::vector<int> & v,std::map<std::string,std::string> &lexer_map,std::multimap<std::string,localized_string> &back_lexer_map,GIAC_CONTEXT){
5528     lexer_map.clear();
5529     back_lexer_map.clear();
5530     int s=int(v.size());
5531     for (int i=0;i<s;++i){
5532       int lang=v[i];
5533       if (lang>=1 && lang<=4){
5534 	std::string doc=find_doc_prefix(lang);
5535 	std::string file=giac_aide_dir()+doc+"keywords";
5536 	//COUT << "keywords " << file << '\n';
5537 	ifstream f(file.c_str());
5538 	if (f.good()){
5539 	  in_update_lexer_localization(f,lang,v,lexer_map,back_lexer_map,contextptr);
5540 	  // COUT << "// Using keyword file " << file << '\n';
5541 	} // if (f)
5542 	else {
5543 	  if (lang==1){
5544 #ifdef HAVE_SSTREAM
5545       istringstream f(
5546 #else
5547       istrstream f(
5548 #endif
5549 		   "# enter couples\n# giac_keyword translation\n# for example, to define integration as a translation for integrate \nintegrate integration\neven est_pair\nodd est_impair\n# geometry\nbarycenter barycentre\nisobarycenter isobarycentre\nmidpoint milieu\nline_segments aretes\nmedian_line mediane\nhalf_line demi_droite\nparallel parallele\nperpendicular perpendiculaire\ncommon_perpendicular perpendiculaire_commune\nenvelope enveloppe\nequilateral_triangle triangle_equilateral\nisosceles_triangle triangle_isocele\nright_triangle triangle_rectangle\nlocus lieu\ncircle cercle\nconic conique\nreduced_conic conique_reduite\nquadric quadrique\nreduced_quadric quadrique_reduite\nhyperbola hyperbole\ncylinder cylindre\nhalf_cone demi_cone\nline droite\nplane plan\nparabola parabole\nrhombus losange\nsquare carre\nhexagon hexagone\npyramid pyramide\nquadrilateral quadrilatere\nparallelogram parallelogramme\northocenter orthocentre\nexbisector exbissectrice\nparallelepiped parallelepipede\npolyhedron polyedre\ntetrahedron tetraedre\ncentered_tetrahedron tetraedre_centre\ncentered_cube cube_centre\noctahedron octaedre\ndodecahedron dodecaedre\nicosahedron icosaedre\nbisector bissectrice\nperpen_bisector mediatrice\naffix affixe\naltitude hauteur\ncircumcircle circonscrit\nexcircle exinscrit\nincircle inscrit\nis_prime est_premier\nis_equilateral est_equilateral\nis_rectangle est_rectangle\nis_parallel est_parallele\nis_perpendicular est_perpendiculaire\nis_orthogonal est_orthogonal\nis_collinear est_aligne\nis_concyclic est_cocyclique\nis_element est_element\nis_included est_inclus\nis_coplanar est_coplanaire\nis_isosceles est_isocele\nis_square est_carre\nis_rhombus est_losange\nis_parallelogram est_parallelogramme\nis_conjugate est_conjugue\nis_harmonic_line_bundle est_faisceau_droite\nis_harmonic_circle_bundle est_faisceau_cercle\nis_inside est_dans\narea aire\nperimeter perimetre\ndistance longueur\ndistance2 longueur2\nareaat aireen\nslopeat penteen\nangleat angleen\nperimeterat perimetreen\ndistanceat distanceen\nareaatraw aireenbrut\nslopeatraw penteenbrut\nangleatraw angleenbrut\nperimeteratraw perimetreenbrut\ndistanceatraw distanceenbrut\nextract_measure extraire_mesure\ncoordinates coordonnees\nabscissa abscisse\nordinate ordonnee\ncenter centre\nradius rayon\npowerpc puissance\nvertices sommets\npolygon polygone\nisopolygon isopolygone\nopen_polygon polygone_ouvert\nhomothety homothetie\nsimilarity similitude\n# affinity affinite\nreflection symetrie\nreciprocation polaire_reciproque\nscalar_product produit_scalaire\n# solid_line ligne_trait_plein\n# dash_line ligne_tiret\n# dashdot_line ligne_tiret_point\n# dashdotdot_line ligne_tiret_pointpoint\n# cap_flat_line ligne_chapeau_plat\n# cap_round_line ligne_chapeau_rond\n# cap_square_line ligne_chapeau_carre\n# line_width_1 ligne_epaisseur_1\n# line_width_2 ligne_epaisseur_2\n# line_width_3 ligne_epaisseur_3\n# line_width_4 ligne_epaisseur_4\n# line_width_5 ligne_epaisseur_5\n# line_width_6 ligne_epaisseur_6\n# line_width_7 ligne_epaisseur_7\n# line_width_8 ligne_epaisseur_8\n# rhombus_point point_losange\n# plus_point point_plus\n# square_point point_carre\n# cross_point point_croix\n# triangle_point point_triangle\n# star_point point_etoile\n# invisible_point point_invisible\ncross_ratio birapport\nradical_axis axe_radical\npolar polaire\npolar_point point_polaire\npolar_coordinates coordonnees_polaires\nrectangular_coordinates coordonnees_rectangulaires\nharmonic_conjugate conj_harmonique\nharmonic_division div_harmonique\ndivision_point point_div\n# harmonic_division_point point_division_harmonique\ndisplay affichage\nvertices_abc sommets_abc\nvertices_abca sommets_abca\nline_inter inter_droite\nsingle_inter inter_unique\ncolor couleur\nlegend legende\nis_harmonic est_harmonique\nbar_plot diagramme_batons\nbarplot diagrammebatons\nhistogram histogramme\nprism prisme\nis_cospherical est_cospherique\ndot_paper papier_pointe\ngrid_paper papier_quadrille\nline_paper papier_ligne\ntriangle_paper papier_triangule\nvector vecteur\nplotarea tracer_aire\nplotproba graphe_probabiliste\nmult_c_conjugate mult_conjugue_C\nmult_conjugate mult_conjugue\ncanonical_form forme_canonique\nibpu integrer_par_parties_u\nibpdv integrer_par_parties_dv\nwhen quand\nslope pente\ntablefunc table_fonction\ntableseq table_suite\nfsolve resoudre_numerique\ninput saisir\nprint afficher\nassume supposons\nabout domaine\nbreakpoint point_arret\nwatch montrer\nrmwatch ne_plus_montrer\nrmbreakpoint suppr_point_arret\nrand alea\nInputStr saisir_chaine\nOx_2d_unit_vector vecteur_unitaire_Ox_2d\nOy_2d_unit_vector vecteur_unitaire_Oy_2d\nOx_3d_unit_vector vecteur_unitaire_Ox_3d\nOy_3d_unit_vector vecteur_unitaire_Oy_3d\nOz_3d_unit_vector vecteur_unitaire_Oz_3d\nframe_2d repere_2d\nframe_3d repere_3d\nrsolve resoudre_recurrence\nassume supposons\ncumulated_frequencies frequences_cumulees\nfrequencies frequences\nnormald loi_normale\nregroup regrouper\nosculating_circle cercle_osculateur\ncurvature courbure\nevolute developpee\nvector vecteur\n");
5550 	    in_update_lexer_localization(f,1,v,lexer_map,back_lexer_map,contextptr);
5551 	  }
5552 	  else
5553 	    CERR << "// Unable to find keyword file " << file << '\n';
5554 	}
5555       }
5556     }
5557   }
5558 #endif
5559 
5560 #if !defined NSPIRE
5561 
5562 #include "input_parser.h"
5563 
has_special_syntax(const char * s)5564     bool has_special_syntax(const char * s){
5565 #ifdef USTL
5566       ustl::pair<charptr_gen *,charptr_gen *> p=
5567 	ustl::equal_range(builtin_lexer_functions_begin(),builtin_lexer_functions_end(),
5568 		    std::pair<const char *,gen>(s,0),
5569 		    tri);
5570 #else
5571       std::pair<charptr_gen *,charptr_gen *> p=
5572 	equal_range(builtin_lexer_functions_begin(),builtin_lexer_functions_end(),
5573 		    std::pair<const char *,gen>(s,0),
5574 		    tri);
5575 #endif
5576       if (p.first!=p.second && p.first!=builtin_lexer_functions_end())
5577 	return (p.first->second.subtype!=T_UNARY_OP-256);
5578       map_charptr_gen::const_iterator i = lexer_functions().find(s);
5579       if (i==lexer_functions().end())
5580 	return false;
5581       return (i->second.subtype!=T_UNARY_OP-256);
5582     }
5583 
lexer_functions_register(const unary_function_ptr & u,const char * s,int parser_token)5584     bool lexer_functions_register(const unary_function_ptr & u,const char * s,int parser_token){
5585       map_charptr_gen::const_iterator i = lexer_functions().find(s);
5586       if (i!=lexer_functions().end())
5587 	return false;
5588       if (doing_insmod){
5589 	if (debug_infolevel) CERR << "insmod register " << s << '\n';
5590 	registered_lexer_functions().push_back(user_function(s,parser_token));
5591       }
5592       if (!builtin_lexer_functions_sorted){
5593 #ifndef STATIC_BUILTIN_LEXER_FUNCTIONS
5594 #if defined NSPIRE_NEWLIB || defined KHICAS || defined NUMWORKS
5595 	builtin_lexer_functions_begin()[builtin_lexer_functions_number]=std::pair<const char *,gen>(s,gen(u));
5596 #else
5597 	builtin_lexer_functions_begin()[builtin_lexer_functions_number].first=s;
5598 	builtin_lexer_functions_begin()[builtin_lexer_functions_number].second.type=0;
5599 	builtin_lexer_functions_begin()[builtin_lexer_functions_number].second=gen(u);
5600 #endif
5601 	if (parser_token==1)
5602 	  builtin_lexer_functions_begin()[builtin_lexer_functions_number].second.subtype=T_UNARY_OP-256;
5603 	else
5604 	  builtin_lexer_functions_begin()[builtin_lexer_functions_number].second.subtype=parser_token-256;
5605 	builtin_lexer_functions_number++;
5606 #endif
5607 	if (debug_infolevel) CERR << "insmod register builtin " << s << '\n';
5608       }
5609       else {
5610 	lexer_functions()[s] = gen(u);
5611 	if (parser_token==1)
5612 	  lexer_functions()[s].subtype=T_UNARY_OP-256;
5613 	else
5614 	  lexer_functions()[s].subtype=parser_token-256;
5615 	if (debug_infolevel) CERR << "insmod register lexer_functions " << s << '\n';
5616       }
5617       // If s is a library function name (with ::), update the library
5618       int ss=int(strlen(s)),j=0;
5619       for (;j<ss-1;++j){
5620 	if (s[j]==':' && s[j+1]==':')
5621 	  break;
5622       }
5623       if (j<ss-1){
5624 	string S(s);
5625 	string libname=S.substr(0,j);
5626 	string funcname=S.substr(j+2,ss-j-2);
5627 #ifdef USTL
5628 	ustl::map<std::string,std::vector<string> >::iterator it=library_functions().find(libname);
5629 #else
5630 	std::map<std::string,std::vector<string> >::iterator it=library_functions().find(libname);
5631 #endif
5632 	if (it!=library_functions().end())
5633 	  it->second.push_back(funcname);
5634 	else
5635 	  library_functions()[libname]=vector<string>(1,funcname);
5636       }
5637       return true;
5638     }
5639 
lexer_function_remove(const vector<user_function> & v)5640     bool lexer_function_remove(const vector<user_function> & v){
5641       vector<user_function>::const_iterator it=v.begin(),itend=v.end();
5642       map_charptr_gen::const_iterator i,iend;
5643       bool ok=true;
5644       for (;it!=itend;++it){
5645 	i = lexer_functions().find(it->s.c_str());
5646 	iend=lexer_functions().end();
5647 	if (i==iend)
5648 	  ok=false;
5649 	else
5650 	  lexer_functions().erase(it->s.c_str());
5651       }
5652       return ok;
5653     }
5654 
find_or_make_symbol(const string & s,gen & res,void * scanner,bool check38,GIAC_CONTEXT)5655     int find_or_make_symbol(const string & s,gen & res,void * scanner,bool check38,GIAC_CONTEXT){
5656       int tmpo=opened_quote(contextptr);
5657       if (tmpo & 2)
5658 	check38=false;
5659       if (s.size()==1){
5660 #ifdef GIAC_HAS_STO_38
5661 	if (0 && s[0]>='a' && s[0]<='z'){
5662 	  index_status(contextptr)=1;
5663 	  res=*tab_one_letter_idnt[s[0]-'a'];
5664 	  return T_SYMBOL;
5665 	}
5666 	if (check38 && s[0]>='a' && s[0]<='z' && calc_mode(contextptr)==38)
5667 	  giac_yyerror(scanner,invalid_name);
5668 #else
5669 	if (s[0]>='a' && s[0]<='z'){
5670 	  if (check38 && calc_mode(contextptr)==38)
5671 	    giac_yyerror(scanner,invalid_name);
5672 	  index_status(contextptr)=1;
5673 	  res=*tab_one_letter_idnt[s[0]-'a'];
5674 	  return T_SYMBOL;
5675 	}
5676 #endif
5677 	switch (s[0]){
5678 	case '+':
5679 	  res=at_plus;
5680 	  return T_UNARY_OP;
5681 	case '-':
5682 	  res=at_neg;
5683 	  return T_UNARY_OP;
5684 	case '*':
5685 	  res=at_prod;
5686 	  return T_UNARY_OP;
5687 	case '/':
5688 	  res=at_division;
5689 	  return T_UNARY_OP;
5690 	case '^':
5691 	  res=at_pow;
5692 	  return T_UNARY_OP;
5693 	}
5694       }
5695       string ts(s);
5696 #ifdef USTL
5697       ustl::map<std::string,std::string>::const_iterator trans=lexer_localization_map().find(ts);
5698       if (trans!=lexer_localization_map().end())
5699 	ts=trans->second;
5700       ustl::map<std::string,std::vector<string> >::const_iterator j=lexer_translator().find(ts);
5701       if (j!=lexer_translator().end() && !j->second.empty())
5702 	ts=j->second.back();
5703       ustl::pair<charptr_gen *,charptr_gen *> p=ustl::equal_range(builtin_lexer_functions_begin(),builtin_lexer_functions_end(),std::pair<const char *,gen>(ts.c_str(),0),tri);
5704 #else
5705       std::map<std::string,std::string>::const_iterator trans=lexer_localization_map().find(ts);
5706       if (trans!=lexer_localization_map().end())
5707 	ts=trans->second;
5708       std::map<std::string,std::vector<string> >::const_iterator j=lexer_translator().find(ts);
5709       if (j!=lexer_translator().end() && !j->second.empty())
5710 	ts=j->second.back();
5711       std::pair<charptr_gen *,charptr_gen *> p=equal_range(builtin_lexer_functions_begin(),builtin_lexer_functions_end(),std::pair<const char *,gen>(ts.c_str(),0),tri);
5712 #endif
5713       if (p.first!=p.second && p.first!=builtin_lexer_functions_end()){
5714 	if (p.first->second.subtype==T_TO-256)
5715 	  res=plus_one;
5716 	else
5717 	  res = p.first->second;
5718 	res.subtype=1;
5719 	if (builtin_lexer_functions_){
5720 #ifdef NSPIRE
5721 	  res=gen(int((*builtin_lexer_functions_())[p.first-builtin_lexer_functions_begin()]+p.first->second.val));
5722 	  res=gen(*res._FUNCptr);
5723 #else
5724 #if !defined NSPIRE_NEWLIB || defined KHICAS
5725 	  res=0;
5726 	  int pos=int(p.first-builtin_lexer_functions_begin());
5727 #if defined KHICAS && !defined x86_64
5728 	  const unary_function_ptr * at_val=*builtin_lexer_functions_[pos];
5729 #else
5730 	  size_t val=builtin_lexer_functions_[pos];
5731 	  unary_function_ptr * at_val=(unary_function_ptr *)val;
5732 #endif
5733 	  res=at_val;
5734 #if defined GIAC_HAS_STO_38 || (defined KHICAS && defined DEVICE)
5735 	  if (builtin_lexer_functions[pos]._FUNC_%2){
5736 #ifdef SMARTPTR64
5737 	    unary_function_ptr tmp=*at_val;
5738 	    tmp._ptr+=1;
5739 	    res=tmp;
5740 #else
5741 	    res._FUNC_ +=1;
5742 #endif // SMARTPTR64
5743 	  }
5744 #endif // GIAC_HAS_STO_38
5745 #else // keep this code, required for the nspire otherwise evalf(pi)=reboot
5746 	  res=gen(int(builtin_lexer_functions_[p.first-builtin_lexer_functions_begin()]+p.first->second.val));
5747 	  res=gen(*res._FUNCptr);
5748 #endif
5749 #endif
5750 	}
5751 	index_status(contextptr)=(p.first->second.subtype==T_UNARY_OP-256);
5752 	int token=p.first->second.subtype;
5753 	token += (token<0)?512:256 ;
5754 	return token;
5755       }
5756       lexer_tab_int_type tst={ts.c_str(),0,0,0,0};
5757 #ifdef USTL
5758       ustl::pair<const lexer_tab_int_type *,const lexer_tab_int_type *> pp = ustl::equal_range(lexer_tab_int_values,lexer_tab_int_values_end,tst,tri1);
5759 #else
5760       std::pair<const lexer_tab_int_type *,const lexer_tab_int_type *> pp = equal_range(lexer_tab_int_values,lexer_tab_int_values_end,tst,tri1);
5761 #endif
5762       if (pp.first!=pp.second && pp.first!=lexer_tab_int_values_end){
5763 	index_status(contextptr)=pp.first->status;
5764 	res=int(pp.first->value);
5765 	res.subtype=pp.first->subtype;
5766 	return pp.first->return_value;
5767       }
5768       // CERR << "lexer_functions search " << ts << '\n';
5769       map_charptr_gen::const_iterator i = lexer_functions().find(ts.c_str());
5770       if (i!=lexer_functions().end()){
5771 	// CERR << "lexer_functions found " << ts << '\n';
5772 	if (i->second.subtype==T_TO-256)
5773 	  res=plus_one;
5774 	else
5775 	  res = i->second;
5776 	res.subtype=1;
5777 	index_status(contextptr)=(i->second.subtype==T_UNARY_OP-256);
5778 	return i->second.subtype+256 ;
5779       }
5780       lock_syms_mutex();
5781       sym_string_tab::const_iterator i2 = syms().find(s),i2end=syms().end();
5782       if (i2 == i2end) {
5783 	unlock_syms_mutex();
5784 	const char * S = s.c_str();
5785 	// std::CERR << "lexer new" << s << '\n';
5786 	if (check38 && calc_mode(contextptr)==38 && strcmp(S,string_pi) && strcmp(S,string_euler_gamma) && strcmp(S,string_infinity) && strcmp(S,string_undef) && S[0]!='G'&& (!is_known_name_38 || !is_known_name_38(0,S))){
5787 	  // detect invalid names and implicit multiplication
5788 	  size_t ss=strlen(S);
5789 	  vecteur args;
5790 	  for (size_t i=0;i<ss;++i){
5791 	    char ch=S[i];
5792 	    if (ch=='C' || (ch>='E' && ch<='H') || ch=='L' || ch=='M' || ch=='R'
5793 		/* || ch=='S' */
5794 		|| ch=='U' || ch=='V' || (ch>='X' && ch<='Z') ){
5795 	      string name;
5796 	      name += ch;
5797 	      char c=0;
5798 	      if (i<ss-1)
5799 		c=s[i+1];
5800 	      if (c>='0' && c<='9'){
5801 		name += c;
5802 		++i;
5803 	      }
5804 	      res = identificateur(name);
5805 	      lock_syms_mutex();
5806 	      syms()[name] = res;
5807 	      unlock_syms_mutex();
5808 	      args.push_back(res);
5809 	    }
5810 	    else {
5811 	      string coeff;
5812 	      for (++i;i<ss;++i){
5813 		// up to next alphabetic char
5814 		if (s[i]>32 && isalpha(s[i])){
5815 		  --i;
5816 		  break;
5817 		}
5818 		if (scanner && (s[i]<0 || s[i]>'z')){
5819 		  giac_yyerror(scanner,invalid_name);
5820 		  res=undef;
5821 		  return T_SYMBOL;
5822 		}
5823 		coeff += s[i];
5824 	      }
5825 	      if (coeff.empty())
5826 		res=1;
5827 	      else
5828 		res=strtod(coeff.c_str(),0);
5829 	      if (ch=='i')
5830 		res=res*cst_i;
5831 	      else {
5832 		if (ch=='e')
5833 		  res=std::exp(1.0)*res;
5834 		else {
5835 		  // Invalid ident name, report error
5836 		  if ( (ch>'Z' || ch<0) && scanner){
5837 		    giac_yyerror(scanner,invalid_name);
5838 		    res=undef;
5839 		    return T_SYMBOL;
5840 		  }
5841 		  coeff=string(1,ch);
5842 		  gen tmp = identificateur(coeff);
5843 		  // syms()[coeff.c_str()]=tmp;
5844 		  res=res*tmp;
5845 		}
5846 	      }
5847 	      args.push_back(res);
5848 	    }
5849 	  }
5850 	  if (args.size()==1)
5851 	    res=args.front();
5852 	  else
5853 	    res=_prod(args,contextptr);
5854 	  lock_syms_mutex();
5855 	  syms()[s]=res;
5856 	  unlock_syms_mutex();
5857 	  return T_SYMBOL;
5858 	} // end 38 compatibility mode
5859 	res = identificateur(s);
5860 	lock_syms_mutex();
5861 	syms()[s] = res;
5862 	unlock_syms_mutex();
5863 	return T_SYMBOL;
5864       } // end if ==syms.end()
5865       res = i2->second;
5866       unlock_syms_mutex();
5867       return T_SYMBOL;
5868     }
5869 
5870   // Add to the list of predefined symbols
set_lexer_symbols(const vecteur & l,GIAC_CONTEXT)5871   void set_lexer_symbols(const vecteur & l,GIAC_CONTEXT){
5872     if (initialisation_done(contextptr))
5873       return;
5874     initialisation_done(contextptr)=true;
5875     const_iterateur it=l.begin(),itend=l.end();
5876     for (; it!=itend; ++it) {
5877       if (it->type!=_IDNT)
5878 	continue;
5879       lock_syms_mutex();
5880       sym_string_tab::const_iterator i = syms().find(it->_IDNTptr->id_name),iend=syms().end();
5881       if (i==iend)
5882 	syms()[it->_IDNTptr->name()] = *it;
5883       unlock_syms_mutex();
5884     }
5885   }
5886 
replace(const string & s,char c1,char c2)5887   string replace(const string & s,char c1,char c2){
5888     string res;
5889     int l=s.size();
5890     res.reserve(l);
5891     const char * ch=s.c_str();
5892     for (int i=0;i<l;++i,++ch){
5893       res+= (*ch==c1? c2: *ch);
5894     }
5895     return res;
5896   }
5897 
remove_comment(const string & s,const string & pattern,bool rep)5898   static string remove_comment(const string & s,const string &pattern,bool rep){
5899     string res(s);
5900     for (;;){
5901       int pos1=res.find(pattern);
5902       if (pos1<0 || pos1+3>=int(res.size()))
5903 	break;
5904       int pos2=res.find(pattern,pos1+3);
5905       if (pos2<0 || pos2+3>=int(res.size()))
5906 	break;
5907       if (rep)
5908 	res=res.substr(0,pos1)+'"'+replace(res.substr(pos1+3,pos2-pos1-3),'\n',' ')+'"'+res.substr(pos2+3,res.size()-pos2-3);
5909       else
5910 	res=res.substr(0,pos1)+res.substr(pos2+3,res.size()-pos2-3);
5911     }
5912     return res;
5913   }
5914 
5915   struct int_string {
5916     int decal;
5917     std::string endbloc;
int_stringgiac::int_string5918     int_string():decal(0){}
int_stringgiac::int_string5919     int_string(int i,string s):decal(i),endbloc(s){}
5920   };
5921 
instruction_at(const string & s,int pos,int shift)5922   static bool instruction_at(const string & s,int pos,int shift){
5923     if (pos && isalphan(s[pos-1]))
5924       return false;
5925     if (pos+shift<int(s.size()) && isalphan(s[pos+shift]))
5926       return false;
5927     return true;
5928   }
5929 
convert_python(string & cur,GIAC_CONTEXT)5930   void convert_python(string & cur,GIAC_CONTEXT){
5931     bool indexshift=array_start(contextptr); //xcas_mode(contextptr)!=0 || abs_calc_mode(contextptr)==38;
5932     if (cur[0]=='_' && (cur.size()==1 || !isalpha(cur[1])))
5933       cur[0]='@'; // python shortcut for ans(-1)
5934     bool instring=cur.size() && cur[0]=='"';
5935     int openpar=0;
5936     for (int pos=1;pos<int(cur.size());++pos){
5937       char prevch=cur[pos-1],curch=cur[pos];
5938       if (curch=='"' && prevch!='\\')
5939 	instring=!instring;
5940       if (instring)
5941 	continue;
5942       if (curch=='(')
5943 	++openpar;
5944       if (curch==')')
5945 	--openpar;
5946       if (curch==',' && pos<int(cur.size()-1)){
5947 	char nextch=cur[pos+1];
5948 	if (nextch=='}' || nextch==']' || nextch==')'){
5949 	  cur.erase(cur.begin()+pos);
5950 	  continue;
5951 	}
5952       }
5953       if (curch=='}' && prevch=='{'){
5954 	cur=cur.substr(0,pos-1)+"table()"+cur.substr(pos+1,cur.size()-pos-1);
5955 	continue;
5956       }
5957       if (curch==':' && (prevch=='[' || prevch==',')){
5958 	cur.insert(cur.begin()+pos,indexshift?'1':'0');
5959 	continue;
5960       }
5961       if (curch==':' && pos<int(cur.size())-1 && cur[pos+1]!='=' && cur[pos+1]!=';'){
5962 	int posif=cur.find("if "),curpos,cursize=int(cur.size()),count=0;
5963 	// check is : for slicing?
5964 	for (curpos=pos+1;curpos<cursize;++curpos){
5965 	  if (cur[curpos]=='[')
5966 	    ++count;
5967 	  if (cur[curpos]==']')
5968 	    --count;
5969 	}
5970 	if (count==0 && posif>=0 && posif<pos){
5971 	  cur[pos]=')';
5972 	  cur.insert(cur.begin()+posif+3,'(');
5973 	  continue;
5974 	}
5975       }
5976       if ( (curch==']' && (prevch==':' || prevch==',')) ||
5977 	   (curch==',' && prevch==':') ){
5978 	cur[pos-1]='.';
5979 	cur.insert(cur.begin()+pos,'.');
5980 	++pos;
5981 	if (indexshift)
5982 	  cur.insert(cur.begin()+pos,'0');
5983 	else {
5984 	  cur.insert(cur.begin()+pos,'1');
5985 	  cur.insert(cur.begin()+pos,'-');
5986 	}
5987 	continue;
5988       }
5989       if (curch==':' && prevch==':'){
5990 	if (pos+1<int(cur.size()) && cur[pos+1]=='-'){
5991 	  cur.insert(cur.begin()+pos,'-');
5992 	  cur.insert(cur.begin()+pos+1,'1');
5993 	}
5994 	else
5995 	  cur.insert(cur.begin()+pos,'0');
5996 	continue;
5997       }
5998       if (curch=='%'){
5999 	cur.insert(cur.begin()+pos+1,'/');
6000 	++pos;
6001 	continue;
6002       }
6003       if (curch=='=' && openpar==0 && prevch!='>' && prevch!='<' && prevch!='!' && prevch!=':' && prevch!=';' && prevch!='=' && prevch!='+' && prevch!='-' && prevch!='*' && prevch!='/' && prevch!='%' && (pos==int(cur.size())-1 || (cur[pos+1]!='=' && cur[pos+1]!='<'))){
6004 	cur.insert(cur.begin()+pos,':');
6005 	++pos;
6006 	continue;
6007       }
6008       if (prevch=='/' && curch=='/' && pos>1)
6009 	cur[pos]='%';
6010     }
6011   }
6012 
glue_lines_backslash(const string & s)6013   string glue_lines_backslash(const string & s){
6014     int ss=s.size();
6015     int i=s.find('\\');
6016     if (i<0 || i>=ss)
6017       return s;
6018     string res,line;
6019     for (i=0;i<ss;++i){
6020       if (s[i]!='\n'){
6021 	line += s[i];
6022 	continue;
6023       }
6024       int ls=line.size(),j;
6025       for (j=ls-1;j>=0;--j){
6026 	if (line[j]!=' ')
6027 	  break;
6028       }
6029       if (line[j]!='\\' || (j && line[j-1]=='\\')){
6030 	res += line+'\n';
6031 	line ="";
6032       }
6033       else
6034 	line=line.substr(0,j);
6035     }
6036     return res+line;
6037   }
6038 
python_import(string & cur,int cs,int posturtle,int poscmath,int posmath,int posnumpy,int posmatplotlib,GIAC_CONTEXT)6039   static void python_import(string & cur,int cs,int posturtle,int poscmath,int posmath,int posnumpy,int posmatplotlib,GIAC_CONTEXT){
6040     if (posmatplotlib>=0 && posmatplotlib<cs){
6041       cur += "np:=numpy:;xlim(a,b):=gl_x=a..b:;ylim(a,b):=gl_y=a..b:;scatter:=scatterplot:;bar:=bar_plot:;text:=legend:;xlabel:=gl_x_axis_name:;ylabel:=gl_y_axis_name:;arrow:=vector:;boxplot:=moustache:;";
6042       posnumpy=posmatplotlib;
6043     }
6044     if (posnumpy>=0 && posnumpy<cs){
6045       static bool alertnum=true;
6046       // add python numpy shortcuts
6047       cur += "mat:=matrix:;arange:=range:;resize:=redim:;shape:=dim:;conjugate:=conj:;full:=matrix:;eye:=identity:;ones(n,c):=matrix(n,c,1):; astype:=convert:;float64:=float:;asarray:=array:;astype:=convert:;reshape(m,n,c):=matrix(n,c,flatten(m));";
6048       if (alertnum){
6049 	alertnum=false;
6050 	alert("mat:=matrix;arange:=range;resize:=redim;shape:=dim;conjugate:=conj;full:=matrix;eye:=idn;ones(n,c):=matrix(n,c,1);reshape(m,n,c):=matrix(n,c,flatten(m));",contextptr);
6051       }
6052       return;
6053     }
6054     if (posturtle>=0 && posturtle<cs){
6055       // add python turtle shortcuts
6056       static bool alertturtle=true;
6057 #ifdef KHICAS
6058       cur += "fd:=forward:;bk:=backward:; rt:=right:; lt:=left:; pos:=position:; seth:=heading:;setheading:=heading:; ";
6059 #else
6060       cur += "pu:=penup:;up:=penup:; pd:=pendown:;down:=pendown:; fd:=forward:;bk:=backward:; rt:=right:; lt:=left:; pos:=position:; seth:=heading:;setheading:=heading:; reset:=efface:;";
6061 #endif
6062       if (alertturtle){
6063 	alertturtle=false;
6064 	alert("pu:=penup;up:=penup; pd:=pendown;down:=pendown; fd:=forward;bk:=backward; rt:=right; lt:=left; pos:=position; seth:=heading;setheading:=heading; reset:=efface",contextptr);
6065       }
6066       return;
6067     }
6068     if (poscmath>=0 && poscmath<cs){
6069       // add python cmath shortcuts
6070       static bool alertcmath=true;
6071       if (alertcmath){
6072 	alertcmath=false;
6073 	alert(gettext("Assigning phase, j, J and rect."),contextptr);
6074       }
6075       cur += "phase:=arg:;j:=i:;J:=i:;rect(r,theta):=r*exp(i*theta):;";
6076       posmath=poscmath;
6077     }
6078     if (posmath>=0 && posmath<cs){
6079       // add python math shortcuts
6080       static bool alertmath=true;
6081       if (alertmath){
6082 	alertmath=false;
6083 	alert(gettext("Assigning gamma, fabs. Not supported: copysign."),contextptr);
6084       }
6085       cur += "gamma:=Gamma:;fabs:=abs:;";
6086     }
6087   }
6088 
replace_deuxpoints_egal(const string & s)6089   string replace_deuxpoints_egal(const string & s){
6090     string res;
6091     int instring=0;
6092     for (size_t i=0;i<s.size();++i){
6093       char ch=s[i];
6094       if (i==0 || s[i-1]!='\\'){
6095 	if (ch=='\''){
6096 	  if (instring==2)
6097 	    res += ch;
6098 	  else {
6099 	    res +='"';
6100 	    instring=instring?0:1;
6101 	  }
6102 	  continue;
6103 	}
6104 	if (instring){
6105 	  if (ch=='"'){
6106 	    if (instring==1)
6107 	      res +="\"\"";
6108 	    else {
6109 	      res += ch;
6110 	      instring=0;
6111 	    }
6112 	  }
6113 	  else
6114 	    res += ch;
6115 	  continue;
6116 	}
6117 	if (ch=='"'){
6118 	  res +='"';
6119 	  instring=2;
6120 	  continue;
6121 	}
6122       }
6123       switch (ch){
6124       case ':':
6125 	res +="-/-";
6126 	break;
6127       case '{':
6128 	res += "{/";
6129 	break;
6130       case '}':
6131 	res += "/}";
6132 	break;
6133       default:
6134 	res += ch;
6135       }
6136     }
6137     return res;
6138   }
6139 
6140   // detect Python like syntax:
6141   // remove """ """ docstrings and ''' ''' comments
6142   // cut string in lines, remove comments at the end (search for #)
6143   // warning don't take care of # inside strings
6144   // if a line of s ends with a :
6145   // search for matching def/for/if/else/while
6146   // stores matching end keyword in a stack as a vector<[int,string]>
6147   // int is the number of white spaces at the start of the next line
6148   // def ... : -> function [ffunction]
6149   // for ... : -> for ... do [od]
6150   // while ... : -> while ... do [od]
6151   // if ...: -> if ... then [fi]
6152   // else: -> else [nothing in stack]
6153   // elif ...: -> elif ... then [nothing in stack]
6154   // try: ... except: ...
python2xcas(const std::string & s_orig,GIAC_CONTEXT)6155   std::string python2xcas(const std::string & s_orig,GIAC_CONTEXT){
6156     if (xcas_mode(contextptr)>0 && abs_calc_mode(contextptr)!=38)
6157       return s_orig;
6158     // quick check for python-like syntax: search line ending with :
6159     int first=0,sss=s_orig.size();
6160     first=s_orig.find("maple_mode");
6161     if (first>=0 && first<sss)
6162       return s_orig;
6163     first=s_orig.find("xcas_mode");
6164     if (first>=0 && first<sss)
6165       return s_orig;
6166     first=s_orig.find('\n');
6167     if (first<0 || first>=sss){
6168       first=s_orig.find('\''); // derivative or Python string delimiter?
6169       if (first>=0 && first<sss){
6170 	if (first==sss-1 || s_orig[first+1]=='\'') // '' is a second derivative
6171 	  return s_orig;
6172 	first=s_orig.find('\'',first+1);
6173 	if (first<0 || first>=sss)
6174 	  return s_orig;
6175       }
6176     }
6177     bool pythoncompat=python_compat(contextptr);
6178     bool pythonmode=false;
6179     first=0;
6180     if (sss>19 && s_orig.substr(first,17)=="add_autosimplify(")
6181       first+=17;
6182     if (s_orig[first]=='/' )
6183       return s_orig;
6184     //if (sss>first+2 && s_orig[first]=='@' && s_orig[first+1]!='@') return s_orig.substr(first+1,sss-first-1);
6185     if (sss>first+2 && s_orig.substr(first,2)=="@@"){
6186       pythonmode=true;
6187       pythoncompat=true;
6188     }
6189     if (s_orig[first]=='#' || (s_orig[first]=='_' && !isalpha(s_orig[first+1])) || s_orig.substr(first,4)=="from" || s_orig.substr(first,7)=="import "){
6190       pythonmode=true;
6191       pythoncompat=true;
6192     }
6193     if (pythoncompat){
6194       int pos=s_orig.find("{");
6195       if (pos>=0 && pos<sss)
6196 	pythonmode=true;
6197       pos=s_orig.find("}");
6198       if (pos>=0 && pos<sss)
6199 	pythonmode=true;
6200       pos=s_orig.find("//");
6201       if (pos>=0 && pos<sss)
6202 	pythonmode=true;
6203       pos=s_orig.find(":");
6204       if (pos>=0 && pos<sss-1 && s_orig[pos+1]!=';')
6205 	pythonmode=true;
6206     }
6207     for (first=0;!pythonmode && first<sss;){
6208       int pos=s_orig.find(":]");
6209       if (pos>=0 && pos<sss){
6210 	pythonmode=true;
6211 	break;
6212       }
6213       pos=s_orig.find("[:");
6214       if (pos>=0 && pos<sss){
6215 	pythonmode=true;
6216 	break;
6217       }
6218       pos=s_orig.find(",:");
6219       if (pos>=0 && pos<sss){
6220 	pythonmode=true;
6221 	break;
6222       }
6223       pos=s_orig.find(":,");
6224       if (pos>=0 && pos<sss){
6225 	pythonmode=true;
6226 	break;
6227       }
6228       pos=s_orig.find('#',0);
6229       if (pos<0 || pos>=sss){
6230 	first=s_orig.find(':',first);
6231 	if (first<0 || first>=sss){
6232 	  return s_orig; // not Python like
6233 	}
6234       }
6235       pos=s_orig.find("lambda");
6236       if (pos>=0 && pos<sss)
6237 	break;
6238       int endl=s_orig.find('\n',first);
6239       if (endl<0 || endl>=sss)
6240 	endl=sss;
6241       ++first;
6242       if (first<endl && (s_orig[first]==';' || s_orig[first]=='='))
6243 	continue; // ignore :;
6244       // search for line finishing with : (or with # comment)
6245       for (;first<endl;++first){
6246 	char ch=s_orig[first];
6247 	if (ch!=' '){
6248 	  if (ch=='#')
6249 	    first=endl;
6250 	  break;
6251 	}
6252       }
6253       if (first==endl)
6254 	break;
6255     }
6256     // probably Python-like
6257     string res;
6258     res.reserve(6*s_orig.size()/5);
6259     res=s_orig;
6260     if (res.size()>18 && res.substr(0,17)=="add_autosimplify("
6261 	&& res[res.size()-1]==')'
6262 	)
6263       res=res.substr(17,res.size()-18);
6264     if (res.size()>2 && res.substr(0,2)=="@@")
6265       res=res.substr(2,res.size()-2);
6266     res=remove_comment(res,"\"\"\"",true);
6267     res=remove_comment(res,"'''",true);
6268     res=glue_lines_backslash(res);
6269     vector<int_string> stack;
6270     string s,cur;
6271     s.reserve(res.capacity());
6272     if (pythoncompat) pythonmode=true;
6273     for (;res.size();){
6274       int pos=-1;
6275       bool cherche=true;
6276       for (;cherche;){
6277 	pos=res.find('\n',pos+1);
6278 	if (pos<0 || pos>=int(res.size()))
6279 	  break;
6280 	cherche=false;
6281 	char ch=0;
6282 	// check if we should skip to next newline, look at previous non space
6283 	for (int pos2=0;pos2<pos;++pos2){
6284 	  ch=res[pos2];
6285 	  if (ch=='#')
6286 	    break;
6287 	}
6288 	if (ch=='#')
6289 	  break;
6290 	for (int pos2=pos-1;pos2>=0;--pos2){
6291 	  ch=res[pos2];
6292 	  if (ch!=' ' && ch!=9){
6293 	    if (ch=='{' || ch=='[' || ch==',' || ch=='-' || ch=='+' ||  ch=='/')
6294 	      cherche=true;
6295 	    break;
6296 	  }
6297 	}
6298 	for (size_t pos2=pos+1;pos2<res.size();++pos2){
6299 	  ch=res[pos2];
6300 	  if (ch!=' ' && ch!=9){
6301 	    if (ch==']' || ch=='}' || ch==')')
6302 	      cherche=true;
6303 	    break;
6304 	  }
6305 	}
6306       }
6307       if (pos<0 || pos>=int(res.size())){
6308 	cur=res; res="";
6309       }
6310       else {
6311 	cur=res.substr(0,pos); // without \n
6312 	res=res.substr(pos+1,res.size()-pos-1);
6313       }
6314       // detect comment (outside of a string) and lambda expr:expr
6315       bool instring=false,chkfrom=true;
6316       for (pos=0;pos<int(cur.size());++pos){
6317 	char ch=cur[pos];
6318 	if (ch==' ' || ch==char(9))
6319 	  continue;
6320 	if (!instring && pythoncompat && ch=='{' && (pos==0 || cur[pos-1]!='\\')){
6321 	  // find matching }, counting : and , and ;
6322 	  int c1=0,c2=0,c3=0,cs=int(cur.size()),p;
6323 	  for (p=pos;p<cs;++p){
6324 	    char ch=cur[p];
6325 	    if (ch=='}' && cur[p-1]!='\\')
6326 	      break;
6327 	    if (ch==':')
6328 	      ++c1;
6329 	    if (ch==',')
6330 	      ++c2;
6331 	    if (ch==';')
6332 	      ++c3;
6333 	  }
6334 	  if (p<cs
6335 	      //&& c1
6336 	      && c3==0){
6337 	    // table initialization, replace {} by table( ) ,
6338 	    // cur=cur.substr(0,pos)+"table("+cur.substr(pos+1,p-pos-1)+")"+cur.substr(p+1,cs-pos-1);
6339 	    cur=cur.substr(0,pos)+"{/"+replace_deuxpoints_egal(cur.substr(pos+1,p-1-pos))+"/}"+cur.substr(p+1,cs-pos-1);
6340 	  }
6341 	}
6342 	if (!instring && pythoncompat &&
6343 	    ch=='\'' && pos<cur.size()-2 && cur[pos+1]!='\\' && (pos==0 || (cur[pos-1]!='\\' && cur[pos-1]!='\''))){ // workaround for '' string delimiters
6344 	  static bool alertstring=true;
6345 	  if (alertstring){
6346 	    alert("// Python compatibility, please use \"...\" for strings",contextptr);
6347 	    alertstring=false;
6348 	  }
6349 	  int p=pos,q=pos+1,beg; // skip spaces
6350 	  for (p++;p<int(cur.size());++p)
6351 	    if (cur[p]!=' ')
6352 	      break;
6353 	  if (p!=cur.size()){
6354 	    // find matching '
6355 	    beg=q;
6356 	    for (;p<int(cur.size());++p)
6357 	      if (cur[p]=='\'')
6358 		break;
6359 	    if (p>0 && p<int(cur.size())){
6360 	      --p;
6361 	      // does cur[pos+1..p-1] look like a string?
6362 	      bool str=!isalpha(cur[q]) || !isalphan(cur[p]);
6363 	      if (p && cur[p]=='.' && cur[p-1]>'9')
6364 		str=true;
6365 	      if (p-q>=minchar_for_quote_as_string(contextptr))
6366 		str=true;
6367 	      for (;!str && q<p;++q){
6368 		char ch=cur[q];
6369 		if (ch=='"' || ch==' ')
6370 		  str=true;
6371 	      }
6372 	      if (str){ // replace delimiters with " and " inside by \"
6373 		string rep("\"");
6374 		for (q=beg;q<=p;++q){
6375 		  if (cur[q]!='"')
6376 		    rep+=cur[q];
6377 		  else
6378 		    rep+="\\\"";
6379 		}
6380 		rep += '"';
6381 		cur=cur.substr(0,pos)+rep+cur.substr(p+2,cur.size()-(p+2));
6382 		ch=cur[pos];
6383 	      }
6384 	    }
6385 	  }
6386 	}
6387 	if (ch=='"' && (pos==0 || cur[pos-1]!='\\')){
6388 	  chkfrom=false;
6389 	  instring=!instring;
6390 	}
6391 	if (instring)
6392 	  continue;
6393 	if (ch=='#'){
6394 	  // workaround to declare local variables
6395 	  if (cur.size()>pos+8 && (cur.substr(pos,8)=="# local " || cur.substr(pos,7)=="#local ")){
6396 	    cur.erase(cur.begin()+pos);
6397 	    if (cur[pos]==' ')
6398 	      cur.erase(cur.begin()+pos);
6399 	  }
6400 	  else
6401 	    cur=cur.substr(0,pos);
6402 	  pythonmode=true;
6403 	  break;
6404 	}
6405 	// skip from * import *
6406 	if (chkfrom && ch=='f' && pos+15<int(cur.size()) && cur.substr(pos,5)=="from "){
6407 	  chkfrom=false;
6408 	  int posi=cur.find(" import ");
6409 	  if (posi<0 || posi>=int(cur.size()))
6410 	    posi = cur.find(" import*");
6411 	  if (posi>pos+5 && posi<int(cur.size())){
6412 	    int posturtle=cur.find("turtle");
6413 	    int poscmath=cur.find("cmath");
6414 	    int posmath=cur.find("math");
6415 	    int posnumpy=cur.find("numpy");
6416 	    int posmatplotlib=cur.find("matplotlib");
6417 	    if (posmatplotlib<0 || posmatplotlib>=cur.size())
6418 	      posmatplotlib=cur.find("pylab");
6419 	    int cs=int(cur.size());
6420 	    pythonmode=true;
6421 #ifdef KHICAS
6422 	    if (
6423 		(posturtle<0 || posturtle>=cs) &&
6424 		(poscmath<0 || poscmath>=cs) &&
6425 		(posmath<0 || posmath>=cs) &&
6426 		(posnumpy<0 || posnumpy>=cs) &&
6427 		(posmatplotlib<0 || posmatplotlib>=cs)
6428 		){
6429 	      string filename=cur.substr(pos+5,posi-pos-5)+".py";
6430 	      // CERR << "import " << filename << endl;
6431 	      const char * ptr=read_file(filename.c_str());
6432 	      if (ptr)
6433 		s += python2xcas(ptr,contextptr); // recursive call
6434 	      cur ="";
6435 	      // CERR << s << endl;
6436 	      continue;
6437 	    }
6438 	    else
6439 #endif
6440 	      {
6441 		cur=cur.substr(0,pos);
6442 		python_import(cur,cs,posturtle,poscmath,posmath,posnumpy,posmatplotlib,contextptr);
6443 	      }
6444 	    break;
6445 	  }
6446 	}
6447 	chkfrom=false;
6448 	// import * as ** -> **:=*
6449 	if (ch=='i' && pos+7<int(cur.size()) && cur.substr(pos,7)=="import "){
6450 	  int posturtle=cur.find("turtle");
6451 	  int poscmath=cur.find("cmath");
6452 	  int posmath=cur.find("math");
6453 	  int posnumpy=cur.find("numpy");
6454 	  int posmatplotlib=cur.find("matplotlib");
6455 	  if (posmatplotlib<0 || posmatplotlib>=cur.size())
6456 	    posmatplotlib=cur.find("pylab");
6457 	  int cs=int(cur.size());
6458 	  int posi=cur.find(" as ");
6459 	  int posp=cur.find('.');
6460 	  if (posp>=posi || posp<0)
6461 	    posp=posi;
6462 	  if (posi>pos+5 && posi<int(cur.size())){
6463 	    cur=cur.substr(posi+4,cur.size()-posi-4)+":="+cur.substr(pos+7,posp-(pos+7))+';';
6464 	  }
6465 	  else
6466 	    cur=cur.substr(pos+7,cur.size()-pos-7);
6467 	  for (int i=0;i<pos;++i)
6468 	    cur = ' '+cur;
6469 	  python_import(cur,cs,posturtle,poscmath,posmath,posnumpy,posmatplotlib,contextptr);
6470 	  pythonmode=true;
6471 	  break;
6472 	}
6473 	if (ch=='l' && pos+6<int(cur.size()) && cur.substr(pos,6)=="lambda" && instruction_at(cur,pos,6)){
6474 	  int posdot=cur.find(':',pos);
6475 	  if (posdot>pos+7 && posdot<int(cur.size())-1 && cur[posdot+1]!='=' && cur[posdot+1]!=';'){
6476 	    pythonmode=true;
6477 	    cur=cur.substr(0,pos)+"("+cur.substr(pos+6,posdot-pos-6)+")->"+cur.substr(posdot+1,cur.size()-posdot-1);
6478 	  }
6479 	}
6480 	if (ch=='e' && pos+4<int(cur.size()) && cur.substr(pos,3)=="end" && instruction_at(cur,pos,3)){
6481 	  // if next char after end is =, replace by endl
6482 	  for (size_t tmp=pos+3;tmp<cur.size();++tmp){
6483 	    if (cur[tmp]!=' '){
6484 	      if (cur[tmp]=='=')
6485 		cur.insert(cur.begin()+pos+3,'l');
6486 	      break;
6487 	    }
6488 	  }
6489 	}
6490       }
6491       if (instring){
6492 	*logptr(contextptr) << "Warning: multi-line strings can not be converted from Python like syntax"<<'\n';
6493 	return s_orig;
6494       }
6495       // detect : at end of line
6496       for (pos=int(cur.size())-1;pos>=0;--pos){
6497 	if (cur[pos]!=' ' && cur[pos]!=char(9))
6498 	  break;
6499       }
6500       if (pos<0){
6501 	s+='\n';
6502 	continue;
6503       }
6504       if (cur[pos]!=':'){ // detect oneliner and function/fonction
6505 	int p;
6506 	for (p=0;p<pos;++p){
6507 	  if (cur[p]!=' ')
6508 	    break;
6509 	}
6510 	if (p<pos-8 && (cur.substr(p,8)=="function" || cur.substr(p,8)=="fonction")){
6511 	  s = s+cur+'\n';
6512 	  continue;
6513 	}
6514 	bool instr=false;
6515 	for (p=pos;p>0;--p){
6516 	  if (instr){
6517 	    if (cur[p]=='"' && cur[p-1]!='\\')
6518 	      instr=false;
6519 	    continue;
6520 	  }
6521 	  if (cur[p]==':' && (cur[p+1]!=';' && cur[p+1]!='='))
6522 	    break;
6523 	  if (cur[p]=='"' && cur[p-1]!='\\')
6524 	    instr=true;
6525 	}
6526 	if (p==0){
6527 	  // = or return expr if cond else alt_expr => ifte(cond,expr,alt_expr)
6528 	  int cs=int(cur.size());
6529 	  int elsepos=cur.find("else");
6530 	  if (elsepos>0 && elsepos<cs){
6531 	    int ifpos=cur.find("if");
6532 	    if (ifpos>0 && ifpos<elsepos){
6533 	      int retpos=cur.find("return"),endretpos=retpos+6;
6534 	      if (retpos<0 || retpos>=cs){
6535 		retpos=cur.find("=");
6536 		endretpos=retpos+1;
6537 	      }
6538 	      if (retpos>=0 && retpos<ifpos){
6539 		cur=cur.substr(0,endretpos)+" ifte("+cur.substr(ifpos+2,elsepos-ifpos-2)+","+cur.substr(endretpos,ifpos-endretpos)+","+cur.substr(elsepos+4,cs-elsepos-4)+")";
6540 	      }
6541 	    }
6542 	  }
6543 	}
6544 	if (p>0){
6545 	  int cs=int(cur.size()),q=4;
6546 	  int progpos=cur.find("elif");;
6547 	  if (progpos<0 || progpos>=cs){
6548 	    progpos=cur.find("if");
6549 	    q=2;
6550 	  }
6551 	  if (p && progpos>=0 && progpos<cs && instruction_at(cur,progpos,q)){
6552 	    pythonmode=true;
6553 #if 1
6554 	    res = cur.substr(0,p)+":\n"+string(progpos+4,' ')+cur.substr(p+1,pos-p)+'\n'+res;
6555 	    continue;
6556 #else
6557 	    cur=cur.substr(0,p)+" then "+cur.substr(p+1,pos-p);
6558 	    convert_python(cur,contextptr);
6559 	    // no fi if there is an else or elif
6560 	    for (p=0;p<int(res.size());++p){
6561 	      if (res[p]!=' ' && res[p]!=char(9))
6562 		break;
6563 	    }
6564 	    if (p<res.size()+5 && (res.substr(p,4)=="else" || res.substr(p,4)=="elif")){
6565 	      cur += " ";
6566 	    }
6567 	    else
6568 	      cur += " fi";
6569 	    p=0;
6570 #endif
6571 	  }
6572 	  progpos=cur.find("else");
6573 	  if (p && progpos>=0 && progpos<cs && instruction_at(cur,progpos,4)){
6574 	    pythonmode=true;
6575 #if 1
6576 	    res = cur.substr(0,p)+":\n"+string(progpos+4,' ')+cur.substr(p+1,pos-p)+'\n'+res;
6577 	    continue;
6578 #else
6579 	    cur=cur.substr(0,p)+' '+cur.substr(p+1,pos-p)+" fi";
6580 	    convert_python(cur,contextptr);
6581 	    p=0;
6582 #endif
6583 	  }
6584 	  progpos=cur.find("for");
6585 	  if (p && progpos>=0 && progpos<cs && instruction_at(cur,progpos,3)){
6586 	    pythonmode=true;
6587 	    cur=cur.substr(0,p)+" do "+cur.substr(p+1,pos-p);
6588 	    convert_python(cur,contextptr);
6589 	    cur += " od";
6590 	    p=0;
6591 	  }
6592 	  progpos=cur.find("while");
6593 	  if (p && progpos>=0 && progpos<cs && instruction_at(cur,progpos,5)){
6594 	    pythonmode=true;
6595 	    cur=cur.substr(0,p)+" do "+cur.substr(p+1,pos-p);
6596 	    convert_python(cur,contextptr);
6597 	    cur += " od";
6598 	    p=0;
6599 	  }
6600 	}
6601       }
6602       // count whitespaces, compare to stack
6603       int ws=0;
6604       int cs=cur.size();
6605       for (ws=0;ws<cs;++ws){
6606 	if (cur[ws]!=' ' && cur[ws]!=char(9))
6607 	  break;
6608       }
6609       if (cur[pos]==':'){
6610 	// detect else or elif or except
6611 	int progpos=cur.find("else");
6612 	if (progpos>=0 && progpos<cs && instruction_at(cur,progpos,4)){
6613 	  pythonmode=true;
6614 	  if (stack.size()>1){
6615 	    int indent=stack[stack.size()-1].decal;
6616 	    if (ws<indent){
6617 	      // remove last \n and add explicit endbloc delimiters from stack
6618 	      int ss=s.size();
6619 	      bool nl= ss && s[ss-1]=='\n';
6620 	      if (nl)
6621 		s=s.substr(0,ss-1);
6622 	      while (stack.size()>1 && stack[stack.size()-1].decal>ws){
6623 		s += ' '+stack.back().endbloc+';';
6624 		stack.pop_back();
6625 	      }
6626 	      if (nl)
6627 		s += '\n';
6628 	    }
6629 	  }
6630 	  s += cur.substr(0,pos)+"\n";
6631 	  continue;
6632 	}
6633 	progpos=cur.find("except");
6634 	if (progpos>=0 && progpos<cs && instruction_at(cur,progpos,6)){
6635 	  pythonmode=true;
6636 	  if (stack.size()>1){
6637 	    int indent=stack[stack.size()-1].decal;
6638 	    if (ws<indent){
6639 	      // remove last \n and add explicit endbloc delimiters from stack
6640 	      int ss=s.size();
6641 	      bool nl= ss && s[ss-1]=='\n';
6642 	      if (nl)
6643 		s=s.substr(0,ss-1);
6644 	      while (stack.size()>1 && stack[stack.size()-1].decal>ws){
6645 		s += ' '+stack.back().endbloc+';';
6646 		stack.pop_back();
6647 	      }
6648 	      if (nl)
6649 		s += '\n';
6650 	    }
6651 	  }
6652 	  s += cur.substr(0,progpos)+"then\n";
6653 	  continue;
6654 	}
6655 	progpos=cur.find("elif");
6656 	if (progpos>=0 && progpos<cs && instruction_at(cur,progpos,4)){
6657 	  pythonmode=true;
6658 	  if (stack.size()>1){
6659 	    int indent=stack[stack.size()-1].decal;
6660 	    if (ws<indent){
6661 	      // remove last \n and add explicit endbloc delimiters from stack
6662 	      int ss=s.size();
6663 	      bool nl= ss && s[ss-1]=='\n';
6664 	      if (nl)
6665 		s=s.substr(0,ss-1);
6666 	      while (stack.size()>1 && stack[stack.size()-1].decal>ws){
6667 		s += ' '+stack.back().endbloc+';';
6668 		stack.pop_back();
6669 	      }
6670 	      if (nl)
6671 		s += '\n';
6672 	    }
6673 	  }
6674 	  cur=cur.substr(0,pos);
6675 	  convert_python(cur,contextptr);
6676 	  s += cur+" then\n";
6677 	  continue;
6678 	}
6679       }
6680       if (!stack.empty()){
6681 	int indent=stack.back().decal;
6682 	if (ws<=indent){
6683 	  // remove last \n and add explicit endbloc delimiters from stack
6684 	  int ss=s.size();
6685 	  bool nl= ss && s[ss-1]=='\n';
6686 	  if (nl)
6687 	    s=s.substr(0,ss-1);
6688 	  while (!stack.empty() && stack.back().decal>=ws){
6689 	    int sb=stack.back().decal;
6690 	    s += ' '+stack.back().endbloc+';';
6691 	    stack.pop_back();
6692 	    // indent must match one of the saved indent
6693 	    if (sb!=ws && !stack.empty() && stack.back().decal<ws){
6694 	      return "\"Bad indentation at "+cur+"\"";
6695 	    }
6696 	  }
6697 	  if (nl)
6698 	    s += '\n';
6699 	}
6700       }
6701       if (cur[pos]==':'){
6702 	// detect matching programming structure
6703 	int progpos=cur.find("if");
6704 	if (progpos>=0 && progpos<cs && instruction_at(cur,progpos,2)){
6705 	  pythonmode=true;
6706 	  cur=cur.substr(0,pos);
6707 	  convert_python(cur,contextptr);
6708 	  s += cur +" then\n";
6709 	  stack.push_back(int_string(ws,"fi"));
6710 	  continue;
6711 	}
6712 	progpos=cur.find("try");
6713 	if (progpos>=0 && progpos<cs && instruction_at(cur,progpos,3)){
6714 	  pythonmode=true;
6715 	  cur=cur.substr(0,progpos);
6716 	  convert_python(cur,contextptr);
6717 	  s += cur +"IFERR\n";
6718 	  stack.push_back(int_string(ws,"end"));
6719 	  continue;
6720 	}
6721 	progpos=cur.find("for");
6722 	if (progpos>=0 && progpos<cs && instruction_at(cur,progpos,3)){
6723 	  pythonmode=true;
6724 	  // for _ -> for x_
6725 	  cur=cur.substr(0,pos);
6726 	  if (progpos+5<cs && cur[progpos+3]==' ' && cur[progpos+4]=='_' && cur[progpos+5]==' '){
6727 	    cur.insert(cur.begin()+progpos+4,'x');
6728 	  }
6729 	  convert_python(cur,contextptr);
6730 	  s += cur+" do\n";
6731 	  stack.push_back(int_string(ws,"od"));
6732 	  continue;
6733 	}
6734 	progpos=cur.find("while");
6735 	if (progpos>=0 && progpos<cs && instruction_at(cur,progpos,5)){
6736 	  pythonmode=true;
6737 	  cur=cur.substr(0,pos);
6738 	  convert_python(cur,contextptr);
6739 	  s += cur +" do\n";
6740 	  stack.push_back(int_string(ws,"od"));
6741 	  continue;
6742 	}
6743 	progpos=cur.find("def");
6744 	if (progpos>=0 && progpos<cs && instruction_at(cur,progpos,3)){
6745 	  pythonmode=true;
6746 	  if (abs_calc_mode(contextptr)==38) python_compat(1,contextptr);
6747 	  pythoncompat=true;
6748 	  // should remove possible returned type, between -> ... and :
6749 	  string entete=cur.substr(progpos+3,pos-progpos-3);
6750 	  int posfleche=entete.find("->");
6751 	  if (posfleche>0 || posfleche<entete.size())
6752 	    entete=entete.substr(0,posfleche);
6753 	  s += cur.substr(0,progpos)+"function"+entete+"\n";
6754 	  stack.push_back(int_string(ws,"ffunction:")); // ; added later
6755 	  continue;
6756 	}
6757 	// no match found, return s
6758 	s = s+cur;
6759       }
6760       else {
6761 	// normal line add ; at end
6762 	char curpos=cur[pos];
6763 	if (pythonmode && !res.empty() && pos>=0 && curpos!=';' && curpos!=',' && curpos!='{' && curpos!='(' && curpos!='[' && curpos!=':' && curpos!='+' && curpos!='-' && curpos!='*' && curpos!='/' && curpos!='%')
6764 	  cur = cur +';';
6765 	if (pythonmode)
6766 	  convert_python(cur,contextptr);
6767 	cur = cur +'\n';
6768 	s = s+cur;
6769       }
6770     }
6771     while (!stack.empty()){
6772       s += ' '+stack.back().endbloc+';';
6773       stack.pop_back();
6774     }
6775     if (pythonmode){
6776       char ch;
6777       while ((ch=s[s.size()-1])==';' || (ch=='\n'))
6778 	s=s.substr(0,s.size()-1);
6779       // replace ;) by )
6780       for (int i=s.size()-1;i>=2;--i){
6781 	if (s[i]==')' && s[i-1]=='\n' && s[i-2]==';'){
6782 	  s.erase(s.begin()+i-2);
6783 	  break;
6784 	}
6785       }
6786       if (s.size()>10 && s.substr(s.size()-9,9)=="ffunction")
6787 	s += ":;";
6788       else {
6789 	int pos=s.find('\n');
6790 	if (pos>=0 && pos<s.size())
6791 	  s += ";";
6792       }
6793       if (debug_infolevel)
6794 	*logptr(contextptr) << "Translated to Xcas as:\n" << s << '\n';
6795     }
6796     res.clear(); cur.clear();
6797     // CERR << s << endl;
6798     return string(s.begin(),s.end());
6799   }
6800 
translate_at(const char * ch)6801     std::string translate_at(const char * ch){
6802       if (!strcmp(ch,"∡"))
6803 	return "polar_complex";
6804       if (!strcmp(ch,"."))
6805 	return "struct_dot";
6806       if (!strcmp(ch,"LINEAR?"))
6807 	return "IS_LINEAR";
6808       if (!strcmp(ch,"ΔLIST"))
6809 	return "DELTALIST";
6810       if (!strcmp(ch,"ΠLIST"))
6811 	return "PILIST";
6812       if (!strcmp(ch,"ΣLIST"))
6813 	return "SIGMALIST";
6814       if (!strcmp(ch,"∫"))
6815 	return "HPINT";
6816       if (!strcmp(ch,"∂"))
6817 	return "HPDIFF";
6818       if (!strcmp(ch,"Σ"))
6819 	return "HPSUM";
6820       if (!strcmp(ch,"∑"))
6821 	return "HPSUM";
6822       string res;
6823       for (;*ch;++ch){
6824         if (*ch=='%')
6825           res +="PERCENT";
6826         else
6827           res += *ch;
6828       }
6829       return res;
6830     }
6831 
6832     bool builtin_lexer_functions_sorted = false;
6833 
lexer_functions()6834     map_charptr_gen & lexer_functions(){
6835       static map_charptr_gen * ans=0;
6836       if (!ans){
6837 	ans = new map_charptr_gen;
6838 	doing_insmod=false;
6839 	builtin_lexer_functions_sorted=false;
6840       }
6841       return * ans;
6842     }
6843 
6844 
6845 #ifdef STATIC_BUILTIN_LEXER_FUNCTIONS
6846 
6847     const charptr_gen_unary builtin_lexer_functions[] ={
6848 #if defined(GIAC_HAS_STO_38) && defined(CAS38_DISABLED)
6849 #include "static_lexer_38.h"
6850 #else
6851 #if defined KHICAS || defined NSPIRE_NEWLIB
6852 #include "static_lexer_numworks.h"
6853 #else
6854 #include "static_lexer.h"
6855 #endif // KHICAS
6856 #endif
6857     };
6858 
6859     const unsigned builtin_lexer_functions_number=sizeof(builtin_lexer_functions)/sizeof(charptr_gen_unary);
6860     // return true/false to tell if s is recognized. return the appropriate gen if true
6861 #ifdef NSPIRE
builtin_lexer_functions_()6862     vector<size_t> * builtin_lexer_functions_(){
6863       static vector<size_t> * res=0;
6864       if (res) return res;
6865       res = new vector<size_t>;
6866       res->reserve(builtin_lexer_functions_number+1);
6867 #include "static_lexer_at.h"
6868       return res;
6869     }
6870 #else
6871     // Array added because GH compiler stores builtin_lexer_functions in RAM
6872 #if defined KHICAS || defined NSPIRE_NEWLIB
6873     const unary_function_ptr * const * const builtin_lexer_functions_[]={
6874 #include "static_lexer__numworks.h"
6875     };
6876 #else
6877     const size_t builtin_lexer_functions_[]={
6878 #if defined(GIAC_HAS_STO_38) && defined(CAS38_DISABLED)
6879 #include "static_lexer_38_.h"
6880 #else
6881 #include "static_lexer_.h"
6882 #endif
6883     };
6884 #endif // KHICAS
6885 #endif // STATIC_BUILTIN
6886 
6887 #ifdef SMARTPTR64
builtin_lexer_functions64()6888     charptr_gen * builtin_lexer_functions64(){
6889       static charptr_gen * ans=0;
6890       if (!ans){
6891 	ans = new charptr_gen[builtin_lexer_functions_number];
6892 	for (unsigned i=0;i<builtin_lexer_functions_number;i++){
6893 	  charptr_gen tmp; tmp.first=builtin_lexer_functions[i].s; tmp.second=builtin_lexer_functions[i]._FUNC_;
6894 	  tmp.second.subtype=builtin_lexer_functions[i].subtype;
6895 	  ans[i]=tmp;
6896 	}
6897       }
6898       return ans;
6899     }
6900 
builtin_lexer_functions_begin()6901     charptr_gen * builtin_lexer_functions_begin(){
6902       return (charptr_gen *) builtin_lexer_functions64();
6903     }
6904 #else
builtin_lexer_functions_begin()6905     charptr_gen * builtin_lexer_functions_begin(){
6906       return (charptr_gen *) builtin_lexer_functions;
6907     }
6908 #endif // SMARTPTR64
6909 
builtin_lexer_functions_end()6910     charptr_gen * builtin_lexer_functions_end(){
6911       return builtin_lexer_functions_begin()+builtin_lexer_functions_number;
6912     }
6913 
6914 #else
6915     unsigned builtin_lexer_functions_number;
builtin_lexer_functions()6916     charptr_gen * builtin_lexer_functions(){
6917       static charptr_gen * ans=0;
6918       if (!ans){
6919 	ans = new charptr_gen[1999];
6920 	builtin_lexer_functions_number=0;
6921       }
6922       return ans;
6923     }
6924 
builtin_lexer_functions_begin()6925     charptr_gen * builtin_lexer_functions_begin(){
6926       return builtin_lexer_functions();
6927     }
6928 
builtin_lexer_functions_end()6929     charptr_gen * builtin_lexer_functions_end(){
6930       return builtin_lexer_functions()+builtin_lexer_functions_number;
6931     }
6932 
6933     const size_t * const builtin_lexer_functions_=0;
6934 
6935 #endif
6936 
6937 #endif // NSPIRE
6938 
make_symbolic(const gen & op,const gen & args)6939   gen make_symbolic(const gen & op,const gen & args){
6940     return symbolic(*op._FUNCptr,args);
6941   }
6942 
6943   // optional, call it just before exiting
release_globals()6944   int release_globals(){
6945 #if !defined VISUALC && !defined KHICAS
6946     delete normal_sin_pi_12_ptr_();
6947     delete normal_cos_pi_12_ptr_();
6948 #endif
6949 #ifndef STATIC_BUILTIN_LEXER_FUNCTIONS
6950     if (debug_infolevel)
6951       CERR << "releasing " << builtin_lexer_functions_number << " functions" << '\n';
6952     for (int i=0;i<builtin_lexer_functions_number;++i){
6953 #ifdef SMARTPTR64
6954       if (debug_infolevel)
6955 	CERR << builtin_lexer_functions_begin()[i].first << '\n';
6956       builtin_lexer_functions_begin()[i].second=0;
6957       //delete (ref_unary_function_ptr *) (* ((ulonglong * ) &builtin_lexer_functions_begin()[i].second) >> 16);
6958 #endif
6959     }
6960 #endif
6961     delete &registered_lexer_functions();
6962     delete &lexer_functions();
6963     delete &library_functions();
6964     delete &lexer_translator();
6965     delete &back_lexer_localization_map();
6966     delete &lexer_localization_map();
6967     delete &lexer_localization_vector();
6968     delete &syms();
6969     delete &unit_conversion_map();
6970     delete &xcasrc();
6971     //delete &usual_units();
6972     if (vector_aide_ptr()) delete vector_aide_ptr();
6973     delete &symbolic_rootof_list();
6974     delete &proot_list();
6975     delete &galoisconj_list();
6976     delete &_autoname_();
6977     delete &_lastprog_name_();
6978     return 0;
6979   }
6980 
6981 #ifndef NO_NAMESPACE_GIAC
6982 } // namespace giac
6983 #endif // ndef NO_NAMESPACE_GIAC
6984