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 ®istered_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