1 /***************************************************************************
2 * parse.cpp is part of Math Graphic Library
3 * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin@gmail.ru> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU Lesser General Public License as *
7 * published by the Free Software Foundation; either version 3 of the *
8 * License, or (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU Lesser General Public *
16 * License along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #include <ctype.h>
21 #include "mgl2/parser.h"
22 #include "mgl2/canvas_cf.h"
23 #include "mgl2/base.h"
24 //-----------------------------------------------------------------------------
mgl_cmd_cmp(const void * a,const void * b)25 int MGL_LOCAL_PURE mgl_cmd_cmp(const void *a, const void *b)
26 {
27 const mglCommand *aa = (const mglCommand *)a;
28 const mglCommand *bb = (const mglCommand *)b;
29 return strcmp(aa->name, bb->name);
30 }
31 //-----------------------------------------------------------------------------
32 mglCommand *mglParser::BaseCmd=NULL; ///< Base table of MGL commands. It MUST be sorted by 'name'!!!
FillBaseCmd()33 void mglParser::FillBaseCmd()
34 {
35 if(BaseCmd) return;
36 size_t na=0, nd=0, ng=0, np=0, ns=0, nr=0, nsum=0;
37 while(mgls_prg_cmd[na].name[0]) na++;
38 while(mgls_dat_cmd[nd].name[0]) nd++;
39 while(mgls_grf_cmd[ng].name[0]) ng++;
40 while(mgls_prm_cmd[np].name[0]) np++;
41 while(mgls_set_cmd[ns].name[0]) ns++;
42 while(mgls_rnd_cmd[nr].name[0]) nr++;
43 BaseCmd = new mglCommand[na+nd+ng+np+ns+nr+1];
44 memcpy(BaseCmd, mgls_prg_cmd, na*sizeof(mglCommand)); nsum+=na;
45 memcpy(BaseCmd+nsum,mgls_dat_cmd, nd*sizeof(mglCommand)); nsum+=nd;
46 memcpy(BaseCmd+nsum,mgls_grf_cmd, ng*sizeof(mglCommand)); nsum+=ng;
47 memcpy(BaseCmd+nsum,mgls_prm_cmd, np*sizeof(mglCommand)); nsum+=np;
48 memcpy(BaseCmd+nsum,mgls_rnd_cmd, nr*sizeof(mglCommand)); nsum+=nr;
49 memcpy(BaseCmd+nsum,mgls_set_cmd,(ns+1)*sizeof(mglCommand));nsum+=ns;
50 qsort(BaseCmd, nsum, sizeof(mglCommand), mgl_cmd_cmp);
51 #if DEBUG
52 long stat[17]; memset(stat,0,17*sizeof(long));
53 const char *name[17] = { _("0 - special plot"), _("1 - other plot"), _("2 - setup"), _("3 - data handle"), _("4 - data create"), _("5 - subplot"), _("6 - program flow"), _("7 - 1d plot"), _("8 - 2d plot"), _("9 - 3d plot"), _("10 - dd plot"), _("11 - vector plot"), _("12 - axis"), _("13 - primitives"), _("14 - axis setup"), _("15 - text/legend"), _("16 - data transform") };
54 for(size_t i=0;BaseCmd[i].name[0];i++) stat[BaseCmd[i].type]+=1;
55 for(size_t i=0;i<17;i++) printf("%s: %ld\n",name[i],stat[i]);
56 printf("\n"); fflush(stdout);
57 #endif
58 }
59 //-----------------------------------------------------------------------------
60 HMDT MGL_NO_EXPORT mglFormulaCalc(const std::wstring &string, mglParser *arg, const std::vector<mglDataA*> &head);
61 HADT MGL_NO_EXPORT mglFormulaCalcC(const std::wstring &string, mglParser *arg, const std::vector<mglDataA*> &head);
62 //-----------------------------------------------------------------------------
63 MGL_EXPORT void (*mgl_ask_func)(const wchar_t *, wchar_t *)=0;
mgl_ask_gets(const wchar_t * quest,wchar_t * res)64 void MGL_EXPORT mgl_ask_gets(const wchar_t *quest, wchar_t *res)
65 { printf("%ls\n",quest); if(!fgetws(res,1024,stdin)) *res=0; }
66 //-----------------------------------------------------------------------------
mgl_progress_txt(int value,int maximal,HMGL)67 void MGL_EXPORT mgl_progress_txt(int value, int maximal, HMGL)
68 {
69 static int prev = 0;
70 if(value<=0 || value>=maximal) { printf("\n"); value=0; }
71 else for(int i=prev;i<value;i++) printf("#");
72 prev = value; fflush(stdout);
73 }
74 MGL_EXPORT void (*mgl_progress_func)(int value, int maximal, HMGL)=mgl_progress_txt;
mgl_progress(int value,int maximal,HMGL gr)75 void MGL_EXPORT mgl_progress(int value, int maximal, HMGL gr)
76 { mgl_progress_func(value, maximal, gr); }
77 //-----------------------------------------------------------------------------
mglFunc(long p,const wchar_t * f)78 mglFunc::mglFunc(long p, const wchar_t *f):func(f)
79 {
80 pos = p;
81 size_t i;
82 for(i=0;(isalnum(f[i]) || f[i]=='_');i++);
83 narg = wcstol(f+i+1,0,0); func.crop(0,i);
84 if(narg<0 || narg>9) narg=0;
85 }
86 //-----------------------------------------------------------------------------
IsFunc(const wchar_t * name,int * na)87 long mglParser::IsFunc(const wchar_t *name, int *na)
88 {
89 for(size_t i=0;i<func.size();i++)
90 {
91 const mglFunc &f = func[i];
92 if(f.func==name)
93 { if(na) *na=f.narg; return f.pos+1; }
94 }
95 return 0;
96 }
97 //-----------------------------------------------------------------------------
ScanFunc(const wchar_t * line)98 void mglParser::ScanFunc(const wchar_t *line)
99 {
100 static long num=0;
101 if(!line)
102 { func.clear(); num=0; return; }
103 num++;
104 while(*line<=' ' && *line!=0) line++;
105 if(wcsncmp(line,L"func",4) || line[4]>' ') return;
106 long i;
107 for(i=4;line[i]<=' ' || line[i]=='\'';i++);
108 func.push_back(mglFunc(num-1, line+i));
109 }
110 //-----------------------------------------------------------------------------
mgl_str_copy(const char * s)111 MGL_NO_EXPORT wchar_t *mgl_str_copy(const char *s)
112 {
113 size_t i,l=strlen(s);
114 wchar_t *str = new wchar_t[l+1];
115 for(i=0;i<l;i++) str[i] = s[i];
116 str[i] = 0; return str;
117 }
118 //-----------------------------------------------------------------------------
CheckForName(const std::wstring & s)119 bool mglParser::CheckForName(const std::wstring &s)
120 {
121 return !isalpha(s[0]) || s.find_first_of(L"!@#$%%^&*/()-+|,.<>:")!=std::wstring::npos || s==L"rnd" || FindNum(s.c_str());
122 // return !isalpha(s[0])||s.find_first_of(L".:()")!=std::wstring::npos;
123 }
124 //-----------------------------------------------------------------------------
FindCommand(const char * com) const125 const mglCommand *mglParser::FindCommand(const char *com) const
126 {
127 if(!AllowFileIO && ( !strncmp(com,"read",4) || !strncmp(com,"save",4) || !strcmp(com,"fgets") || !strcmp(com,"import") || !strcmp(com,"export") ))
128 return 0;
129 mglCommand tst, *rts, *cmd = Cmd;
130 long i;
131 for(i=0;cmd[i].name[0];i++); // determine the number of symbols
132 tst.name = com;
133 rts = (mglCommand *) bsearch(&tst, cmd, i, sizeof(mglCommand), mgl_cmd_cmp);
134 return rts;
135 }
136 //-----------------------------------------------------------------------------
FindCommand(const wchar_t * com) const137 const mglCommand *mglParser::FindCommand(const wchar_t *com) const
138 {
139 char cmd[33]="";
140 size_t s = wcstombs(0,com,0); // NOTE: command name should be less than 32
141 if(s<32) { wcstombs(cmd,com,s+1); cmd[s]=0; }
142 return FindCommand(cmd);
143 }
144 //-----------------------------------------------------------------------------
145 // return values : 0 -- OK, 1 -- wrong arguments, 2 -- wrong command, 3 -- unclosed string
Exec(mglGraph * gr,const wchar_t * com,long n,mglArg * a,const std::wstring &,const wchar_t * opt)146 int mglParser::Exec(mglGraph *gr, const wchar_t *com, long n, mglArg *a, const std::wstring &/*var*/, const wchar_t *opt)
147 {
148 const char *id="dsn";
149 std::string k;
150 for(long i=0;i<n;i++) k += id[a[i].type];
151 const mglCommand *rts=FindCommand(com);
152 if(!rts || !rts->exec) return 2;
153 /* if(rts->type == 4)
154 {
155 if(n<1 || CheckForName(var)) return 2;
156 a[0].type = 0; a[0].d = AddVar(var.c_str());
157 a[0].w = var; k[0] = 'd';
158 }*/
159 std::string vopt;
160 if(opt && *opt) // TODO: parse arguments of options
161 {
162 size_t len = mgl_wcslen(opt);
163 std::vector<std::wstring> ss;
164 std::wstring s, o;
165 bool st = true, name = true;
166 for(size_t i=0;i<len+1;i++)
167 {
168 if(st && opt[i]<=' ') continue; // skip spaces at beginning
169 st = false;
170 if(i<len && opt[i]!=';')
171 {
172 if(name && opt[i]<=' ') { name = false; o = s; }
173 s.push_back(opt[i]);
174 }
175 else
176 {
177 size_t j = o.size(),k;
178 wchar_t buf[64];
179 if(o==L"xrange" || o==L"yrange" || o==L"zrange" || o==L"crange") // 2 arguments
180 {
181 bool alph=false;
182 for(k=j;k<s.length();k++)
183 {
184 if(s[k]>' ') alph=true;
185 if(alph && s[k]<=' ') break;
186 }
187 if(k<s.length())
188 {
189 HMDT d1 = mglFormulaCalc(s.substr(j+1,k-j),this, DataList);
190 HMDT d2 = mglFormulaCalc(s.substr(k+1),this, DataList);
191 mglprintf(buf,64,L" %g %g",d1->a[0],d2->a[0]);
192 s = o+buf; delete d1; delete d2;
193 }
194 }
195 else if(o!=L"legend") // 1 argument
196 {
197 HMDT dd = mglFormulaCalc(s.substr(j+1),this, DataList);
198 mglprintf(buf,64,L" %g",dd->a[0]);
199 s = o+buf; delete dd;
200 }
201 st = name = true; ss.push_back(s);
202 o.clear(); s.clear();
203 }
204 }
205 for(size_t i=0;i<ss.size();i++)
206 {
207 for(size_t j=0;j<ss[i].length();j++) vopt += ss[i][j];
208 vopt += ';';
209 }
210 }
211 int res=rts->exec(gr, n, a, k.c_str(), vopt.c_str());
212 return res;
213 }
214 //-----------------------------------------------------------------------------
mglParser(bool setsize)215 mglParser::mglParser(bool setsize)
216 {
217 InUse = 1; curGr = 0; Variant = 0;
218 Skip=Stop=false; StarObhID = 0;
219 for(long i=0;i<40;i++) par[i]=L"";
220
221 FillBaseCmd(); Cmd = BaseCmd;
222 AllowSetSize=setsize; AllowFileIO=true; AllowDllCall=true;
223 Once = true;
224 mglNum *v;
225 v = new mglNum(0); v->s = L"off"; NumList.push_back(v);
226 v = new mglNum(1); v->s = L"on"; NumList.push_back(v);
227 v = new mglNum(-1); v->s = L"all"; NumList.push_back(v);
228 v = new mglNum(NAN); v->s = L"nan"; NumList.push_back(v);
229 v = new mglNum(M_PI); v->s = L"pi"; NumList.push_back(v);
230 v = new mglNum(INFINITY); v->s = L"inf"; NumList.push_back(v);
231 #if MGL_HAVE_LTDL
232 lt_dlinit();
233 #endif
234 }
235 //-----------------------------------------------------------------------------
~mglParser()236 mglParser::~mglParser()
237 {
238 DeleteAll();
239 for(size_t i=0;i<NumList.size();i++) // force delete built-in variables
240 if(NumList[i]) delete NumList[i];
241 NumList.clear();
242 #if MGL_HAVE_LTDL
243 lt_dlexit();
244 #endif
245 }
246 //-----------------------------------------------------------------------------
DeleteAll()247 void mglParser::DeleteAll()
248 {
249 for(size_t i=0;i<DataList.size();i++)
250 if(DataList[i]) delete DataList[i];
251 DataList.clear();
252 for(size_t i=0;i<NumList.size();i++)
253 if(NumList[i]) delete NumList[i];
254 NumList.clear();
255 mglNum *v;
256 v = new mglNum(0); v->s = L"off"; NumList.push_back(v);
257 v = new mglNum(1); v->s = L"on"; NumList.push_back(v);
258 v = new mglNum(-1); v->s = L"all"; NumList.push_back(v);
259 v = new mglNum(NAN); v->s = L"nan"; NumList.push_back(v);
260 v = new mglNum(M_PI); v->s = L"pi"; NumList.push_back(v);
261 v = new mglNum(INFINITY); v->s = L"inf"; NumList.push_back(v);
262 if(Cmd && Cmd!=BaseCmd) { delete []Cmd; Cmd = BaseCmd; }
263 #if MGL_HAVE_LTDL
264 for(size_t i=0;i<DllOpened.size();i++)
265 lt_dlclose(DllOpened[i]);
266 DllOpened.clear();
267 #endif
268 }
269 //-----------------------------------------------------------------------------
AddParam(int n,const char * str)270 void mglParser::AddParam(int n, const char *str)
271 {
272 MGL_TO_WCS(str,AddParam(n,wcs));
273 }
274 //-----------------------------------------------------------------------------
Parse(mglGraph * gr,const char * str,long pos)275 int mglParser::Parse(mglGraph *gr, const char *str, long pos)
276 {
277 int r=0;
278 MGL_TO_WCS(str,r = Parse(gr,wcs,pos));
279 return r;
280 }
281 //-----------------------------------------------------------------------------
AddVar(const char * str)282 mglDataA *mglParser::AddVar(const char *str)
283 {
284 mglDataA *v=0;
285 MGL_TO_WCS(str,v = AddVar(wcs));
286 return v;
287 }
288 //-----------------------------------------------------------------------------
FindVar(const char * str)289 mglDataA *mglParser::FindVar(const char *str)
290 {
291 mglDataA *v=0;
292 MGL_TO_WCS(str,v = FindVar(wcs));
293 return v;
294 }
295 //-----------------------------------------------------------------------------
AddNum(const char * str)296 mglNum *mglParser::AddNum(const char *str)
297 {
298 mglNum *v=0;
299 MGL_TO_WCS(str,v = AddNum(wcs));
300 return v;
301 }
302 //-----------------------------------------------------------------------------
FindNum(const char * str)303 mglNum *mglParser::FindNum(const char *str)
304 {
305 mglNum *v=0;
306 MGL_TO_WCS(str,v = FindNum(wcs));
307 return v;
308 }
309 //-----------------------------------------------------------------------------
AddParam(int n,const wchar_t * str)310 void mglParser::AddParam(int n, const wchar_t *str)
311 {
312 // if(str && n>=0 && n<40 && !wcschr(str,'$')) par[n] = str;
313 if(str && n>=0 && n<40) par[n] = str;
314 }
315 //-----------------------------------------------------------------------------
FindVar(const wchar_t * name)316 mglDataA *mglParser::FindVar(const wchar_t *name)
317 {
318 if(name[0]=='!') name = name+1; // ignore complex prefix
319 for(size_t i=0;i<DataList.size();i++)
320 if(DataList[i] && !wcscmp(DataList[i]->Name(),name))
321 return DataList[i];
322 return 0;
323 }
324 //-----------------------------------------------------------------------------
AddVar(const wchar_t * name)325 mglDataA *mglParser::AddVar(const wchar_t *name)
326 { // TODO add list of forbidden names (like function names)
327 mglDataA *d=FindVar(name);
328 if(name[0]=='!' && dynamic_cast<mglDataC*>(d)==0)
329 { d = new mglDataC; d->Name(name+1); DataList.push_back(d); }
330 else if(!d)
331 { d = new mglData; d->Name(name); DataList.push_back(d); }
332 return d;
333 }
334 //-----------------------------------------------------------------------------
FindNum(const wchar_t * name)335 mglNum *mglParser::FindNum(const wchar_t *name)
336 {
337 for(size_t i=0;i<NumList.size();i++)
338 if(NumList[i] && NumList[i]->s==name) return NumList[i];
339 return 0;
340 }
341 //-----------------------------------------------------------------------------
AddNum(const wchar_t * name)342 mglNum *mglParser::AddNum(const wchar_t *name)
343 {
344 mglNum *v = FindNum(name);
345 if(!v) { v=new mglNum; v->s = name; NumList.push_back(v); }
346 return v;
347 }
348 //-----------------------------------------------------------------------------
mglFindArg(const std::wstring & str)349 int MGL_LOCAL_PURE mglFindArg(const std::wstring &str)
350 {
351 long l=0,k=0;
352 const size_t s=str.length();
353 for(size_t i=0;i<s;i++)
354 {
355 if(str[i]=='\'') l++;
356 if(str[i]=='{') k++;
357 if(str[i]=='}') k--;
358 if(l%2==0 && k==0)
359 {
360 if(str[i]=='#' || str[i]==';') return -long(i);
361 if(str[i]<=' ') return long(i);
362 }
363 }
364 return 0;
365 }
366 //-----------------------------------------------------------------------------
367 // convert substrings to arguments
FillArg(mglGraph * gr,int k,std::wstring * arg,mglArg * a)368 void mglParser::FillArg(mglGraph *gr, int k, std::wstring *arg, mglArg *a)
369 {
370 for(long n=1;n<k;n++)
371 {
372 mglDataA *v; mglNum *f;
373 a[n-1].type = -1;
374 std::wstring str = arg[n];
375 size_t i1=0, i2=str.length(), j=0;
376 bool s=true;
377 for(size_t i=0;i<i2;i++)
378 {
379 if(str[i]=='\'') s = !s;
380 if(s && str[i]=='?')
381 {
382 if(j<Variant) i1=i+1;
383 else i2=i;
384 j++;
385 }
386 }
387 str = str.substr(i1,i2-i1);
388
389 if(str.empty()) a[n-1].type = -2;
390 else if(str[0]=='|') a[n-1].type = -1;
391 else if(str[0]=='\'') // this is string (simplest case)
392 {
393 a[n-1].type = 1;
394 long na=1, ns=0, np=0, ll=str.length(), ii=1, op=0;
395 std::vector<std::wstring> s;
396 std::vector<int> id; // 0 - string, 1 - cval, 2 - rval, 3 - plus, 4 - index
397 for(long i=1;i<ll;i++)
398 {
399 if(str[i]=='\'')
400 {
401 if(na%2==1)
402 { id.push_back(0); s.push_back(str.substr(ii,i-ii)); }
403 else if(op && i>ii)
404 { id.push_back(op); s.push_back(str.substr(ii,i-ii)); }
405 na++; ii=i+1; op=0;
406 }
407 else if(na%2==0 && ns==0 && np==0)
408 {
409 if(str[i]=='+' && str[i-1]=='\'')
410 { op=3; ii=i+1; }
411 else if(str[i]==',' && str[i+1]=='!')
412 {
413 if(op && i>ii)
414 { id.push_back(op); s.push_back(str.substr(ii,i-ii)); }
415 op=1; ii=i+2;
416 }
417 else if(str[i]==',')
418 {
419 if(op && i>ii)
420 { id.push_back(op); s.push_back(str.substr(ii,i-ii)); }
421 op=2; ii=i+1;
422 }
423 else if(str[i]=='[' && str[i-1]=='\'')
424 { ii=i+1; ns++; }
425 else if(str[i]=='(') np++;
426 }
427 else if(na%2==0 && np==0 && str[i]==']' && ns==1)
428 {
429 id.push_back(4); s.push_back(str.substr(ii,i-ii));
430 op=0; ii=i+1; ns--;
431 }
432 else if(na%2==0 && np>0 && ns==0)
433 {
434 if(str[i]==')') np--;
435 if(str[i]=='(') np++;
436 }
437 }
438 if(op && ll>ii)
439 { id.push_back(op); s.push_back(str.substr(ii,ll-ii)); }
440 wchar_t buf[32];
441 for(size_t i=0;i<id.size();i++)
442 {
443 if(id[i]==0) a[n-1].s += s[i].c_str();
444 else if(id[i]==1)
445 {
446 HADT d = mglFormulaCalcC(s[i], this, DataList);
447 mreal di = imag(d->a[0]), dr = real(d->a[0]);
448 if(di>0) mglprintf(buf,32,L"%g+%gi",dr,di);
449 else if(di<0) mglprintf(buf,32,L"%g-%gi",dr,-di); // TODO use \u2212 ???
450 else mglprintf(buf,32,L"%g",dr);
451 a[n-1].s += buf; delete d;
452 }
453 else if(id[i]==2)
454 {
455 HMDT d = mglFormulaCalc(s[i], this, DataList);
456 mglprintf(buf,32,L"%g",d->a[0]); a[n-1].s += buf; delete d;
457 }
458 else if(id[i]==3)
459 {
460 HMDT d = mglFormulaCalc(s[i], this, DataList);
461 a[n-1].s[a[n-1].s.length()-1] += d->a[0]; delete d;
462 }
463 else if(id[i]==4)
464 {
465 HMDT d = mglFormulaCalc(s[i], this, DataList);
466 long v = long(d->a[0]+0.5); delete d;
467 if(v>=0 && v<long(a[n-1].s.length())) a[n-1].s = a[n-1].s[v];
468 else a[n-1].s = L"";
469 }
470 }
471 }
472 else if(str[0]=='{')
473 { // this is temp data
474 mglData *u=new mglData;
475 std::wstring s = str.substr(1,str.length()-2);
476 a[n-1].s = L"/*"+s+L"*/";
477 a[n-1].type = 0; u->Name(a[n-1].s.w);
478 ParseDat(gr, s, *u); a[n-1].d = u;
479 u->temp=true; DataList.push_back(u);
480 }
481 else if((v = FindVar(str.c_str()))!=0) // try to find normal variables (for data creation)
482 { a[n-1].type=0; a[n-1].d=v; a[n-1].s=v->Name(); }
483 else if((f = FindNum(str.c_str()))!=0) // try to find normal number (for data creation)
484 { a[n-1].type=2; a[n-1].d=0; a[n-1].v=f->d; a[n-1].c=f->c; a[n-1].s = f->s; }
485 else if(str[0]=='!') // complex array is asked
486 { // parse all numbers and formulas by unified way
487 HADT d = mglFormulaCalcC(str.substr(1), this, DataList);
488 if(d->GetNN()==1)
489 {
490 if(CheckForName(str.substr(1)))
491 { a[n-1].type = 2; a[n-1].v = d->v(0); a[n-1].c = d->a[0]; }
492 else
493 { a[n-1].type = 0; a[n-1].d = AddVar(str.c_str()); }
494 delete d;
495 }
496 else
497 {
498 a[n-1].s = L"/*"+str+L"*/";
499 d->temp=true; DataList.push_back(d);
500 a[n-1].type = 0; a[n-1].d = d;
501 }
502 }
503 else
504 { // parse all numbers and formulas by unified way
505 HMDT d = mglFormulaCalc(str, this, DataList);
506 if(d->GetNN()==1)
507 {
508 if(CheckForName(str))
509 { a[n-1].type = 2; a[n-1].c = a[n-1].v = d->v(0); }
510 else
511 { a[n-1].type = 0; a[n-1].d = AddVar(str.c_str()); }
512 delete d;
513 }
514 else
515 {
516 a[n-1].s = L"/*"+str+L"*/";
517 d->temp=true; DataList.push_back(d);
518 a[n-1].type = 0; a[n-1].d = d;
519 }
520 }
521 }
522 }
523 //-----------------------------------------------------------------------------
524 // return values: 0 - not found, 1 - OK, 2 - wrong arguments, 3 - wrong command, 4 - string too long
PreExec(mglGraph *,long k,std::wstring * arg,mglArg * a)525 int mglParser::PreExec(mglGraph *, long k, std::wstring *arg, mglArg *a)
526 {
527 long n=0;
528 if(!arg[0].compare(L"list")) // parse command "list"
529 {
530 if(k<3 || CheckForName(arg[1])) return 2;
531 long nx=0, ny=1,j=0,i,t=0;
532 for(i=2;i<k;i++)
533 {
534 char ch = arg[i][0];
535 if(a[i-1].type==1) return 2;
536 if(a[i-1].type==0)
537 {
538 if(t==1) return 2;
539 t=2; nx++;
540 }
541 if(a[i-1].type==2)
542 {
543 if(t==2) return 2;
544 j++; t=1;
545 }
546 if(ch=='|' && t==1) { nx = j>nx ? j:nx; j=0; ny++; }
547 }
548 mglDataA *vv = AddVar(arg[1].c_str());
549 mglData *v = dynamic_cast<mglData*>(vv);
550 mglDataC *vc = dynamic_cast<mglDataC*>(vv);
551 if(v)
552 {
553 if(t==1) nx = j>nx ? j:nx;
554 if(t==1) // list of numeric values
555 {
556 v->Create(nx,ny);
557 j=t=0;
558 for(i=2;i<k;i++)
559 {
560 if(arg[i][0]=='|') { t++; j=0; }
561 else
562 { v->a[j+nx*t] = a[i-1].v; j++; }
563 }
564 }
565 if(t==2) // list of data
566 {
567 v->Set(a[1].d);
568 for(long i=2;i<k;i++) v->Join(*(a[i].d));
569 }
570 n=1;
571 }
572 if(vc)
573 {
574 if(t==1) nx = j>nx ? j:nx;
575 if(t==1) // list of numeric values
576 {
577 vc->Create(nx,ny);
578 j=t=0;
579 for(i=2;i<k;i++)
580 {
581 if(arg[i][0]=='|') { t++; j=0; }
582 else
583 { vc->a[j+nx*t] = a[i-1].c; j++; }
584 }
585 }
586 if(t==2) // list of data
587 {
588 vc->Set(a[1].d);
589 for(long i=2;i<k;i++) vc->Join(*(a[i].d));
590 }
591 n=1;
592 }
593 }
594 return n;
595 }
596 //-----------------------------------------------------------------------------
PutArg(std::wstring & str,bool def)597 void mglParser::PutArg(std::wstring &str, bool def)
598 {
599 size_t pos = str.find('$',def?10:0);
600 while(pos<str.length())
601 {
602 wchar_t ch = str[pos+1];
603 if(ch>='0' && ch<='9') str.replace(pos,2,par[ch-'0'].w);
604 else if(ch>='a' && ch<='z') str.replace(pos,2,par[ch-'a'+10].w);
605 else if(ch=='$') str.replace(pos,2,L"\uffff");
606 else str.replace(pos,1,L"\uffff");
607 pos = str.find('$',def?10:0);
608 }
609 while((pos = str.find(L'\uffff'))<str.length()) str[pos]='$';
610 }
611 //-----------------------------------------------------------------------------
mgl_trim_ws(const std::wstring & str)612 std::wstring mgl_trim_ws(const std::wstring &str)
613 {
614 size_t n=str.length(), k, i;
615 for(k=0;k<n;k++) if(str[k]>' ') break;
616 for(i=n;i>k;i--) if(str[i-1]>' ') break;
617 return str.substr(k,i-k);
618 }
619 //-----------------------------------------------------------------------------
ParseDef(std::wstring & str)620 int mglParser::ParseDef(std::wstring &str)
621 {
622 if(!skip() && !str.compare(0,3,L"def") && (str[6]==' ' || str[6]=='\t'))
623 {
624 int res = 1; mreal d;
625 PutArg(str,true);
626 size_t end; bool ss=false;
627 for(end=7;str[end] && (str[end]!='#' || ss);end++)
628 { if(str[end]=='\'') ss=!ss; }
629 const std::wstring s = mgl_trim_ws(str.substr(7,end-7));
630 if(!str.compare(3,3,L"ine"))
631 {
632 int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1);
633 if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10)
634 {
635 AddParam(nn, mgl_trim_ws(s.substr(2)).c_str()); return 1;
636 }
637 }
638 if(!str.compare(3,3,L"num"))
639 {
640 int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1);
641 if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10)
642 {
643 res = 0;
644 HMDT dd = mglFormulaCalc(mgl_trim_ws(s.substr(2)), this, DataList);
645 d = dd->a[0]; delete dd;
646 AddParam(nn, mgl_str_num(d).c_str());
647 }
648 return res+1;
649 }
650 if(!str.compare(3,3,L"chr"))
651 {
652 int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1);
653 if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10)
654 {
655 res = 0;
656 HMDT dd = mglFormulaCalc(mgl_trim_ws(s.substr(2)), this, DataList);
657 d=dd->a[0]; delete dd;
658 wchar_t buf[2]={0,0}; buf[0] = wchar_t(d); AddParam(nn, buf);
659 }
660 return res+1;
661 }
662 }
663 if(!skip() && !str.compare(0,3,L"ask") && (str[3]==' ' || str[3]=='\t'))
664 {
665 PutArg(str,true);
666 std::wstring s = mgl_trim_ws(str.substr(4));
667 int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1);
668 if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10)
669 {
670 s = mgl_trim_ws(s.substr(2));
671 if(s[0]=='\'') s=s.substr(1,s.length()-2);
672 if(mgl_ask_func)
673 {
674 static wchar_t res[1024];
675 mgl_ask_func(s.c_str(),res);
676 if(*res) AddParam(nn, res);
677 }
678 return mgl_ask_func?1:2;
679 }
680 else return 2;
681 }
682 if(!skip() && !str.compare(0,3,L"for") && (str[3]==' ' || str[3]=='\t'))
683 {
684 size_t i; for(i=4;str[i]<=' ';i++);
685 // if command have format 'for $N ...' then change it to 'for N ...'
686 if(str[i]=='$' && str[i+1]>='0' && str[i+1]<='9') str[i] = ' ';
687 if(str[i]=='$' && str[i+1]>='a' && str[i+1]<='z') str[i] = ' ';
688 }
689 return 0;
690 }
691 //-----------------------------------------------------------------------------
692 // return values: 0 - OK, 1 - wrong arguments, 2 - wrong command, 3 - string too long, 4 -- unclosed string
Parse(mglGraph * gr,std::wstring str,long pos)693 int mglParser::Parse(mglGraph *gr, std::wstring str, long pos)
694 {
695 if(Stop || gr->NeedStop()) return 0;
696 curGr = gr->Self(); gr->pr = this;
697 str=mgl_trim_ws(str);
698 long n,k=0,m=0,mm=0,res;
699 // try parse ':' -- several commands in line
700 for(n=0;n<long(str.length());n++)
701 {
702 if(str[n]=='\'' && (n==0 || str[n-1]!='\\')) k++;
703 if(k%2) continue;
704 if(str[n]=='(') m++;
705 if(str[n]==')') m--;
706 if(str[n]=='{') mm++;
707 if(str[n]=='}') mm--;
708 if(str[n]=='#') break;
709 if((str[n]==':' || str[n]=='\n') && k%2==0 && m==0 && mm==0)
710 {
711 res=Parse(gr,str.substr(0,n),pos);
712 if(!res) res=Parse(gr,str.substr(n+1),pos);
713 return res;
714 }
715 }
716 if(k%2 || m || mm) return 4; // strings is not closed
717 // define parameters or start cycle
718 res = ParseDef(str); if(res) return res-1;
719 // parse arguments (parameters $1, ..., $9)
720 PutArg(str,false); str=mgl_trim_ws(str);
721
722 std::wstring opt;
723 std::vector<std::wstring> arg;
724 while(!str.empty()) // parse string to substrings (by spaces)
725 {
726 n = mglFindArg(str);
727 if(n<1) // this is option
728 {
729 if(str[-n]==';') opt = str.substr(-n+1);
730 if(n<0) str = str.substr(0,-n);
731 break;
732 }
733 arg.push_back(str.substr(0,n));
734 str = mgl_trim_ws(str.substr(n+1));
735 }
736 // try to find last argument
737 if(str[0]!=0 && str[0]!='#' && str[0]!=';') arg.push_back(str);
738 k = arg.size();
739 if(k<1) n = 0;
740 else
741 {
742 // fill arguments by its values
743 mglArg *a = new mglArg[k];
744 FillArg(gr, k, &(arg[0]), a);
745 // execute first special (program-flow-control) commands
746 if(!skip() && !arg[0].compare(L"stop"))
747 { Stop = true; delete []a; return 0; }
748 if(!arg[0].compare(L"func"))
749 { Stop = true; delete []a; return 0; }
750 n = FlowExec(gr, arg[0].c_str(),k-1,a);
751 if(n) { delete []a; return n-1; }
752 if(skip()) { delete []a; return 0; }
753 if(!arg[0].compare(L"define"))
754 {
755 if(k==3)
756 {
757 DeleteVar(arg[1].c_str()); // force to delete variable with the same name
758 mglNum *v=AddNum(arg[1].c_str());
759 if(arg[2][0]=='!') // complex number is added
760 { HADT dd = mglFormulaCalcC(arg[2].substr(1),this, DataList);
761 v->d=NAN; v->c = dd->a[0]; delete dd; }
762 else
763 { HMDT dd = mglFormulaCalc(arg[2],this, DataList);
764 v->c = v->d = dd->a[0]; delete dd; }
765 }
766 delete []a; return k==3?0:1;
767 }
768 if(!arg[0].compare(L"call"))
769 {
770 n = 1;
771 if(a[0].type==1)
772 {
773 int na=0;
774 n=-IsFunc(a[0].s.w,&na);
775 if(n && k!=na+2)
776 {
777 char buf[64];
778 snprintf(buf,64,_("Bad arguments for %ls: %ld instead of %d\n"), a[0].s.w,k-2,na);
779 buf[63]=0; gr->SetWarn(-1,buf); n = 1;
780 }
781 else if(n)
782 {
783 mglFnStack fn; fn.pos = pos; fn.stk = stack.size();
784 for(int i=0;i<10;i++) { fn.par[i] = par[i]; par[i]=L""; }
785 for(int i=1;i<k-1;i++) AddParam(i,arg[i+1].c_str());
786 fn_stack.push_back(fn); n--;
787 }
788 else if(AllowFileIO) // disable external scripts if AllowFileIO=false
789 {
790 FILE *fp = fopen(a[0].s.s,"rt");
791 if(fp)
792 {
793 mglParser *prs = new mglParser(AllowSetSize);
794 prs->DataList.swap(DataList); prs->NumList.swap(NumList); prs->Cmd=Cmd;
795 for(int i=10;i<30;i++) prs->AddParam(i,par[i].w);
796 prs->Execute(gr,fp);
797 for(int i=10;i<30;i++) AddParam(i,prs->par[i].w);
798 DataList.swap(prs->DataList); NumList.swap(prs->NumList);
799 prs->Cmd=0; delete prs; fclose(fp);
800 }
801 else n=1;
802 }
803 }
804 delete []a; return n;
805 }
806 if(!arg[0].compare(L"if") && k>3 && !arg[2].compare(L"then"))
807 {
808 bool cond=false; n=0;
809 if(a[0].type==2) cond = (a[0].v!=0);
810 else if(a[0].type==0)
811 { cond = a[0].d->FindAny((m>1 && a[1].type==1) ? a[1].s.s:"u"); }
812 if(cond)
813 { // alocate new arrays and execute the command itself
814 n = FlowExec(gr, arg[3].c_str(),k-4,a+3);
815 if(!n && !skip())
816 {
817 n = PreExec(gr, k-4, &(arg[3]), a+3);
818 if(n>0) n--;
819 else if(!arg[3].compare(L"setsize") && !AllowSetSize) n = 2;
820 else n = Exec(gr, arg[3].c_str(),k-4,a+3, k>3?arg[4]:L"", opt.c_str());
821 }
822 else n = skip()?0:n-1;
823 }
824 delete []a; DeleteTemp(); return n;
825 }
826 if(!arg[0].compare(L"do"))
827 {
828 mglPosStack st(MGL_ST_LOOP);
829 st.pos = pos; st.par = -1; st.ind = -1;
830 stack.push_back(st); delete []a; return n;
831 }
832 if(!arg[0].compare(L"for"))
833 {
834 if(k<2) { delete []a; return 1; }
835 n = 1;
836 char ch = arg[1][0];
837 int r = ch-'0';
838 if(ch>='a' && ch<='z') r = 10+ch-'a';
839 // int r = int(a[0].v);
840 mglPosStack st(MGL_ST_LOOP);
841 if(arg[1][1]==0 && (r>=0 && r<40))
842 {
843 if(a[1].type==0) { st.v = *(a[1].d); n=0; }
844 else if(a[1].type==2 && a[2].type==2 && a[2].v>=a[1].v)
845 {
846 mreal step = a[3].type==2?a[3].v:1;
847 mm = int(step>0 ? (a[2].v-a[1].v)/step : 0);
848 if(mm>=0)
849 {
850 n=0; st.v.Create(mm+1);
851 for(int ii=0;ii<mm+1;ii++) st.v.a[ii] = a[1].v + step*ii;
852 }
853 }
854 if(n==0)
855 {
856 st.pos = pos; st.par = r; st.ind = 1;
857 st.v.nx *= st.v.ny*st.v.nz; st.v.ny=st.v.nz=1;
858 wchar_t buf[32]; mglprintf(buf,32,L"%g",st.v.a[0]);
859 AddParam(r, buf);
860 }
861 }
862 if(n) st.state = MGL_ST_BREAK;
863 stack.push_back(st); delete []a; return n;
864 }
865 // allocate new arrays and execute the command itself
866 n = PreExec(gr, k, &(arg[0]), a);
867 if(n>0) n--;
868 else if(!arg[0].compare(L"setsize") && !AllowSetSize) n = 2;
869 else n = Exec(gr, arg[0].c_str(),k-1,a, k>1?arg[1]:L"", opt.c_str());
870 delete []a;
871 }
872 DeleteTemp(); return n;
873 }
874 //-----------------------------------------------------------------------------
875 // return values: 0 - OK, 1 - wrong arguments, 2 - wrong command, 3 - string too long, 4 -- unclosed string
ParseDat(mglGraph * gr,std::wstring str,mglData & res)876 int mglParser::ParseDat(mglGraph *gr, std::wstring str, mglData &res)
877 {
878 std::wstring arg[32];
879 str = mgl_trim_ws(str);
880 long n,k=0;
881 for(k=0;k<32;k++) // parse string to substrings (by spaces)
882 {
883 n = mglFindArg(str);
884 if(n<1) { if(n<0) str=str.substr(0,-n); break; }
885 arg[k] = str.substr(0,n);// k++;
886 str = str.substr(n+1); str = mgl_trim_ws(str);
887 }
888 // try to find last argument
889 if(!str.empty() && k<32) { arg[k] = str; k++; }
890 if(k<1) n = 0;
891 else
892 { // fill arguments by its values
893 mglArg *a = new mglArg[k+1];
894 FillArg(gr, k, arg, a+1); a[0].type=0; a[0].d=&res;
895 // alocate new arrays and execute the command itself
896 int i;
897 std::string kk;
898 const char *id="dsn";
899 for(i=0;i<k;i++) kk += id[a[i].type];
900 const mglCommand *rts=FindCommand(arg[0].c_str());
901 if(!rts || rts->type!=4) n = 2;
902 else n = rts->exec(gr, k, a, kk.c_str(), 0);
903 delete []a;
904 }
905 return n;
906 }
907 //-----------------------------------------------------------------------------
FlowExec(mglGraph *,const std::wstring & com,long m,mglArg * a)908 int mglParser::FlowExec(mglGraph *, const std::wstring &com, long m, mglArg *a)
909 {
910 int n=-1;
911 if(!ifskip() && !com.compare(L"once"))
912 {
913 if(a[0].type==2)
914 {
915 n = 0;
916 if(a[0].v) Skip = !Once;
917 else Skip = Once = false;
918 }
919 else n = 1;
920 }
921 else if(!Skip && !com.compare(L"if"))
922 {
923 bool cond=0; n=1;
924 if(m>2 && a[1].type==0 && !wcscmp(a[1].d->Name(),L"then"))
925 { n = -1; a[1].d->temp=true; } // NOTE: ugly hack :(
926 else if(a[0].type==2)
927 { n = 0; cond = (a[0].v!=0); }
928 else n = TestCond(m, a[0], a[1], cond);
929 if(n==0)
930 { mglPosStack st(cond?MGL_ST_TRUE:MGL_ST_FALSE); stack.push_back(st); }
931 }
932 else if(!Skip && !com.compare(L"while"))
933 {
934 n=1; if(stack.size())
935 {
936 mglPosStack &st = stack.back();
937 if(st.state==MGL_ST_LOOP)
938 {
939 bool cond = false;
940 n = TestCond(m, a[0], a[1], cond);
941 if(cond)
942 {
943 if(st.ind<0) n = -st.pos-1; // do-while loop
944 else if(st.ind<st.v.GetNN()) // next iteration
945 {
946 wchar_t buf[32]; mglprintf(buf,32,L"%g",st.v.a[st.ind]);
947 AddParam(st.par, buf); st.ind++; n = -st.pos-1;
948 }
949 else stack.pop_back(); // finish
950 }
951 else stack.pop_back();
952 }
953 else if(st.state==MGL_ST_BREAK)
954 { stack.pop_back(); n=0; }
955 }
956 }
957 else if(!Skip && !com.compare(L"endif"))
958 {
959 if(stack.size() && stack.back().state<MGL_ST_LOOP)
960 { stack.pop_back(); n=0; }
961 else n = 1;
962 }
963 else if(!Skip && !com.compare(L"else"))
964 {
965 n=1; if(stack.size())
966 {
967 mglPosStack &st = stack.back();
968 if(st.state<MGL_ST_LOOP) n=0;
969 if(st.state==MGL_ST_TRUE) st.state = MGL_ST_DONE;
970 if(st.state==MGL_ST_FALSE) st.state = MGL_ST_TRUE;
971 }
972 }
973 else if(!Skip && !com.compare(L"elseif"))
974 {
975 n=1; if(stack.size())
976 {
977 mglPosStack &st = stack.back();
978 if(st.state<MGL_ST_LOOP) n=0;
979 if(st.state==MGL_ST_TRUE) st.state = MGL_ST_DONE;
980 if(st.state==MGL_ST_FALSE)
981 {
982 bool cond=false;
983 n = TestCond(m, a[0], a[1], cond);
984 if(cond) st.state = MGL_ST_TRUE;
985 }
986 }
987 }
988 else if(!ifskip() && !Skip && !com.compare(L"break"))
989 {
990 bool nf=true;
991 size_t nn = stack.size();
992 if(nn) for(size_t i=nn;i>0;i--)
993 if(stack[i-1].state==MGL_ST_LOOP)
994 { nf=false; stack[i-1].state=MGL_ST_BREAK; break; }
995 n = nf?1:0;
996 }
997 else if(!ifskip() && !Skip && !com.compare(L"next"))
998 {
999 n=1;
1000 if(stack.size())
1001 {
1002 mglPosStack &st = stack.back();
1003 if(st.state==MGL_ST_LOOP)
1004 {
1005 if(st.ind<0) n = -st.pos-1; // do-while loop
1006 else if(st.ind<st.v.GetNN()) // next iteration
1007 {
1008 wchar_t buf[32]; mglprintf(buf,32,L"%g",st.v.a[st.ind]);
1009 AddParam(st.par, buf); st.ind++; n = -st.pos-1;
1010 }
1011 else { stack.pop_back(); n=0; } // finish
1012 }
1013 else if(st.state==MGL_ST_BREAK)
1014 { stack.pop_back(); n=0; }
1015 }
1016 }
1017 else if(!ifskip() && !Skip && !com.compare(L"continue"))
1018 {
1019 bool nf=true;
1020 size_t nn = stack.size();
1021 if(nn) for(size_t i=nn;i>0;i--)
1022 {
1023 mglPosStack &st = stack[i-1];
1024 if(st.state==MGL_ST_LOOP)
1025 {
1026 if(st.ind<0) n = -st.pos-1; // do-while loop
1027 else if(st.ind<st.v.GetNN()) // next iteration
1028 {
1029 wchar_t buf[32]; mglprintf(buf,32,L"%g",st.v.a[st.ind]);
1030 AddParam(st.par, buf); st.ind++; n = -st.pos-1;
1031 }
1032 else { st.state = MGL_ST_BREAK; n=0; } // finish
1033 nf=false; stack.resize(i); break;
1034 }
1035 }
1036 if(nf) n=1;
1037 }
1038 else if(!skip() && !com.compare(L"return"))
1039 {
1040 if(fn_stack.size()<1) return 2;
1041 const mglFnStack &fn=fn_stack.back();
1042 for(int i=0;i<10;i++) par[i]=fn.par[i];
1043 n = -fn.pos-1; fn_stack.pop_back();
1044 }
1045 return n+1;
1046 }
1047 //-----------------------------------------------------------------------------
Execute(mglGraph * gr,FILE * fp,bool print)1048 void mglParser::Execute(mglGraph *gr, FILE *fp, bool print)
1049 {
1050 if(gr==0 || fp==0) return;
1051 std::wstring str;
1052 wchar_t ch;
1053 while(!feof(fp) && size_t(ch=fgetwc(fp))!=WEOF) str.push_back(ch);
1054 Execute(gr,str.c_str());
1055 if(print) printf("%s\n",gr->Message());
1056 }
1057 //-----------------------------------------------------------------------------
Execute(mglGraph * gr,int n,const wchar_t ** text)1058 void mglParser::Execute(mglGraph *gr, int n, const wchar_t **text)
1059 {
1060 if(n<1 || text==0) return;
1061 long res=0;
1062 char buf[64];
1063 Skip=false; ScanFunc(0); fn_stack.clear(); stack.clear();
1064 for(long i=0;i<n;i++) ScanFunc(text[i]);
1065 for(long i=0;i<n;i++)
1066 {
1067 gr->SetWarn(-1, "");
1068 gr->SetObjId(i+1+StarObhID);
1069 long r = Parse(gr,text[i],i+1);
1070 if(r<0) { i = -r-2; continue; }
1071 if(r==1) snprintf(buf,64,_("\nWrong argument(s) in line %ld"), i+1);
1072 else if(r==2) snprintf(buf,64,_("\nWrong command in line %ld"), i+1);
1073 else if(r==3) snprintf(buf,64,_("\nString too long in line %ld"), i+1);
1074 else if(r==4) snprintf(buf,64,_("\nUnbalanced ' in line %ld"), i+1);
1075 else if(r==5) snprintf(buf,64,_("\nChange temporary data in line %ld"), i+1);
1076 else if(gr->GetWarn()>0) snprintf(buf,64,_("in line %ld"), i+1);
1077 else *buf=0;
1078 buf[63] = 0;
1079 if(*buf) gr->SetWarn(-2,buf);
1080 if(r>0 && r<5) res=r;
1081 }
1082 int code[]={mglScrArg, mglScrCmd, mglScrLong, mglScrStr, mglScrTemp};
1083 if(res>0) gr->SetWarn(code[res-1],_("MGL Parser"));
1084 }
1085 //-----------------------------------------------------------------------------
Execute(mglGraph * gr,const wchar_t * text)1086 void mglParser::Execute(mglGraph *gr, const wchar_t *text)
1087 {
1088 size_t s = mgl_wcslen(text)+1, n=1;
1089 wchar_t *wcs = new wchar_t[s];
1090 const wchar_t **str;
1091 for(size_t i=0;i<s;i++) if(text[i]=='\n') n++;
1092 str = (const wchar_t **)malloc(n*sizeof(wchar_t *));
1093 memcpy(wcs, text, s*sizeof(wchar_t));
1094 str[0] = wcs; n=1;
1095 long next=0;
1096 Stop = false;
1097 for(size_t i=0;i<s;i++)
1098 {
1099 if(text[i]=='\\') next = i;
1100 else if(text[i]>' ')next = 0;
1101 if(text[i]=='\n')
1102 { // if string need to be continued then I put ' ' instead of 0x0 and
1103 // pointer next string to 0x0. Last one for keeping number of strings.
1104 if(next)
1105 { for(size_t ii=next;ii<=i;ii++) wcs[ii]='\b'; str[n] = wcs+s-1; next=0; }
1106 else
1107 { wcs[i]=0; str[n] = wcs+i+1; }
1108 n++;
1109 }
1110 }
1111 Execute(gr, n, str);
1112 delete []wcs; free(str);
1113 }
1114 //-----------------------------------------------------------------------------
Execute(mglGraph * gr,const char * text)1115 void mglParser::Execute(mglGraph *gr, const char *text)
1116 {
1117 MGL_TO_WCS(text, Execute(gr, wcs));
1118 }
1119 //-----------------------------------------------------------------------------
DeleteVar(const char * name)1120 void mglParser::DeleteVar(const char *name)
1121 {
1122 MGL_TO_WCS(name,DeleteVar(wcs));
1123 }
1124 //-----------------------------------------------------------------------------
DeleteVar(const wchar_t * name)1125 void mglParser::DeleteVar(const wchar_t *name)
1126 {
1127 for(size_t i=0;i<DataList.size();i++)
1128 if(DataList[i] && !wcscmp(DataList[i]->Name(),name))
1129 { mglDataA *u=DataList[i]; DataList[i]=0; delete u; }
1130 }
1131 //-----------------------------------------------------------------------------
AddCommand(const mglCommand * cmd)1132 void mglParser::AddCommand(const mglCommand *cmd)
1133 {
1134 // determine the number of symbols
1135 size_t mp=0; while(Cmd[mp].name[0]) mp++;
1136 size_t mc=0; while(cmd[mc].name[0]) mc++;
1137 // copy all together
1138 mglCommand *buf = new mglCommand[mp+mc+1];
1139 memcpy(buf, cmd, mc*sizeof(mglCommand));
1140 memcpy(buf+mc, Cmd, (mp+1)*sizeof(mglCommand));
1141 qsort(buf, mp+mc, sizeof(mglCommand), mgl_cmd_cmp); // sort it
1142 #pragma omp critical(cmd_parser)
1143 { if(Cmd!=BaseCmd) delete []Cmd; Cmd = buf; }
1144 }
1145 //-----------------------------------------------------------------------------
mgl_create_parser()1146 HMPR MGL_EXPORT mgl_create_parser() { return new mglParser; }
mgl_delete_parser(HMPR p)1147 void MGL_EXPORT mgl_delete_parser(HMPR p) { delete p; }
mgl_parser_add_param(HMPR p,int id,const char * str)1148 void MGL_EXPORT mgl_parser_add_param(HMPR p, int id, const char *str) { p->AddParam(id,str); }
mgl_parser_add_paramw(HMPR p,int id,const wchar_t * str)1149 void MGL_EXPORT mgl_parser_add_paramw(HMPR p, int id, const wchar_t *str) { p->AddParam(id,str); }
mgl_parser_add_var(HMPR p,const char * name)1150 MGL_EXPORT mglDataA *mgl_parser_add_var(HMPR p, const char *name) { return p->AddVar(name); }
mgl_parser_find_var(HMPR p,const char * name)1151 MGL_EXPORT_PURE mglDataA *mgl_parser_find_var(HMPR p, const char *name) { return p->FindVar(name);}
mgl_parser_del_var(HMPR p,const char * name)1152 void MGL_EXPORT mgl_parser_del_var(HMPR p, const char *name) { p->DeleteVar(name); }
mgl_parser_add_varw(HMPR p,const wchar_t * name)1153 MGL_EXPORT mglDataA *mgl_parser_add_varw(HMPR p, const wchar_t *name) { return p->AddVar(name); }
mgl_parser_find_varw(HMPR p,const wchar_t * name)1154 MGL_EXPORT_PURE mglDataA *mgl_parser_find_varw(HMPR p, const wchar_t *name) { return p->FindVar(name);}
mgl_parser_del_varw(HMPR p,const wchar_t * name)1155 void MGL_EXPORT mgl_parser_del_varw(HMPR p, const wchar_t *name) { p->DeleteVar(name); }
mgl_parse_line(HMGL gr,HMPR p,const char * str,int pos)1156 int MGL_EXPORT mgl_parse_line(HMGL gr, HMPR p, const char *str, int pos)
1157 { return p->Parse(gr, str, pos); }
mgl_parse_linew(HMGL gr,HMPR p,const wchar_t * str,int pos)1158 int MGL_EXPORT mgl_parse_linew(HMGL gr, HMPR p, const wchar_t *str, int pos)
1159 { return p->Parse(gr, str, pos); }
mgl_parse_text(HMGL gr,HMPR p,const char * str)1160 void MGL_EXPORT mgl_parse_text(HMGL gr, HMPR p, const char *str)
1161 { p->Execute(gr, str); }
mgl_parse_textw(HMGL gr,HMPR p,const wchar_t * str)1162 void MGL_EXPORT mgl_parse_textw(HMGL gr, HMPR p, const wchar_t *str)
1163 { p->Execute(gr, str); }
mgl_parse_file(HMGL gr,HMPR p,FILE * fp,int print)1164 void MGL_EXPORT mgl_parse_file(HMGL gr, HMPR p, FILE *fp, int print)
1165 { p->Execute(gr,fp,print); }
mgl_parser_restore_once(HMPR p)1166 void MGL_EXPORT mgl_parser_restore_once(HMPR p) { p->RestoreOnce(); }
mgl_parser_stop(HMPR p)1167 void MGL_EXPORT mgl_parser_stop(HMPR p) { p->Stop = true; }
mgl_parser_allow_setsize(HMPR p,int a)1168 void MGL_EXPORT mgl_parser_allow_setsize(HMPR p, int a) { p->AllowSetSize= a; }
mgl_parser_allow_file_io(HMPR p,int a)1169 void MGL_EXPORT mgl_parser_allow_file_io(HMPR p, int a) { p->AllowFileIO = a; }
mgl_parser_allow_dll_call(HMPR p,int a)1170 void MGL_EXPORT mgl_parser_allow_dll_call(HMPR p, int a){ p->AllowDllCall = a; }
1171 //-----------------------------------------------------------------------------
1172 #define _PR_ ((mglParser *)(*p))
mgl_create_parser_()1173 uintptr_t MGL_EXPORT mgl_create_parser_() { return uintptr_t(new mglParser); }
mgl_delete_parser_(uintptr_t * p)1174 void MGL_EXPORT mgl_delete_parser_(uintptr_t* p) { delete _PR_; }
mgl_parser_add_param_(uintptr_t * p,int * id,const char * str,int l)1175 void MGL_EXPORT mgl_parser_add_param_(uintptr_t* p, int *id, const char *str, int l)
1176 { char *s=new char[l+1]; memcpy(s,str,l); s[l]=0;
1177 _PR_->AddParam(*id, s); delete []s; }
1178 /*===!!! NOTE !!! You must not delete obtained data arrays !!!===============*/
mgl_parser_add_var_(uintptr_t * p,const char * name,int l)1179 uintptr_t MGL_EXPORT mgl_parser_add_var_(uintptr_t* p, const char *name, int l)
1180 { char *s=new char[l+1]; memcpy(s,name,l); s[l]=0;
1181 mglDataA *v=_PR_->AddVar(s); delete []s; return uintptr_t(v); }
1182 /*===!!! NOTE !!! You must not delete obtained data arrays !!!===============*/
mgl_parser_find_var_(uintptr_t * p,const char * name,int l)1183 uintptr_t MGL_EXPORT mgl_parser_find_var_(uintptr_t* p, const char *name, int l)
1184 { char *s=new char[l+1]; memcpy(s,name,l); s[l]=0;
1185 mglDataA *v=_PR_->FindVar(s); delete []s; return uintptr_t(v); }
mgl_parser_del_var_(uintptr_t * p,const char * name,int l)1186 void MGL_EXPORT mgl_parser_del_var_(uintptr_t* p, const char *name, int l)
1187 { char *s=new char[l+1]; memcpy(s,name,l); s[l]=0;
1188 _PR_->DeleteVar(s); delete []s; }
mgl_parse_line_(uintptr_t * gr,uintptr_t * p,const char * str,int * pos,int l)1189 int MGL_EXPORT mgl_parse_line_(uintptr_t* gr, uintptr_t* p, const char *str, int *pos, int l)
1190 { char *s=new char[l+1]; memcpy(s,str,l); s[l]=0;
1191 int r = _PR_->Parse(_GR_, s, *pos); delete []s; return r; }
mgl_parse_text_(uintptr_t * gr,uintptr_t * p,const char * str,int l)1192 void MGL_EXPORT mgl_parse_text_(uintptr_t* gr, uintptr_t* p, const char *str, int l)
1193 { char *s=new char[l+1]; memcpy(s,str,l); s[l]=0;
1194 _PR_->Execute(_GR_, s); delete []s; }
mgl_parser_restore_once_(uintptr_t * p)1195 void MGL_EXPORT mgl_parser_restore_once_(uintptr_t* p) { _PR_->RestoreOnce(); }
mgl_parser_allow_setsize_(uintptr_t * p,int * a)1196 void MGL_EXPORT mgl_parser_allow_setsize_(uintptr_t* p, int *a) { _PR_->AllowSetSize= *a; }
mgl_parser_allow_file_io_(uintptr_t * p,int * a)1197 void MGL_EXPORT mgl_parser_allow_file_io_(uintptr_t* p, int *a) { _PR_->AllowFileIO = *a; }
mgl_parser_allow_dll_call_(uintptr_t * p,int * a)1198 void MGL_EXPORT mgl_parser_allow_dll_call_(uintptr_t* p, int *a){ _PR_->AllowDllCall= *a; }
mgl_parser_stop_(uintptr_t * p)1199 void MGL_EXPORT mgl_parser_stop_(uintptr_t* p) { _PR_->Stop = true; }
1200 //-----------------------------------------------------------------------------
mgl_use_parser(HMPR pr,int inc)1201 long MGL_EXPORT mgl_use_parser(HMPR pr, int inc)
1202 { pr->InUse+=inc; return pr->InUse; }
mgl_use_parser_(uintptr_t * p,int * inc)1203 long MGL_EXPORT mgl_use_parser_(uintptr_t *p, int *inc)
1204 { _PR_->InUse+=*inc; return _PR_->InUse; }
1205 //---------------------------------------------------------------------------
mgl_parser_get_var(HMPR p,unsigned long id)1206 MGL_EXPORT_PURE mglDataA *mgl_parser_get_var(HMPR p, unsigned long id)
1207 { return id<p->DataList.size()?p->DataList[id]:0; }
mgl_parser_get_var_(uintptr_t * p,unsigned long * id)1208 uintptr_t MGL_EXPORT_PURE mgl_parser_get_var_(uintptr_t* p, unsigned long *id)
1209 { return uintptr_t(mgl_parser_get_var(_PR_,*id)); }
mgl_parser_num_var(HMPR p)1210 long MGL_EXPORT_PURE mgl_parser_num_var(HMPR p)
1211 { return p->DataList.size(); }
mgl_parser_num_var_(uintptr_t * p)1212 long MGL_EXPORT_PURE mgl_parser_num_var_(uintptr_t* p)
1213 { return mgl_parser_num_var(_PR_); }
mgl_parser_num_const(HMPR p)1214 long MGL_EXPORT_PURE mgl_parser_num_const(HMPR p)
1215 { return p->NumList.size(); }
mgl_parser_num_const_(uintptr_t * p)1216 long MGL_EXPORT_PURE mgl_parser_num_const_(uintptr_t* p)
1217 { return mgl_parser_num_const(_PR_); }
mgl_parser_get_const(HMPR p,unsigned long id)1218 MGL_EXPORT_PURE mglNum *mgl_parser_get_const(HMPR p, unsigned long id)
1219 { return id<p->NumList.size()?p->NumList[id]:0; }
mgl_parser_get_const_(uintptr_t * p,unsigned long * id)1220 uintptr_t MGL_EXPORT_PURE mgl_parser_get_const_(uintptr_t* p, unsigned long *id)
1221 { return uintptr_t(mgl_parser_get_const(_PR_,*id)); }
1222 //---------------------------------------------------------------------------
mgl_parser_cmd_type(HMPR pr,const char * name)1223 int MGL_EXPORT_PURE mgl_parser_cmd_type(HMPR pr, const char *name)
1224 {
1225 const mglCommand *cmd = pr->FindCommand(name);
1226 return cmd ? cmd->type + 1 : 0;
1227 }
mgl_parser_cmd_type_(uintptr_t * p,const char * str,int l)1228 int MGL_EXPORT_PURE mgl_parser_cmd_type_(uintptr_t* p, const char *str, int l)
1229 { char *s=new char[l+1]; memcpy(s,str,l); s[l]=0;
1230 l = mgl_parser_cmd_type(_PR_, s); delete []s; return l; }
1231 //---------------------------------------------------------------------------
mgl_parser_cmd_desc(HMPR pr,const char * name)1232 MGL_EXPORT_PURE const char *mgl_parser_cmd_desc(HMPR pr, const char *name)
1233 {
1234 const mglCommand *cmd = pr->FindCommand(name);
1235 return cmd ? cmd->desc : 0;
1236 }
mgl_parser_cmd_frmt(HMPR pr,const char * name)1237 MGL_EXPORT_PURE const char *mgl_parser_cmd_frmt(HMPR pr, const char *name)
1238 {
1239 const mglCommand *cmd = pr->FindCommand(name);
1240 return cmd ? cmd->form : 0;
1241 }
1242 //---------------------------------------------------------------------------
mgl_parser_cmd_name(HMPR pr,long id)1243 MGL_EXPORT_PURE const char *mgl_parser_cmd_name(HMPR pr, long id)
1244 { return (id<mgl_parser_cmd_num(pr) && id>=0) ? pr->Cmd[id].name:""; }
mgl_parser_cmd_num(HMPR pr)1245 long MGL_EXPORT_PURE mgl_parser_cmd_num(HMPR pr)
1246 { long i=0; while(pr->Cmd[i].name[0]) i++; return i; }
1247 //---------------------------------------------------------------------------
mgl_parser_calc(HMPR pr,const char * formula)1248 HMDT MGL_EXPORT mgl_parser_calc(HMPR pr, const char *formula)
1249 { HMDT d=0; MGL_TO_WCS(formula,d = mgl_parser_calcw(pr,wcs)); return d; }
mgl_parser_calcw(HMPR pr,const wchar_t * formula)1250 HMDT MGL_EXPORT mgl_parser_calcw(HMPR pr, const wchar_t *formula)
1251 { return mglFormulaCalc(formula,pr, pr->DataList); }
mgl_parser_calc_(uintptr_t * p,const char * str,int l)1252 uintptr_t MGL_EXPORT mgl_parser_calc_(uintptr_t *p, const char *str,int l)
1253 { char *s=new char[l+1]; memcpy(s,str,l); s[l]=0;
1254 uintptr_t d = (uintptr_t)mgl_parser_calc(_PR_, s); delete []s; return d; }
1255 //---------------------------------------------------------------------------
mgl_parser_calc_complex(HMPR pr,const char * formula)1256 HADT MGL_EXPORT mgl_parser_calc_complex(HMPR pr, const char *formula)
1257 { HADT d=0; MGL_TO_WCS(formula,d = mgl_parser_calc_complexw(pr,wcs)); return d; }
mgl_parser_calc_complexw(HMPR pr,const wchar_t * formula)1258 HADT MGL_EXPORT mgl_parser_calc_complexw(HMPR pr, const wchar_t *formula)
1259 { return mglFormulaCalcC(formula,pr, pr->DataList); }
mgl_parser_calc_complex_(uintptr_t * p,const char * str,int l)1260 uintptr_t MGL_EXPORT mgl_parser_calc_complex_(uintptr_t *p, const char *str,int l)
1261 { char *s=new char[l+1]; memcpy(s,str,l); s[l]=0;
1262 uintptr_t d = (uintptr_t)mgl_parser_calc_complex(_PR_, s); delete []s; return d; }
1263 //---------------------------------------------------------------------------
mgl_parser_del_all(HMPR p)1264 void MGL_EXPORT mgl_parser_del_all(HMPR p) { p->DeleteAll(); }
mgl_parser_del_all_(uintptr_t * p)1265 void MGL_EXPORT mgl_parser_del_all_(uintptr_t *p) { _PR_->DeleteAll(); }
1266 //---------------------------------------------------------------------------
mgl_parser_load(HMPR pr,const char * so_name)1267 void MGL_EXPORT mgl_parser_load(HMPR pr, const char *so_name)
1268 {
1269 if(!pr->AllowDllCall) return;
1270 #if MGL_HAVE_LTDL
1271 lt_dlhandle so = lt_dlopen(so_name);
1272 if(!so) return;
1273 const mglCommand *cmd = (const mglCommand *)lt_dlsym(so,"mgl_cmd_extra");
1274 bool exist = true;
1275 if(cmd) for(size_t i=0;cmd[i].name[0];i++)
1276 if(!pr->FindCommand(cmd[i].name)) exist=false;
1277 if(exist) { lt_dlclose(so); return; } // all commands already presents
1278 else pr->DllOpened.push_back(so);
1279 pr->AddCommand(cmd);
1280 #endif
1281 }
mgl_parser_load_(uintptr_t * p,const char * dll_name,int l)1282 void MGL_EXPORT mgl_parser_load_(uintptr_t *p, const char *dll_name,int l)
1283 { char *s=new char[l+1]; memcpy(s,dll_name,l); s[l]=0;
1284 mgl_parser_load(_PR_, s); delete []s; }
1285 //---------------------------------------------------------------------------
1286 struct mglRKdat
1287 {
1288 mglDataA *v;
1289 std::wstring e;
1290 bool cmplx;
1291 mglDataC cin,c1,c2,c3,c4, *cc;
1292 mglData din,d1,d2,d3,d4, *dd;
mglRKdatmglRKdat1293 mglRKdat(mglDataA *var, std::wstring &eq):v(var), e(eq)
1294 { cmplx = dynamic_cast<mglDataC*>(var); cc=0; dd=0; }
allocatemglRKdat1295 void allocate()
1296 {
1297 if(cmplx)
1298 { cc = dynamic_cast<mglDataC*>(v); cin.Set(v); }
1299 else
1300 { dd = dynamic_cast<mglData*>(v); din.Set(v); }
1301 }
1302 };
mgl_rk_step_w(HMPR pr,const wchar_t * Eqs,const wchar_t * Vars,mreal dt)1303 void MGL_EXPORT mgl_rk_step_w(HMPR pr, const wchar_t *Eqs, const wchar_t *Vars, mreal dt)
1304 {
1305 const std::wstring eqs(Eqs);
1306 const std::wstring vars(Vars);
1307 std::vector<mglRKdat> rkv;
1308 size_t iv=0,jv=0,ie=0,je=0;
1309 while(1)
1310 {
1311 iv = vars.find(';',jv); ie = eqs.find(';',je);
1312 mglDataA *vv=mgl_parser_find_varw(pr,vars.substr(jv,iv-jv).c_str());
1313 std::wstring eq = eqs.substr(je,ie-je).c_str();
1314 if(vv) rkv.push_back(mglRKdat(vv, eq ));
1315 jv = iv+1; je = ie+1;
1316 if(iv==std::wstring::npos || ie==std::wstring::npos) break;
1317 }
1318 for(size_t i=0;i<rkv.size();i++) rkv[i].allocate();
1319 mreal hh = dt/2;
1320 for(size_t i=0;i<rkv.size();i++)
1321 {
1322 mglRKdat &rk = rkv[i];
1323 if(rk.cmplx) rk.c1.Move(mglFormulaCalcC(rk.e, pr, pr->DataList));
1324 else rk.d1.Move(mglFormulaCalc(rk.e, pr, pr->DataList));
1325 }
1326 for(size_t i=0;i<rkv.size();i++)
1327 {
1328 mglRKdat &rk = rkv[i];
1329 if(rk.cc)
1330 {
1331 long n = rk.cc->GetNN(); dual a = hh*rk.c1.a[0];
1332 if(rk.c1.GetNN()==n)
1333 #pragma omp parallel for
1334 for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + hh*rk.c1.a[j];
1335 else
1336 #pragma omp parallel for
1337 for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + a;
1338 }
1339 if(rk.dd)
1340 {
1341 long n = rk.dd->GetNN(); mreal a = hh*rk.d1.a[0];
1342 if(rk.d1.GetNN()==n)
1343 #pragma omp parallel for
1344 for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + hh*rk.d1.a[j];
1345 else
1346 #pragma omp parallel for
1347 for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + a;
1348 }
1349 }
1350
1351 for(size_t i=0;i<rkv.size();i++)
1352 {
1353 mglRKdat &rk = rkv[i];
1354 if(rk.cmplx) rk.c2.Move(mglFormulaCalcC(rk.e, pr, pr->DataList));
1355 else rk.d2.Move(mglFormulaCalc(rk.e, pr, pr->DataList));
1356 }
1357 for(size_t i=0;i<rkv.size();i++)
1358 {
1359 mglRKdat &rk = rkv[i];
1360 if(rk.cc)
1361 {
1362 long n = rk.cc->GetNN(); dual a = hh*rk.c2.a[0];
1363 if(rk.c2.GetNN()==n)
1364 #pragma omp parallel for
1365 for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + hh*rk.c2.a[j];
1366 else
1367 #pragma omp parallel for
1368 for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + a;
1369 }
1370 if(rk.dd)
1371 {
1372 long n = rk.dd->GetNN(); mreal a = hh*rk.d2.a[0];
1373 if(rk.d2.GetNN()==n)
1374 #pragma omp parallel for
1375 for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + hh*rk.d2.a[j];
1376 else
1377 #pragma omp parallel for
1378 for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + a;
1379 }
1380 }
1381
1382 for(size_t i=0;i<rkv.size();i++)
1383 {
1384 mglRKdat &rk = rkv[i];
1385 if(rk.cmplx) rk.c3.Move(mglFormulaCalcC(rk.e, pr, pr->DataList));
1386 else rk.d3.Move(mglFormulaCalc(rk.e, pr, pr->DataList));
1387 }
1388 for(size_t i=0;i<rkv.size();i++)
1389 {
1390 mglRKdat &rk = rkv[i];
1391 if(rk.cc)
1392 {
1393 long n = rk.cc->GetNN(); dual a = dt*rk.c3.a[0];
1394 if(rk.c3.GetNN()==n)
1395 #pragma omp parallel for
1396 for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + dt*rk.c3.a[j];
1397 else
1398 #pragma omp parallel for
1399 for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + a;
1400 }
1401 if(rk.dd)
1402 {
1403 long n = rk.dd->GetNN(); mreal a = dt*rk.d3.a[0];
1404 if(rk.d3.GetNN()==n)
1405 #pragma omp parallel for
1406 for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + dt*rk.d3.a[j];
1407 else
1408 #pragma omp parallel for
1409 for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + a;
1410 }
1411 }
1412
1413 for(size_t i=0;i<rkv.size();i++)
1414 {
1415 mglRKdat &rk = rkv[i];
1416 if(rk.cmplx) rk.c4.Move(mglFormulaCalcC(rk.e, pr, pr->DataList));
1417 else rk.d4.Move(mglFormulaCalc(rk.e, pr, pr->DataList));
1418 }
1419 for(size_t i=0;i<rkv.size();i++)
1420 {
1421 mglRKdat &rk = rkv[i];
1422 if(rk.cc)
1423 {
1424 long n = rk.cc->GetNN();
1425 dual a = (rk.c1.a[0]+rk.c2.a[0]+mreal(2)*(rk.c3.a[0]+rk.c4.a[0]))*(dt/6);
1426 if(rk.c1.GetNN()==n)
1427 #pragma omp parallel for
1428 for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + (rk.c1.a[j]+rk.c2.a[j]+mreal(2)*(rk.c3.a[j]+rk.c4.a[j]))*(dt/6);
1429 else
1430 #pragma omp parallel for
1431 for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + a;
1432 }
1433 if(rk.dd)
1434 {
1435 long n = rk.dd->GetNN();
1436 mreal a = (rk.d1.a[0]+rk.d2.a[0]+2*(rk.d3.a[0]+rk.d4.a[0]))*(dt/6);
1437 if(rk.d1.GetNN()==n)
1438 #pragma omp parallel for
1439 for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + (rk.d1.a[j]+rk.d2.a[j]+2*(rk.d3.a[j]+rk.d4.a[j]))*(dt/6);
1440 else
1441 #pragma omp parallel for
1442 for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + a;
1443 }
1444 }
1445 }
mgl_rk_step(HMPR pr,const char * Eqs,const char * Vars,mreal dt)1446 void MGL_EXPORT mgl_rk_step(HMPR pr, const char *Eqs, const char *Vars, mreal dt)
1447 {
1448 if(Eqs && *Eqs && Vars && *Vars)
1449 {
1450 size_t s=mbstowcs(0,Eqs,0), w=mbstowcs(0,Vars,0);
1451 wchar_t *eqs=new wchar_t[s+1]; mbstowcs(eqs,Eqs ,s); eqs[s]=0;
1452 wchar_t *wcs=new wchar_t[s+1]; mbstowcs(wcs,Vars,s); wcs[w]=0;
1453 mgl_rk_step_w(pr,eqs,wcs,dt); delete []wcs; delete []eqs;
1454 }
1455 }
mgl_rk_step_(uintptr_t * p,const char * eqs,const char * vars,double * dt,int l,int m)1456 void MGL_EXPORT mgl_rk_step_(uintptr_t *p, const char *eqs, const char *vars, double *dt,int l,int m)
1457 { char *e=new char[l+1]; memcpy(e,eqs,l); e[l]=0;
1458 char *s=new char[m+1]; memcpy(s,vars,m); s[m]=0;
1459 mgl_rk_step(_PR_,e,s,*dt); delete []e; delete []s; }
1460 //---------------------------------------------------------------------------
mgl_parser_variant(HMPR p,int var)1461 void MGL_EXPORT mgl_parser_variant(HMPR p, int var) { p->SetVariant(var); }
mgl_parser_variant_(uintptr_t * p,int * var)1462 void MGL_EXPORT mgl_parser_variant_(uintptr_t *p, int *var) { mgl_parser_variant(_PR_,*var); }
1463 //---------------------------------------------------------------------------
mgl_parser_openhdf(HMPR p,const char * fname)1464 void MGL_EXPORT mgl_parser_openhdf(HMPR p, const char *fname)
1465 {
1466 const char * const *res = mgl_datas_hdf_str(fname);
1467 if(!res) return;
1468 for(size_t n=0;res[n][0];n++)
1469 {
1470 mglDataA *d = p->AddVar(res[n]);
1471 mglData *dr = dynamic_cast<mglData*>(d);
1472 mglDataC *dc = dynamic_cast<mglDataC*>(d);
1473 if(dr) dr->ReadHDF(fname,res[n]);
1474 if(dc) dc->ReadHDF(fname,res[n]);
1475 }
1476 }
mgl_parser_openhdf_(uintptr_t * p,const char * fname,int l)1477 void MGL_EXPORT mgl_parser_openhdf_(uintptr_t *p, const char *fname,int l)
1478 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
1479 mgl_parser_openhdf(_PR_,s); delete []s; }
1480 //---------------------------------------------------------------------------
mgl_parser_start_id(HMPR pr,int id)1481 void MGL_EXPORT mgl_parser_start_id(HMPR pr, int id)
1482 { pr->StarObhID = id; }
mgl_parser_start_id_(uintptr_t * p,int * id)1483 void MGL_EXPORT mgl_parser_start_id_(uintptr_t* p, int *id)
1484 { mgl_parser_start_id(_PR_, *id); }
1485
1486 //---------------------------------------------------------------------------
1487 mglCommand mgls_prg_cmd[] = {
1488 {"ask",_("Define parameter from user input"),"ask $N 'question'", 0, 6},
1489 {"break",_("Break for-loop"),"break", 0, 6},
1490 {"call",_("Execute script in external file"),"call 'name' [args]", 0, 6},
1491 {"continue",_("Skip commands and iterate for-loop again"),"continue", 0, 6},
1492 {"do",_("Begin of do-while loop"),"do", 0, 6},
1493 {"defchr",_("Define parameter as character"),"defchr $N val", 0, 6},
1494 {"define",_("Define constant or parameter"),"define $N sth | Var val", 0, 6},
1495 {"defnum",_("Define parameter as numerical value"),"defnum $N val", 0, 6},
1496 // {"defpal",_("Define parameter as palette color"),"defpal $N val", 0, 6},
1497 {"else",_("Execute if condition is false"),"else", 0, 6},
1498 {"elseif",_("Conditional operator"),"elseif val|Dat ['cond']", 0, 6},
1499 {"endif",_("Finish if/else block"),"endif", 0, 6},
1500 {"for",_("For loop"),"for $N v1 v2 [dv] | $N Dat", 0, 6},
1501 {"func",_("Start function definition and stop execution of main script"),"func 'name' [narg]", 0, 6},
1502 {"if",_("Conditional operator"),"if val|Dat ['cond']", 0, 6},
1503 {"list",_("Creates new variable from list of numbers or data"),"list Var v1 ...|Var D1 ...", 0, 4},
1504 {"next",_("Start next for-loop iteration"),"next", 0, 6},
1505 {"once",_("Start/close commands which should executed only once"),"once val", 0, 6},
1506 {"return",_("Return from function"),"return", 0, 6},
1507 {"stop",_("Stop execution"),"stop", 0, 6},
1508 {"while",_("Condition of do-while loop"),"while val|Dat ['cond']", 0, 6},
1509 {"","","",NULL,0}};
1510 //-----------------------------------------------------------------------------
1511