9625708826f5979cb273bd1bd7422f5667ec19d0
[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     InitializeEnvironnement();
185
186     if (_pSEI->pstLang)
187     {
188         wchar_t *pwstLang = to_wide_string(_pSEI->pstLang);
189         setlanguage(pwstLang);
190         FREE(pwstLang);
191     }
192
193 #ifdef _MSC_VER
194     InitializeWindows_tools();
195 #endif
196
197     if (_pSEI->iNoJvm == 0) // With JVM
198     {
199         /* bug 3702 */
200         /* tclsci creates a TK window on Windows */
201         /* it changes focus on previous windows */
202         /* we put InitializeTclTk before InitializeGUI */
203
204         //InitializeTclTk();
205         InitializeJVM();
206         InitializeGUI();
207
208         /* create needed data structure if not already created */
209         loadGraphicModule();
210
211         loadBackGroundClassPath();
212     }
213
214     /* Standard mode -> init Java Console */
215     if (_pSEI->iConsoleMode == 0)
216     {
217         /* Initialize console: lines... */
218         InitializeConsole();
219     }
220     else
221     {
222 #ifndef _MSC_VER
223         initConsoleMode(RAW);
224 #endif
225     }
226
227     //open "protection" scope to protect all variables after scilab start
228     symbol::Context::getInstance()->scope_begin();
229
230     LoadModules();
231
232     //execute scilab.start
233     if (_pSEI->iNoStart == 0)
234     {
235         StartModules();
236         execScilabStartTask(_pSEI->iSerialize != 0);
237     }
238
239     int pause = 0;
240
241     //set prompt value
242     C2F(setprlev) (&pause);
243
244     ConfigVariable::setPromptMode(0);
245     try
246     {
247         if (_pSEI->pstExec)
248         {
249             //-e option
250
251             processCommand(_pSEI);
252             iMainRet = ConfigVariable::getExitStatus();
253         }
254         else if (_pSEI->pstFile)
255         {
256             //-f option execute exec('%s',-1)
257             char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
258             sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
259
260             _pSEI->pstExec = pstCommand;
261             processCommand(_pSEI);
262             FREE(pstCommand);
263             iMainRet = ConfigVariable::getExitStatus();
264             _pSEI->pstExec = NULL;
265             _pSEI->pstFile = NULL;
266         }
267     }
268     catch (const ast::ScilabException& se)
269     {
270         scilabErrorW(se.GetErrorMessage().c_str());
271     }
272
273     ConfigVariable::setStartFinished(true);
274     ConfigVariable::setPromptMode(2);
275     return iMainRet;
276 }
277
278 int RunScilabEngine(ScilabEngineInfo* _pSEI)
279 {
280     if (_pSEI->pstParseFile)
281     {
282         // Only for parsing test, won't execute anything.
283         return batchMain(_pSEI);
284     }
285     else
286     {
287         //always run as interactiveMain even after -e or -f option
288         return interactiveMain(_pSEI);
289     }
290 }
291
292 int ExecExternalCommand(ScilabEngineInfo* _pSEI)
293 {
294     if (_pSEI->pstExec)
295     {
296         processCommand(_pSEI);
297         return ConfigVariable::getExitStatus();
298     }
299
300     return -1;
301 }
302
303 void StopScilabEngine(ScilabEngineInfo* _pSEI)
304 {
305 #ifdef _MSC_VER
306     /* bug 3672 */
307     /* Create a Mutex (closing scilab)
308      * used by files association
309      */
310     createMutexClosingScilab();
311 #endif
312
313     clearScilabPreferences();
314
315     //execute scilab.quit
316     if (_pSEI->pstFile)
317     {
318         //-f option execute exec('%s',-1)
319         char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
320         sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
321
322         _pSEI->pstExec = pstCommand;
323         processCommand(_pSEI);
324         FREE(pstCommand);
325     }
326     else if (_pSEI->iNoStart == 0)
327     {
328         execScilabQuitTask(_pSEI->iSerialize != 0);
329         //call all modules.quit
330         EndModules();
331     }
332
333     //close "protection" scope
334     symbol::Context::getInstance()->scope_end();
335
336     //clean context
337     symbol::Context::getInstance()->clearAll();
338     //destroy context
339     symbol::Context::destroyInstance();
340     //destroy function manager
341     destroyfunctionManagerInstance();
342
343     //from ExitScilab()
344     saveCWDInPreferences();
345     clearScilabPreferences();
346
347     if (_pSEI->iNoJvm == 0)
348     {
349         //dynamic_TerminateTclTk();
350         TerminateGraphics();
351         TerminateJVM();
352     }
353
354     /* TerminateCorePart2 */
355
356     //clear opened files
357     FileManager::destroy();
358
359     /*
360     * Cleanup function for the XML library.
361     */
362     xmlCleanupParser();
363
364     /* Remove TMPDIR before exit */
365     clearTMPDIR();
366
367     //Unload dynamic modules
368     UnloadModules();
369     /* TerminateCorePart2 end */
370
371 #ifdef _MSC_VER
372     TerminateWindows_tools();
373 #endif
374
375     /* Reset terminal configuration */
376     if (_pSEI->iConsoleMode)
377     {
378 #ifndef _MSC_VER
379         initConsoleMode(ATTR_RESET);
380 #endif
381     }
382
383 #ifdef _MSC_VER
384     /* close mutex (closing scilab)
385      * used by files association
386      */
387     terminateMutexClosingScilab();
388 #endif
389 }
390
391 static Parser::ControlStatus processCommand(ScilabEngineInfo* _pSEI)
392 {
393     Parser *parser = new Parser();
394
395     parser->setParseTrace(_pSEI->iParseTrace != 0);
396     if (strcmp(_pSEI->pstExec, "") != 0)
397     {
398         wchar_t *pwstCommand = to_wide_string(_pSEI->pstExec);
399
400         /*
401          ** -*- PARSING -*-
402          */
403         parseCommandTask(parser, _pSEI->iTimed != 0, pwstCommand);
404
405         /*
406          ** -*- DUMPING TREE -*-
407          */
408         if (_pSEI->iDumpAst)
409         {
410             dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
411         }
412
413         if (parser->getExitStatus() == Parser::Succeded)
414         {
415             /*
416              ** -*- PRETTY PRINT TREE -*-
417              */
418             if (_pSEI->iPrintAst)
419             {
420                 printAstTask(parser->getTree(), _pSEI->iTimed != 0);
421             }
422
423             /*
424              ** -*- EXECUTING TREE -*-
425              */
426             if (_pSEI->iExecAst)
427             {
428                 //before calling YaspReader, try to call %onprompt function
429                 callOnPrompt();
430                 execAstTask(parser->getTree(), _pSEI->iSerialize != 0, _pSEI->iTimed != 0, _pSEI->iAstTimed != 0, _pSEI->iExecVerbose != 0);
431             }
432
433             /*
434              ** -*- DUMPING STACK AFTER EXECUTION -*-
435              */
436             if (_pSEI->iDumpStack)
437             {
438                 dumpStackTask(_pSEI->iTimed != 0);
439             }
440         }
441         else if (parser->getExitStatus() == Parser::Failed && parser->getControlStatus() == Parser::AllControlClosed)
442         {
443             if (_pSEI->iExecAst)
444             {
445                 //before calling YaspReader, try to call %onprompt function
446                 callOnPrompt();
447             }
448
449             scilabWriteW(parser->getErrorMessage());
450         }
451
452         FREE(pwstCommand);
453     }
454     else
455     {
456         if (_pSEI->iExecAst)
457         {
458             //before calling YaspReader, try to call %onprompt function
459             callOnPrompt();
460         }
461     }
462
463     Parser::ControlStatus ret = parser->getControlStatus();
464     delete parser;
465     return ret;
466 }
467
468 /*
469 ** -*- Interactive Main -*-
470 */
471 static int interactiveMain(ScilabEngineInfo* _pSEI)
472 {
473     int pause = 0;
474     char *command = NULL;
475
476     Parser::ControlStatus controlStatus = Parser::AllControlClosed;
477
478 #ifndef WITH_GUI
479 #ifndef _MSC_VER
480     if (getScilabMode() != SCILAB_NWNI)
481     {
482         fprintf(stderr, "Scilab was compiled without its GUI and advanced features. Run scilab-cli or us the -nwni option.\n");
483         initConsoleMode(ATTR_RESET);
484         exit(1);
485     }
486 #endif
487 #endif
488
489     InitializeHistoryManager();
490
491     //before calling reader, try to call %onprompt function
492     callOnPrompt();
493
494     while (!ConfigVariable::getForceQuit())
495     {
496         // Show Parser Sate before prompt
497         stateShow(controlStatus);
498
499         pause = ConfigVariable::getPauseLevel();
500
501         //set prompt value
502         C2F(setprlev) (&pause);
503
504         if (controlStatus == Parser::AllControlClosed)
505         {
506             if (command)
507             {
508                 FREE(command);
509                 command = NULL;
510             }
511             scilabWriteW(L"\n");
512             command = scilabRead();
513         }
514         else
515         {
516             char *pstRead = scilabRead();
517
518             //+1 for null termination and +1 for '\n'
519             size_t iLen = strlen(command) + strlen(pstRead) + 2;
520             char *pstNewCommand = (char *)MALLOC(iLen * sizeof(char));
521
522 #ifdef _MSC_VER
523             sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
524 #else
525             sprintf(pstNewCommand, "%s\n%s", command, pstRead);
526 #endif
527             FREE(pstRead);
528             FREE(command);
529             command = pstNewCommand;
530         }
531
532         _pSEI->pstExec = command;
533         controlStatus = processCommand(_pSEI);
534         _pSEI->pstExec = NULL;
535     }
536 #ifdef DEBUG
537     std::cerr << "To end program press [ENTER]" << std::endl;
538 #endif
539
540     return ConfigVariable::getExitStatus();
541 }
542
543 /*
544 ** -*- Batch Main -*-
545 */
546 static int batchMain(ScilabEngineInfo* _pSEI)
547 {
548     /*
549      ** -*- PARSING -*-
550      */
551     Parser *parser = new Parser();
552
553     parser->setParseTrace(_pSEI->iParseTrace != 0);
554
555     wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
556
557     /*
558      ** -*- PARSING -*-
559      */
560     parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"YaSp");
561
562     /*
563      ** -*- DUMPING TREE -*-
564      */
565     if (_pSEI->iDumpAst)
566     {
567         dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
568     }
569
570     if (parser->getExitStatus() == Parser::Succeded)
571     {
572         /*
573          ** -*- PRETTY PRINT TREE -*-
574          */
575         if (_pSEI->iPrintAst)
576         {
577             printAstTask(parser->getTree(), _pSEI->iTimed != 0);
578         }
579
580     }
581     else
582     {
583         scilabWriteW(parser->getErrorMessage());
584     }
585
586 #ifdef DEBUG
587     std::cerr << "To end program press [ENTER]" << std::endl;
588 #endif
589     return parser->getExitStatus();
590 }
591
592 /*
593 ** -*- stateView
594 ** Used to show parser state.
595 ** Find if we are stuck within some control structure.
596 */
597 static void stateShow(Parser::ControlStatus status)
598 {
599     switch (status)
600     {
601         case Parser::WithinFor:
602             SetTemporaryPrompt("-for       ->");
603             break;
604         case Parser::WithinWhile:
605             SetTemporaryPrompt("-while     ->");
606             break;
607         case Parser::WithinIf:
608             SetTemporaryPrompt("-if        ->");
609             break;
610         case Parser::WithinElse:
611             SetTemporaryPrompt("-else      ->");
612             break;
613         case Parser::WithinElseIf:
614             SetTemporaryPrompt("-elseif    ->");
615             break;
616         case Parser::WithinTry:
617             SetTemporaryPrompt("-try       ->");
618             break;
619         case Parser::WithinCatch:
620             SetTemporaryPrompt("-catch     ->");
621             break;
622         case Parser::WithinFunction:
623             SetTemporaryPrompt("-function  ->");
624             break;
625         case Parser::WithinSelect:
626             SetTemporaryPrompt("-select    ->");
627             break;
628         case Parser::WithinCase:
629             SetTemporaryPrompt("-case      ->");
630             break;
631         case Parser::WithinSwitch:
632             SetTemporaryPrompt("-switch    ->");
633             break;
634         case Parser::WithinOtherwise:
635             SetTemporaryPrompt("-otherwise ->");
636             break;
637         case Parser::WithinMatrix:
638             SetTemporaryPrompt("- [        ->");
639             break;
640         case Parser::WithinCell:
641             SetTemporaryPrompt("- {        ->");
642             break;
643         case Parser::WithinBlockComment:
644             SetTemporaryPrompt("- /*       ->");
645             break;
646         case Parser::WithinDots:
647             SetTemporaryPrompt("- ...      ->");
648             break;
649         case Parser::AllControlClosed:
650             //ClearTemporaryPrompt();
651             break;
652     }
653 }
654
655 static int InitializeEnvironnement(void)
656 {
657     SetScilabEnvironment();
658     InitializeLocalization();
659
660     ConfigVariable::setConsoleWidth(75);
661     ConfigVariable::setFormatSize(10);
662     ConfigVariable::setFormatMode(1);
663     Add_All_Variables();
664     FileManager::initialize();
665     initOperationArray();
666     return 0;
667 }
668
669 /*
670  * Private function to check any linker errors
671  */
672
673 static void checkForLinkerErrors(void)
674 {
675 #ifndef _MSC_VER
676     /*
677        Depending on the linking order, sometime, libs are not loaded the right way.
678        This can cause painful debugging tasks for packager or developer, we are
679        doing the check to help them.
680     */
681 #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"
682 #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"
683
684     if (getScilabMode() != SCILAB_NWNI)
685     {
686         if (isItTheDisabledLib())
687         {
688             fprintf(stderr, LINKER_ERROR_1);
689             fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
690             fprintf(stderr, LINKER_ERROR_2);
691             exit(1);
692
693         }
694     }
695     else
696     {
697         /* NWNI mode */
698         if (!isItTheDisabledLib())
699         {
700             fprintf(stderr, LINKER_ERROR_1);
701             fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
702             fprintf(stderr, LINKER_ERROR_2);
703             exit(1);
704         }
705     }
706 #undef LINKER_ERROR_1
707 #undef LINKER_ERROR_2
708 #endif
709 }
710
711 static void Add_All_Variables(void)
712 {
713     Add_pi();
714     Add_eps();
715     Add_e();
716     Add_i();
717     Add_s();
718     Add_z();
719     Add_true();
720     Add_false();
721     Add_Nan();
722     Add_Inf();
723 }
724
725 static void Add_Nan(void)
726 {
727     double dbl1 = 1.0;
728     double dbl0 = dbl1 - dbl1;
729
730     Add_Double_Constant(L"%nan", dbl0 / dbl0, 0, false);
731 }
732
733 static void Add_Inf(void)
734 {
735     double dbl1 = 1.0;
736     double dbl0 = dbl1 - dbl1;
737
738     Add_Double_Constant(L"%inf", dbl1 / dbl0, 0, false);
739 }
740
741 static void Add_false(void)
742 {
743     Add_Boolean_Constant(L"%f", false);
744 }
745
746 static void Add_true(void)
747 {
748     Add_Boolean_Constant(L"%t", true);
749 }
750
751 static void Add_pi(void)
752 {
753     Add_Double_Constant(L"%pi", 3.1415926535897931159980, 0, false);
754 }
755
756 static void Add_eps(void)
757 {
758     Add_Double_Constant(L"%eps", C2F(dlamch) ("p", 1L), 0, false);
759 }
760
761 static void Add_e(void)
762 {
763     Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
764 }
765
766 static void Add_i(void)
767 {
768     Add_Double_Constant(L"%i", 0, 1, true);
769 }
770
771 static void Add_s(void)
772 {
773     Double dblCoef(1, 2);
774
775     dblCoef.set(0, 0, 0);
776     dblCoef.set(0, 1, 1);
777
778     Add_Poly_Constant(L"%s", L"s", 1, &dblCoef);
779 }
780
781 static void Add_z(void)
782 {
783     Double dblCoef(1, 2);
784
785     dblCoef.set(0, 0, 0);
786     dblCoef.set(0, 1, 1);
787
788     Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
789 }
790
791 static void Add_Poly_Constant(wstring _szName, wstring _szPolyVar, int _iRank, Double * _pdbl)
792 {
793     types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
794     SinglePoly *poPoly = pVar->get(0);
795
796     poPoly->setCoef(_pdbl);
797     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
798 }
799
800 static void Add_Double_Constant(wstring _szName, double _dblReal, double _dblImg, bool _bComplex)
801 {
802     types::Double * pVal = new types::Double(1, 1, _bComplex);
803     pVal->set(0, 0, _dblReal);
804     pVal->setImg(0, 0, _dblImg);
805     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
806 }
807
808 static void Add_Boolean_Constant(wstring _szName, bool _bBool)
809 {
810     types::Bool * pVal = new types::Bool(_bBool);
811     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
812 }
813
814 static void Add_String_Constant(wstring _szName, const char *_pstString)
815 {
816     types::String * ps = new types::String(_pstString);
817     symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);
818 }