exec : management of macro and macrofile.
[scilab.git] / scilab / modules / functions / sci_gateway / cpp / sci_exec.cpp
index bfe1b36..e908174 100644 (file)
@@ -60,6 +60,12 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
     int iID             = 0;
     Parser parser;
 
+    wchar_t* pwstFile = NULL;
+    char* pstFile = NULL;
+
+    std::string stFile;
+    std::ifstream* file = NULL;
+
     if (ConfigVariable::getStartProcessing() == false)
     {
         if (ConfigVariable::getVerbose())
@@ -78,73 +84,29 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
         return Function::Error;
     }
 
-    if (in.size() > 1)
-    {
-        //errcatch or mode
-        if (in[1]->isString() && in[1]->getAs<types::String>()->isScalar())
-        {
-            //errcatch
-            String* pS = in[1]->getAs<types::String>();
-            if (os_wcsicmp(pS->get(0), L"errcatch") == 0)
-            {
-                bErrCatch = true;
-            }
-            else
-            {
-                Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "exec", 2);
-                return Function::Error;
-            }
-
-            if (in.size() > 2)
-            {
-                if (in[2]->isDouble() == false || in[2]->getAs<Double>()->isScalar() == false)
-                {
-                    //mode
-                    Scierror(999, _("%s: Wrong type for input argument #%d: A integer expected.\n"), "exec", 3);
-                    return Function::Error;
-                }
-
-                promptMode = (int)in[2]->getAs<Double>()->getReal()[0];
-                bPromptMode = true;
-            }
-        }
-        else if (in[1]->isDouble() && in[1]->getAs<Double>()->isScalar())
-        {
-            //mode
-            promptMode = (int)in[1]->getAs<Double>()->getReal()[0];
-            bPromptMode = true;
-        }
-        else
-        {
-            //not managed
-            Scierror(999, _("%s: Wrong type for input argument #%d: A integer or string expected.\n"), "exec", 2);
-            return Function::Error;
-        }
-    }
-
     if (in[0]->isString() && in[0]->getAs<types::String>()->isScalar())
     {
         //1st argument is a path, parse file and execute it
-        int iParsePathLen              = 0;
+        int iParsePathLen = 0;
         String* pS = in[0]->getAs<types::String>();
 
-        wchar_t* pstFile = pS->get(0);
-        wchar_t *expandedPath = expandPathVariableW(pstFile);
+        pwstFile = expandPathVariableW(pS->get(0));
+        pstFile = wide_string_to_UTF8(pwstFile);
+        stFile = std::string(pstFile);
+        file = new std::ifstream(pstFile);
+
         wchar_t* pwstTemp = (wchar_t*)MALLOC(sizeof(wchar_t) * (PATH_MAX * 2));
-        get_full_pathW(pwstTemp, (const wchar_t*)expandedPath, PATH_MAX * 2);
+        get_full_pathW(pwstTemp, (const wchar_t*)pwstFile, PATH_MAX * 2);
 
         /*fake call to mopen to show file within file()*/
         if (mopen(pwstTemp, L"r", 0, &iID) != MOPEN_NO_ERROR)
         {
             FREE(pwstTemp);
-            char* pstPath = wide_string_to_UTF8(expandedPath);
-            Scierror(999, _("%s: Cannot open file %s.\n"), "exec", pstPath);
-            FREE(pstPath);
+            Scierror(999, _("%s: Cannot open file %s.\n"), "exec", pstFile);
             return Function::Error;
         }
 
         parser.parseFile(pwstTemp, L"exec");
-        FREE(expandedPath);
         FREE(pwstTemp);
         if (parser.getExitStatus() !=  Parser::Succeded)
         {
@@ -173,23 +135,42 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
             pExp = parser.getTree();
         }
     }
-    else if (in[0]->isMacro())
+    else if (in[0]->isMacro() || in[0]->isMacroFile())
     {
-        //1st argument is a macro name, execute it in the current environnement
-        pExp = in[0]->getAs<Macro>()->getBody();
-    }
-    else if (in[0]->isMacroFile())
-    {
-        //1st argument is a macro name, parse and execute it in the current environnement
-        if (in[0]->getAs<MacroFile>()->parse() == false)
+        types::Macro* pMacro = NULL;
+        typed_list input;
+        optional_list optional;
+        typed_list output;
+        ast::ExecVisitor execFunc;
+
+        if (in[0]->isMacroFile())
         {
-            char* pstMacro = wide_string_to_UTF8(in[0]->getAs<MacroFile>()->getName().c_str());
-            Scierror(999, _("%s: Unable to parse macro '%s'"), "exec", pstMacro);
-            FREE(pstMacro);
-            mclose(iID);
+            //1st argument is a macro name, parse and execute it in the current environnement
+            if (in[0]->getAs<MacroFile>()->parse() == false)
+            {
+                char* pstMacro = wide_string_to_UTF8(in[0]->getAs<MacroFile>()->getName().c_str());
+                Scierror(999, _("%s: Unable to parse macro '%s'"), "exec", pstMacro);
+                FREE(pstMacro);
+                return Function::Error;
+            }
+
+            pMacro = in[0]->getAs<MacroFile>()->getMacro();
+
+        }
+        else //1st argument is a macro name, execute it in the current environnement
+        {
+            pMacro = in[0]->getAs<Macro>();
+        }
+
+        // We dont care about the input and output argument
+        if (pMacro->outputs_get()->empty() == false || pMacro->inputs_get()->empty() == false)
+        {
+            Scierror(999, _("%s: Wrong type for input argument #%d: A macro without input and output argument expected.\n"), "exec", 1);
             return Function::Error;
         }
-        pExp = in[0]->getAs<MacroFile>()->getMacro()->getBody();
+
+        promptMode = 3;
+        pExp = pMacro->getBody();
     }
     else
     {
@@ -197,18 +178,57 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
         return Function::Error;
     }
 
+    // get mode and errcatch
+    if (in.size() > 1)
+    {
+        //errcatch or mode
+        if (in[1]->isString() && in[1]->getAs<types::String>()->isScalar())
+        {
+            //errcatch
+            String* pS = in[1]->getAs<types::String>();
+            if (os_wcsicmp(pS->get(0), L"errcatch") == 0)
+            {
+                bErrCatch = true;
+            }
+            else
+            {
+                Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "exec", 2);
+                return Function::Error;
+            }
+
+            if (in.size() > 2)
+            {
+                if (in[2]->isDouble() == false || in[2]->getAs<Double>()->isScalar() == false)
+                {
+                    //mode
+                    Scierror(999, _("%s: Wrong type for input argument #%d: A integer expected.\n"), "exec", 3);
+                    return Function::Error;
+                }
+
+                promptMode = (int)in[2]->getAs<Double>()->getReal()[0];
+                bPromptMode = true;
+            }
+        }
+        else if (in[1]->isDouble() && in[1]->getAs<Double>()->isScalar())
+        {
+            //mode
+            promptMode = (int)in[1]->getAs<Double>()->getReal()[0];
+            bPromptMode = true;
+        }
+        else
+        {
+            //not managed
+            Scierror(999, _("%s: Wrong type for input argument #%d: A integer or string expected.\n"), "exec", 2);
+            return Function::Error;
+        }
+    }
+
     ast::exps_t LExp = pExp->getAs<SeqExp>()->getExps();
 
     char pstPrompt[64];
     //get prompt
     GetCurrentPrompt(pstPrompt);
     std::string stPrompt(pstPrompt);
-    //    MessageBoxA(NULL, stPrompt, "", 0);
-
-    wchar_t* pwstFile =  expandPathVariableW(in[0]->getAs<types::String>()->get(0));
-    char* pstFile = wide_string_to_UTF8(pwstFile);
-    std::string stFile(pstFile);
-    std::ifstream file(pstFile);
 
     std::string str;
     int iCurrentLine = -1; //no data in str
@@ -225,12 +245,12 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
         {
             ast::exps_t::iterator k = j;
             //mode == 0, print new variable but not command
-            if (ConfigVariable::getPromptMode() != 0 && ConfigVariable::getPromptMode() != 2)
+            if (file && ConfigVariable::getPromptMode() != 0 && ConfigVariable::getPromptMode() != 2)
             {
                 int iLastLine = (*j)->getLocation().last_line;
                 do
                 {
-                    str = printExp(file, *k, stPrompt, &iCurrentLine, &iCurrentCol, str);
+                    str = printExp(*file, *k, stPrompt, &iCurrentLine, &iCurrentCol, str);
                     iLastLine = (*k)->getLocation().last_line;
                     k++;
                 }
@@ -398,15 +418,22 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
                         ConfigVariable::setLastErrorFunction(execFunc.getResult()->getAs<Callable>()->getName());
                     }
 
+                    if (file)
+                    {
+                        mclose(iID);
+                    }
 
-                    mclose(iID);
                     //restore previous prompt mode
                     ConfigVariable::setPromptMode(oldVal);
                     throw ast::ScilabMessage(os.str(), 0, (*j)->getLocation());
                 }
             }
 
-            mclose(iID);
+            if (file)
+            {
+                mclose(iID);
+            }
+
             throw ast::ScilabMessage((*j)->getLocation());
         }
         catch (const ast::ScilabError& se)
@@ -423,10 +450,13 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
             iErr = ConfigVariable::getLastErrorNumber();
             if (bErrCatch == false)
             {
-                file.close();
-                //print failed command
-                scilabError(getExpression(stFile, *j).c_str());
-                scilabErrorW(L"\n");
+                if (file)
+                {
+                    file->close();
+                    //print failed command
+                    scilabError(getExpression(stFile, *j).c_str());
+                    scilabErrorW(L"\n");
+                }
 
                 //write error
                 scilabErrorW(se.GetErrorMessage().c_str());
@@ -435,7 +465,11 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
                 wchar_t szError[bsiz];
                 os_swprintf(szError, bsiz, _W("at line % 5d of exec file called by :\n").c_str(), (*j)->getLocation().first_line);
                 scilabErrorW(szError);
-                mclose(iID);
+                if (file)
+                {
+                    mclose(iID);
+                }
+
                 //restore previous prompt mode
                 ConfigVariable::setPromptMode(oldVal);
                 //throw ast::ScilabMessage(szError, 1, (*j)->getLocation());
@@ -456,11 +490,16 @@ types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, typ
         ConfigVariable::setLastErrorCall();
     }
 
-    delete pExp;
-    mclose(iID);
-    file.close();
-    FREE(pstFile);
-    FREE(pwstFile);
+    if (file)
+    {
+        delete pExp;
+        mclose(iID);
+        file->close();
+        delete file;
+        FREE(pstFile);
+        FREE(pwstFile);
+    }
+
     return Function::OK;
 }