* Bug 14606 fixed: now `[names,mem]=who()` returns memory used by variables
[scilab.git] / scilab / modules / ast / src / cpp / types / macrofile.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2009-2010 - DIGITEO - Bruno JOFRET
4 *  Copyright (C) 2009-2009 - DIGITEO - Antoine ELIAS
5 *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14 *
15 */
16
17 #include <fstream>
18 #include <iostream>
19 #include <sstream>
20 #include "macrofile.hxx"
21 #include "context.hxx"
22 #include "localization.h"
23 #include "scilabWrite.hxx"
24 #include "parser.hxx"
25 #include "configvariable.hxx"
26 #include "deserializervisitor.hxx"
27 #include "scilabWrite.hxx"
28
29 extern "C"
30 {
31 #include "Scierror.h"
32 }
33 namespace types
34 {
35 MacroFile::MacroFile(const std::wstring& _stName, const std::wstring& _stPath, const std::wstring& _stModule) :
36     Callable(), m_stPath(_stPath), m_pMacro(NULL)
37 {
38     setName(_stName);
39     setModule(_stModule);
40 }
41
42 MacroFile::~MacroFile()
43 {
44     if (m_pMacro)
45     {
46         delete m_pMacro;
47     }
48 }
49
50 MacroFile* MacroFile::clone()
51 {
52     IncreaseRef();
53     return this;
54 }
55
56 void MacroFile::whoAmI()
57 {
58     std::cout << "types::MacroFile";
59 }
60
61 bool MacroFile::toString(std::wostringstream& ostr)
62 {
63
64     parse();
65     if (m_pMacro)
66     {
67         m_pMacro->toString(ostr);
68     }
69     return true;
70 }
71
72 Callable::ReturnValue MacroFile::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out)
73 {
74     parse();
75     if (m_pMacro)
76     {
77         return m_pMacro->call(in, opt, _iRetCount, out);
78     }
79     else
80     {
81         return Callable::Error;
82     }
83 }
84
85 bool MacroFile::parse(void)
86 {
87     if (m_pMacro == NULL)
88     {
89         //load file, only for the first call
90         char* pstPath = wide_string_to_UTF8(m_stPath.c_str());
91         std::ifstream f(pstPath, std::ios::in | std::ios::binary | std::ios::ate);
92         if (f.is_open() == false)
93         {
94             Scierror(999, _("Unable to open : %s.\n"), pstPath);
95             FREE(pstPath);
96             return false;
97         }
98         FREE(pstPath);
99
100         int size = (int)f.tellg();
101         unsigned char* binAst = new unsigned char[size];
102         f.seekg(0);
103         f.read((char*)binAst, size);
104         f.close();
105         ast::DeserializeVisitor d(binAst);
106         ast::Exp* tree = d.deserialize();
107         delete[] binAst;
108
109         //find FunctionDec
110         ast::FunctionDec* pFD = NULL;
111
112         ast::exps_t LExp = tree->getAs<ast::SeqExp>()->getExps();
113         std::map<symbol::Symbol, Macro*> sub;
114
115         for (auto exp : LExp)
116         {
117             if (exp->isFunctionDec() == false)
118             {
119                 continue;
120             }
121
122             pFD = exp->getAs<ast::FunctionDec>();
123
124             //get input parameters list
125             std::list<symbol::Variable*> *pVarList = new std::list<symbol::Variable*>();
126             ast::ArrayListVar *pListVar = pFD->getArgs().getAs<ast::ArrayListVar>();
127             ast::exps_t & vars = pListVar->getVars();
128             for (auto var : vars)
129             {
130                 pVarList->push_back(var->getAs<ast::SimpleVar>()->getStack());
131             }
132
133             //get output parameters list
134             std::list<symbol::Variable*> *pRetList = new std::list<symbol::Variable*>();
135             ast::ArrayListVar *pListRet = pFD->getReturns().getAs<ast::ArrayListVar>();
136             ast::exps_t & recs = pListRet->getVars();
137             for (auto rec : recs)
138             {
139                 pRetList->push_back(rec->getAs<ast::SimpleVar>()->getStack());
140             }
141
142             const symbol::Symbol & sym = pFD->getSymbol();
143             Macro* macro = new Macro(sym.getName(), *pVarList, *pRetList, (ast::SeqExp&)pFD->getBody(), m_wstModule);
144             macro->setLines(pFD->getLocation().first_line, pFD->getLocation().last_line);
145             macro->setFileName(m_stPath);
146
147             if (m_pMacro == nullptr && sym.getName() == getName())
148             {
149                 //we found the main macro
150                 m_pMacro = macro;
151             }
152             else
153             {
154                 //we found a sub macro
155                 if (sub.find(sym) == sub.end())
156                 {
157                     sub[sym] = macro;
158                 }
159                 else
160                 {
161                     // This macro is a doublon !!
162                     delete macro;
163                 }
164             }
165         }
166
167         if (m_pMacro)
168         {
169             for (const auto & macro : sub)
170             {
171                 m_pMacro->add_submacro(macro.first, macro.second);
172             }
173         }
174         else
175         {
176             // This is an incorrect library => we should not be here !
177             for (const auto & macro : sub)
178             {
179                 delete macro.second;
180             }
181         }
182         sub.clear();
183
184         delete tree;
185
186     }
187     return true;
188 }
189
190 int MacroFile::getNbInputArgument(void)
191 {
192     return getMacro()->getNbInputArgument();
193 }
194
195 int MacroFile::getNbOutputArgument(void)
196 {
197     return getMacro()->getNbOutputArgument();
198 }
199
200 Macro* MacroFile::getMacro(void)
201 {
202     parse();
203     return m_pMacro;
204 }
205
206 void MacroFile::setLines(int _iFirstLine, int _iLastLine)
207 {
208     getMacro()->setLines(_iFirstLine, _iLastLine);
209 }
210
211 bool MacroFile::getMemory(int* _piSize, int* _piSizePlusType)
212 {
213     return this->getMacro()->getMemory(_piSize, _piSizePlusType);
214 }
215
216 bool MacroFile::operator==(const InternalType& it)
217 {
218     if (const_cast<InternalType &>(it).isMacro() == false && const_cast<InternalType &>(it).isMacroFile() == false)
219     {
220         return false;
221     }
222
223     Macro* pL = getMacro();
224     Macro* pR = NULL;
225
226     if (const_cast<InternalType &>(it).isMacroFile())
227     {
228         MacroFile* pMF = const_cast<InternalType &>(it).getAs<types::MacroFile>();
229         pR = pMF->getMacro();
230     }
231     else
232     {
233         pR = const_cast<InternalType &>(it).getAs<types::Macro>();
234     }
235
236     return (*pL == *pR);
237 }
238 }