Fix memory leak at startup / exit
[scilab.git] / scilab / modules / core / src / cpp / InitScilab.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2013 - Scilab Enterprises - Antoine ELIAS
4  * Copyright (C) 2013 - Scilab Enterprises - Cedric DELAMARRE
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 #include <string>
15 #include <libxml/parser.h>
16
17
18 #include "double.hxx"
19 #include "polynom.hxx"
20 #include "string.hxx"
21 #include "bool.hxx"
22
23 #include "scilabWrite.hxx"
24 #include "tasks.hxx"
25 #include "parser.hxx"
26 #include "context.hxx"
27 #include "configvariable.hxx"
28 #include "filemanager.hxx"
29 #include "runner.hxx"
30 #include "visitor_common.hxx"
31 #include "operations.hxx"
32
33 extern "C"
34 {
35 #include "machine.h"
36 #include "InitializeLocalization.h"
37 #include "elem_common.h"
38 #include "LaunchScilabSignal.h"
39 #include "InitializeJVM.h"
40 #include "TerminateJVM.h"
41 #include "InitializeGUI.h"
42 #include "graphicModuleLoad.h"
43 #include "TerminateGraphics.h"
44 #include "loadBackGroundClassPath.h"
45 #include "sci_tmpdir.h"
46 #include "sci_mode.h"
47 #include "setgetlanguage.h"
48 #include "InitializeConsole.h"
49 #include "InitializeHistoryManager.h"
50 #include "TerminateHistoryManager.h"
51 #include "prompt.h"
52 #include "scilabRead.h"
53 #include "functions_manager.h"
54 #include "InitScilab.h"
55 #include "setenvvar.h"
56 #include "getScilabPreference.h"
57 #include "saveCWDInPreferences.h"
58
59
60 #ifdef _MSC_VER
61 #include "InitializeWindows_tools.h"
62 #include "TerminateWindows_tools.h"
63 #include "WndThread.h"
64 #include "console.h"
65 #include "InnosetupMutex.h"
66 #include "MutexClosingScilab.h"
67 #include "WinConsole.h"
68 #else
69 #include "signal_mgmt.h"
70 #include "initConsoleMode.h"
71 #endif
72
73 #if defined(linux) && defined(__i386__)
74 #include "setPrecisionFPU.h"
75 #endif
76
77     /* Defined without include to avoid useless header dependency */
78     extern BOOL isItTheDisabledLib(void);
79 }
80
81 static void Add_i(void);
82 static void Add_pi(void);
83 static void Add_eps(void);
84 static void Add_e(void);
85 static void Add_s(void);
86 static void Add_z(void);
87 static void Add_true(void);
88 static void Add_false(void);
89 static void Add_Nan(void);
90 static void Add_Inf(void);
91 static void Add_All_Variables(void);
92 static void Add_Double_Constant(std::wstring _szName, double _dblReal, double _dblImg, bool _bComplex);
93 static void Add_Poly_Constant(std::wstring _szName, std::wstring _szPolyVar, int _iRank, types::Double * _pdblReal);
94 static void Add_Boolean_Constant(std::wstring _szName, bool _bBool);
95 static void Add_String_Constant(std::wstring _szName, const char *_pstString);
96 static void checkForLinkerErrors(void);
97
98 static int batchMain(ScilabEngineInfo* _pSEI);
99 static int InitializeEnvironnement(void);
100 static int interactiveMain(ScilabEngineInfo* _pSEI);
101 static Parser::ControlStatus processCommand(ScilabEngineInfo* _pSEI);
102 static void stateShow(Parser::ControlStatus status);
103
104 using namespace ast;
105
106 ScilabEngineInfo* InitScilabEngineInfo()
107 {
108     // Disable all startup flags.
109     ScilabEngineInfo* pSEI = (ScilabEngineInfo*)CALLOC(1, sizeof(ScilabEngineInfo));
110
111     //Active default flags
112     pSEI->iExecAst = 1;
113     pSEI->iNoBanner = 1;
114
115     return pSEI;
116 }
117
118 int StartScilabEngine(ScilabEngineInfo* _pSEI)
119 {
120     int iMainRet = 0;
121
122     /* This bug only occurs under Linux 32 bits
123      * See: http://wiki.scilab.org/Scilab_precision
124      */
125 #if defined(linux) && defined(__i386__)
126     setFPUToDouble();
127 #endif
128
129 #ifndef _MSC_VER
130     /* Management of the signals (seg fault, floating point exception, etc) */
131     if (getenv("SCI_DISABLE_EXCEPTION_CATCHING") == NULL)
132     {
133         base_error_init();
134     }
135 #endif
136
137 #if defined(netbsd) || defined(freebsd)
138     /* floating point exceptions */
139     fpsetmask(0);
140 #endif
141
142     Runner::init();
143
144     checkForLinkerErrors();
145
146 #ifdef _MSC_VER
147     //get current console window and hide it
148     int scilabMode = getScilabMode();
149     if (scilabMode == SCILAB_STD)
150     {
151         CreateScilabHiddenWndThread();
152         //show banner in console window
153         CreateScilabConsole(_pSEI->iNoBanner);
154
155         if (_pSEI->iKeepConsole == 0)
156         {
157             HideScilex(); /* hide console window */
158         }
159         else
160         {
161             ShowScilex();
162         }
163     }
164     else
165     {
166         if (scilabMode == SCILAB_NW || scilabMode == SCILAB_NWNI)
167         {
168             SaveConsoleColors();
169             if (scilabMode == SCILAB_NW)
170             {
171                 RenameConsole();
172                 UpdateConsoleColors();
173             }
174         }
175     }
176
177     //create a thread for innosetup to allow reinstall during scilab running
178     createInnosetupMutex();
179 #endif
180
181     InitializeLaunchScilabSignal();
182
183     /* Scilab Startup */
184     xmlInitParser();
185     InitializeEnvironnement();
186
187     if (_pSEI->pstLang)
188     {
189         wchar_t *pwstLang = to_wide_string(_pSEI->pstLang);
190         setlanguage(pwstLang);
191         FREE(pwstLang);
192     }
193
194 #ifdef _MSC_VER
195     InitializeWindows_tools();
196 #endif
197
198     if (_pSEI->iNoJvm == 0) // With JVM
199     {
200         /* bug 3702 */
201         /* tclsci creates a TK window on Windows */
202         /* it changes focus on previous windows */
203         /* we put InitializeTclTk before InitializeGUI */
204
205         //InitializeTclTk();
206         InitializeJVM();
207         InitializeGUI();
208
209         /* create needed data structure if not already created */
210         loadGraphicModule();
211
212         loadBackGroundClassPath();
213     }
214
215     /* Standard mode -> init Java Console */
216     if (_pSEI->iConsoleMode == 0)
217     {
218         /* Initialize console: lines... */
219         InitializeConsole();
220     }
221     else
222     {
223 #ifndef _MSC_VER
224         initConsoleMode(RAW);
225 #endif
226     }
227
228     //open "protection" scope to protect all variables after scilab start
229     symbol::Context::getInstance()->scope_begin();
230
231     LoadModules();
232
233     //execute scilab.start
234     if (_pSEI->iNoStart == 0)
235     {
236         StartModules();
237         execScilabStartTask(_pSEI->iSerialize != 0);
238     }
239
240     int pause = 0;
241
242     //set prompt value
243     C2F(setprlev) (&pause);
244
245     ConfigVariable::setPromptMode(0);
246     try
247     {
248         if (_pSEI->pstExec)
249         {
250             //-e option
251
252             processCommand(_pSEI);
253             iMainRet = ConfigVariable::getExitStatus();
254         }
255         else if (_pSEI->pstFile)
256         {
257             //-f option execute exec('%s',-1)
258             char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
259             sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
260
261             _pSEI->pstExec = pstCommand;
262             processCommand(_pSEI);
263             FREE(pstCommand);
264             iMainRet = ConfigVariable::getExitStatus();
265             _pSEI->pstExec = NULL;
266             _pSEI->pstFile = NULL;
267         }
268     }
269     catch (const ast::ScilabException& se)
270     {
271         scilabErrorW(se.GetErrorMessage().c_str());
272     }
273
274     ConfigVariable::setStartFinished(true);
275     ConfigVariable::setPromptMode(2);
276     return iMainRet;
277 }
278
279 int RunScilabEngine(ScilabEngineInfo* _pSEI)
280 {
281     if (_pSEI->pstParseFile)
282     {
283         // Only for parsing test, won't execute anything.
284         return batchMain(_pSEI);
285     }
286     else
287     {
288         //always run as interactiveMain even after -e or -f option
289         return interactiveMain(_pSEI);
290     }
291 }
292
293 int ExecExternalCommand(ScilabEngineInfo* _pSEI)
294 {
295     if (_pSEI->pstExec)
296     {
297         processCommand(_pSEI);
298         return ConfigVariable::getExitStatus();
299     }
300
301     return -1;
302 }
303
304 void StopScilabEngine(ScilabEngineInfo* _pSEI)
305 {
306 #ifdef _MSC_VER
307     /* bug 3672 */
308     /* Create a Mutex (closing scilab)
309      * used by files association
310      */
311     createMutexClosingScilab();
312 #endif
313
314     clearScilabPreferences();
315
316     //execute scilab.quit
317     if (_pSEI->pstFile)
318     {
319         //-f option execute exec('%s',-1)
320         char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
321         sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
322
323         _pSEI->pstExec = pstCommand;
324         processCommand(_pSEI);
325         FREE(pstCommand);
326     }
327     else if (_pSEI->iNoStart == 0)
328     {
329         execScilabQuitTask(_pSEI->iSerialize != 0);
330         //call all modules.quit
331         EndModules();
332     }
333
334     //close "protection" scope
335     symbol::Context::getInstance()->scope_end();
336
337     //clean context
338     symbol::Context::getInstance()->clearAll();
339     //destroy context
340     symbol::Context::destroyInstance();
341
342     //from ExitScilab()
343     saveCWDInPreferences();
344     clearScilabPreferences();
345
346     if (_pSEI->iNoJvm == 0)
347     {
348         //dynamic_TerminateTclTk();
349         TerminateGraphics();
350         TerminateJVM();
351     }
352
353     /* TerminateCorePart2 */
354
355     //clear opened files
356     FileManager::destroy();
357
358     /* Remove TMPDIR before exit */
359     clearTMPDIR();
360
361     //Unload dynamic modules
362     UnloadModules();
363
364     //destroy function manager
365     destroyfunctionManagerInstance();
366     /* TerminateCorePart2 end */
367
368     /*
369      * History manager cleanup
370      */
371     TerminateHistoryManager();
372
373     /*
374     * Cleanup function for the XML library.
375     */
376     xmlCleanupParser();
377
378     /* Cleanup the parser state */
379     Parser::cleanup();
380
381 #ifdef _MSC_VER
382     TerminateWindows_tools();
383 #endif
384
385     /* Reset terminal configuration */
386     if (_pSEI->iConsoleMode)
387     {
388 #ifndef _MSC_VER
389         initConsoleMode(ATTR_RESET);
390 #endif
391     }
392
393 #ifdef _MSC_VER
394     /* close mutex (closing scilab)
395      * used by files association
396      */
397     terminateMutexClosingScilab();
398 #endif
399 }
400
401 static Parser::ControlStatus processCommand(ScilabEngineInfo* _pSEI)
402 {
403     Parser *parser = new Parser();
404
405     parser->setParseTrace(_pSEI->iParseTrace != 0);
406     if (strcmp(_pSEI->pstExec, "") != 0)
407     {
408         wchar_t *pwstCommand = to_wide_string(_pSEI->pstExec);
409
410         /*
411          ** -*- PARSING -*-
412          */
413         parseCommandTask(parser, _pSEI->iTimed != 0, pwstCommand);
414
415         /*
416          ** -*- DUMPING TREE -*-
417          */
418         if (_pSEI->iDumpAst)
419         {
420             dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
421         }
422
423         if (parser->getExitStatus() == Parser::Succeded)
424         {
425             /*
426              ** -*- PRETTY PRINT TREE -*-
427              */
428             if (_pSEI->iPrintAst)
429             {
430                 printAstTask(parser->getTree(), _pSEI->iTimed != 0);
431             }
432
433             /*
434              ** -*- EXECUTING TREE -*-
435              */
436             if (_pSEI->iExecAst)
437             {
438                 //before calling YaspReader, try to call %onprompt function
439                 callOnPrompt();
440                 execAstTask(parser->getTree(), _pSEI->iSerialize != 0, _pSEI->iTimed != 0, _pSEI->iAstTimed != 0, _pSEI->iExecVerbose != 0);
441             }
442
443             /*
444              ** -*- DUMPING STACK AFTER EXECUTION -*-
445              */
446             if (_pSEI->iDumpStack)
447             {
448                 dumpStackTask(_pSEI->iTimed != 0);
449             }
450         }
451         else if (parser->getExitStatus() == Parser::Failed && parser->getControlStatus() == Parser::AllControlClosed)
452         {
453             if (_pSEI->iExecAst)
454             {
455                 //before calling YaspReader, try to call %onprompt function
456                 callOnPrompt();
457             }
458
459             scilabWriteW(parser->getErrorMessage());
460         }
461
462         FREE(pwstCommand);
463     }
464     else
465     {
466         if (_pSEI->iExecAst)
467         {
468             //before calling YaspReader, try to call %onprompt function
469             callOnPrompt();
470         }
471     }
472
473     Parser::ControlStatus ret = parser->getControlStatus();
474     delete parser;
475     return ret;
476 }
477
478 /*
479 ** -*- Interactive Main -*-
480 */
481 static int interactiveMain(ScilabEngineInfo* _pSEI)
482 {
483     int pause = 0;
484     char *command = NULL;
485
486     Parser::ControlStatus controlStatus = Parser::AllControlClosed;
487
488 #ifndef WITH_GUI
489 #ifndef _MSC_VER
490     if (getScilabMode() != SCILAB_NWNI)
491     {
492         fprintf(stderr, "Scilab was compiled without its GUI and advanced features. Run scilab-cli or us the -nwni option.\n");
493         initConsoleMode(ATTR_RESET);
494         exit(1);
495     }
496 #endif
497 #endif
498
499     InitializeHistoryManager();
500
501     //before calling reader, try to call %onprompt function
502     callOnPrompt();
503
504     while (!ConfigVariable::getForceQuit())
505     {
506         // Show Parser Sate before prompt
507         stateShow(controlStatus);
508
509         pause = ConfigVariable::getPauseLevel();
510
511         //set prompt value
512         C2F(setprlev) (&pause);
513
514         if (controlStatus == Parser::AllControlClosed)
515         {
516             if (command)
517             {
518                 FREE(command);
519                 command = NULL;
520             }
521             scilabWriteW(L"\n");
522             command = scilabRead();
523         }
524         else
525         {
526             char *pstRead = scilabRead();
527
528             //+1 for null termination and +1 for '\n'
529             size_t iLen = strlen(command) + strlen(pstRead) + 2;
530             char *pstNewCommand = (char *)MALLOC(iLen * sizeof(char));
531
532 #ifdef _MSC_VER
533             sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
534 #else
535             sprintf(pstNewCommand, "%s\n%s", command, pstRead);
536 #endif
537             FREE(pstRead);
538             FREE(command);
539             command = pstNewCommand;
540         }
541
542         _pSEI->pstExec = command;
543         controlStatus = processCommand(_pSEI);
544         _pSEI->pstExec = NULL;
545     }
546 #ifdef DEBUG
547     std::cerr << "To end program press [ENTER]" << std::endl;
548 #endif
549
550     FREE(command);
551     return ConfigVariable::getExitStatus();
552 }
553
554 /*
555 ** -*- Batch Main -*-
556 */
557 static int batchMain(ScilabEngineInfo* _pSEI)
558 {
559     /*
560      ** -*- PARSING -*-
561      */
562     Parser *parser = new Parser();
563
564     parser->setParseTrace(_pSEI->iParseTrace != 0);
565
566     wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
567
568     /*
569      ** -*- PARSING -*-
570      */
571     parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"YaSp");
572
573     /*
574      ** -*- DUMPING TREE -*-
575      */
576     if (_pSEI->iDumpAst)
577     {
578         dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
579     }
580
581     if (parser->getExitStatus() == Parser::Succeded)
582     {
583         /*
584          ** -*- PRETTY PRINT TREE -*-
585          */
586         if (_pSEI->iPrintAst)
587         {
588             printAstTask(parser->getTree(), _pSEI->iTimed != 0);
589         }
590
591     }
592     else
593     {
594         scilabWriteW(parser->getErrorMessage());
595     }
596
597 #ifdef DEBUG
598     std::cerr << "To end program press [ENTER]" << std::endl;
599 #endif
600     return parser->getExitStatus();
601 }
602
603 /*
604 ** -*- stateView
605 ** Used to show parser state.
606 ** Find if we are stuck within some control structure.
607 */
608 static void stateShow(Parser::ControlStatus status)
609 {
610     switch (status)
611     {
612         case Parser::WithinFor:
613             SetTemporaryPrompt("-for       ->");
614             break;
615         case Parser::WithinWhile:
616             SetTemporaryPrompt("-while     ->");
617             break;
618         case Parser::WithinIf:
619             SetTemporaryPrompt("-if        ->");
620             break;
621         case Parser::WithinElse:
622             SetTemporaryPrompt("-else      ->");
623             break;
624         case Parser::WithinElseIf:
625             SetTemporaryPrompt("-elseif    ->");
626             break;
627         case Parser::WithinTry:
628             SetTemporaryPrompt("-try       ->");
629             break;
630         case Parser::WithinCatch:
631             SetTemporaryPrompt("-catch     ->");
632             break;
633         case Parser::WithinFunction:
634             SetTemporaryPrompt("-function  ->");
635             break;
636         case Parser::WithinSelect:
637             SetTemporaryPrompt("-select    ->");
638             break;
639         case Parser::WithinCase:
640             SetTemporaryPrompt("-case      ->");
641             break;
642         case Parser::WithinSwitch:
643             SetTemporaryPrompt("-switch    ->");
644             break;
645         case Parser::WithinOtherwise:
646             SetTemporaryPrompt("-otherwise ->");
647             break;
648         case Parser::WithinMatrix:
649             SetTemporaryPrompt("- [        ->");
650             break;
651         case Parser::WithinCell:
652             SetTemporaryPrompt("- {        ->");
653             break;
654         case Parser::WithinBlockComment:
655             SetTemporaryPrompt("- /*       ->");
656             break;
657         case Parser::WithinDots:
658             SetTemporaryPrompt("- ...      ->");
659             break;
660         case Parser::AllControlClosed:
661             //ClearTemporaryPrompt();
662             break;
663     }
664 }
665
666 static int InitializeEnvironnement(void)
667 {
668     SetScilabEnvironment();
669     InitializeLocalization();
670
671     ConfigVariable::setConsoleWidth(75);
672     ConfigVariable::setFormatSize(10);
673     ConfigVariable::setFormatMode(1);
674     Add_All_Variables();
675     FileManager::initialize();
676     initOperationArray();
677     return 0;
678 }
679
680 /*
681  * Private function to check any linker errors
682  */
683
684 static void checkForLinkerErrors(void)
685 {
686 #ifndef _MSC_VER
687     /*
688        Depending on the linking order, sometime, libs are not loaded the right way.
689        This can cause painful debugging tasks for packager or developer, we are
690        doing the check to help them.
691     */
692 #define LINKER_ERROR_1 "Scilab startup function detected that the function proposed to the engine is the wrong one. Usually, it comes from a linker problem in your distribution/OS.\n"
693 #define LINKER_ERROR_2 "If you do not know what it means, please report a bug on http://bugzilla.scilab.org/. If you do, you probably know that you should change the link order in SCI/modules/Makefile.am\n"
694
695     if (getScilabMode() != SCILAB_NWNI)
696     {
697         if (isItTheDisabledLib())
698         {
699             fprintf(stderr, LINKER_ERROR_1);
700             fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
701             fprintf(stderr, LINKER_ERROR_2);
702             exit(1);
703
704         }
705     }
706     else
707     {
708         /* NWNI mode */
709         if (!isItTheDisabledLib())
710         {
711             fprintf(stderr, LINKER_ERROR_1);
712             fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
713             fprintf(stderr, LINKER_ERROR_2);
714             exit(1);
715         }
716     }
717 #undef LINKER_ERROR_1
718 #undef LINKER_ERROR_2
719 #endif
720 }
721
722 static void Add_All_Variables(void)
723 {
724     Add_pi();
725     Add_eps();
726     Add_e();
727     Add_i();
728     Add_s();
729     Add_z();
730     Add_true();
731     Add_false();
732     Add_Nan();
733     Add_Inf();
734 }
735
736 static void Add_Nan(void)
737 {
738     double dbl1 = 1.0;
739     double dbl0 = dbl1 - dbl1;
740
741     Add_Double_Constant(L"%nan", dbl0 / dbl0, 0, false);
742 }
743
744 static void Add_Inf(void)
745 {
746     double dbl1 = 1.0;
747     double dbl0 = dbl1 - dbl1;
748
749     Add_Double_Constant(L"%inf", dbl1 / dbl0, 0, false);
750 }
751
752 static void Add_false(void)
753 {
754     Add_Boolean_Constant(L"%f", false);
755 }
756
757 static void Add_true(void)
758 {
759     Add_Boolean_Constant(L"%t", true);
760 }
761
762 static void Add_pi(void)
763 {
764     Add_Double_Constant(L"%pi", 3.1415926535897931159980, 0, false);
765 }
766
767 static void Add_eps(void)
768 {
769     Add_Double_Constant(L"%eps", C2F(dlamch) ("p", 1L), 0, false);
770 }
771
772 static void Add_e(void)
773 {
774     Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
775 }
776
777 static void Add_i(void)
778 {
779     Add_Double_Constant(L"%i", 0, 1, true);
780 }
781
782 static void Add_s(void)
783 {
784     Double dblCoef(1, 2);
785
786     dblCoef.set(0, 0, 0);
787     dblCoef.set(0, 1, 1);
788
789     Add_Poly_Constant(L"%s", L"s", 1, &dblCoef);
790 }
791
792 static void Add_z(void)
793 {
794     Double dblCoef(1, 2);
795
796     dblCoef.set(0, 0, 0);
797     dblCoef.set(0, 1, 1);
798
799     Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
800 }
801
802 static void Add_Poly_Constant(wstring _szName, wstring _szPolyVar, int _iRank, Double * _pdbl)
803 {
804     types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
805     SinglePoly *poPoly = pVar->get(0);
806
807     poPoly->setCoef(_pdbl);
808     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
809 }
810
811 static void Add_Double_Constant(wstring _szName, double _dblReal, double _dblImg, bool _bComplex)
812 {
813     types::Double * pVal = new types::Double(1, 1, _bComplex);
814     pVal->set(0, 0, _dblReal);
815     pVal->setImg(0, 0, _dblImg);
816     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
817 }
818
819 static void Add_Boolean_Constant(wstring _szName, bool _bBool)
820 {
821     types::Bool * pVal = new types::Bool(_bBool);
822     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
823 }
824
825 static void Add_String_Constant(wstring _szName, const char *_pstString)
826 {
827     types::String * ps = new types::String(_pstString);
828     symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);
829 }