ReturnCode REGARGS AddVar(struct Data *scr, /* pointer to struct Data */ struct Identifier *ident,/* identifier struct pointer */ struct Local **local, uchar output) { ReturnCode ret; struct Local *temp; if(ret=AddIdentifier(scr, ident)) INFO(scr, CERROR_IDENTIFIER_USED, ident->name); else { GETMEM(temp, sizeof(struct Local)); temp->next=*local; temp->ident=ident; *local=temp; scr->currvariables++; /* increase number of current symbols */ scr->totalvariables++; /* increase total number of symbols */ ident->number= ++IdentNumber; if(output) { CALL(PutArg(scr, COMP_DECLARE, ident->flags)); if(!(ident->flags&FPL_EXPORT_SYMBOL)) { CALL(PutArg(scr, COMP_NOTHING, ident->number)); } else { CALL(PutArg(scr, COMP_NOTHING, ident->hash)); } CALL(PutString(scr, COMP_NOTHING, ident->name, -1)); } } return(ret); }
//----------------------------------------------------------------------------- // return values: 0 - OK, 1 - wrong arguments, 2 - wrong command, 3 - string too long, 4 -- unclosed string int mglParser::Parse(mglGraph *gr, std::wstring str, long pos) { if(Stop || gr->NeedStop()) return 0; curGr = gr->Self(); std::wstring arg[1024]; str=mgl_trim_ws(str); long n,k=0,m=0,mm=0,res; // try parse ':' -- several commands in line for(n=0;n<long(str.length());n++) { if(str[n]=='\'' && (n==0 || str[n-1]!='\\')) k++; if(k%2) continue; if(str[n]=='(') m++; if(str[n]==')') m--; if(str[n]=='{') mm++; if(str[n]=='}') mm--; if(str[n]=='#') break; if((str[n]==':' || str[n]=='\n') && k%2==0 && m==0 && mm==0) { res=Parse(gr,str.substr(0,n),pos); if(!res) res=Parse(gr,str.substr(n+1),pos); return res; } } if(k%2 || m || mm) return 4; // strings is not closed // define parameters or start cycle res = ParseDef(str); if(res) return res-1; // parse arguments (parameters $1, ..., $9) PutArg(str,false); str=mgl_trim_ws(str); std::wstring opt; for(k=0;k<1024;k++) // parse string to substrings (by spaces) { n = mglFindArg(str); if(n<1) // this is option { if(str[-n]==';') opt = str.substr(-n+1); if(n<0) str = str.substr(0,-n); break; } arg[k] = str.substr(0,n); str = mgl_trim_ws(str.substr(n+1)); } // try to find last argument if(str[0]!=0 && str[0]!='#' && str[0]!=';') { arg[k] = str; k++; } if(k<1) n =0; else { // fill arguments by its values mglArg *a = new mglArg[k]; FillArg(gr, k, arg, a); // execute first special (program-flow-control) commands if(!skip() && !arg[0].compare(L"stop")) { Stop = true; delete []a; return 0; } if(!arg[0].compare(L"func")) { Stop = true; delete []a; return 0; } n = FlowExec(gr, arg[0].c_str(),k-1,a); if(n) { delete []a; return n-1; } if(skip()) { delete []a; return 0; } if(!arg[0].compare(L"load")) { int n = a[0].type==1?0:1; a[0].s.assign(a[0].w.begin(),a[0].w.end()); if(!n) mgl_parser_load(this,a[0].s.c_str()); delete []a; return n; } if(!arg[0].compare(L"define")) { if(k==3) { DeleteVar(arg[1].c_str()); // force to delete variable with the same name mglNum *v=AddNum(arg[1].c_str()); if(arg[2][0]=='!') // complex number is added { HADT dd = mglFormulaCalcC(arg[2].substr(1),this, DataList); v->d=NAN; v->c = dd->a[0]; delete dd; } else { HMDT dd = mglFormulaCalc(arg[2],this, DataList); v->c = v->d = dd->a[0]; delete dd; } } delete []a; return k==3?0:1; } if(!arg[0].compare(L"rkstep")) { int res=1; if(k>2 && a[0].type==1 && a[1].type==1) { std::wstring a1 = arg[1], a2=arg[2]; res = 0; if(a1[0]=='\'') a1 = a1.substr(1,a1.length()-2); if(a2[0]=='\'') a2 = a2.substr(1,a2.length()-2); mgl_rk_step_w(this, a1.c_str(), a2.c_str(), (k>=3 && a[2].type==2)?a[2].v:1); } delete []a; return res; } if(!arg[0].compare(L"call")) { n = 1; if(a[0].type==1) { int na=0; a[0].s.assign(a[0].w.begin(),a[0].w.end()); n=-IsFunc(a[0].w.c_str(),&na); if(n && k!=na+2) { char buf[64]; snprintf(buf,64,"Bad arguments for %ls: %ld instead of %d\n", a[0].w.c_str(),k-2,na); buf[63]=0; gr->SetWarn(-1,buf); n = 1; } else if(n) { mglFnStack fn; fn.pos = pos; for(int i=0;i<10;i++) { fn.par[i] = par[i]; par[i]=L""; } for(int i=1;i<k-1;i++) AddParam(i,arg[i+1].c_str()); fn_stack.push_back(fn); n--; } else if(AllowFileIO) // disable external scripts if AllowFileIO=false { FILE *fp = fopen(a[0].s.c_str(),"rt"); if(fp) { register int i; mglParser *prs = new mglParser(AllowSetSize); prs->DataList.swap(DataList); prs->NumList.swap(NumList); prs->Cmd=Cmd; for(i=10;i<30;i++) prs->AddParam(i,par[i].c_str()); prs->Execute(gr,fp); for(i=10;i<30;i++) AddParam(i,prs->par[i].c_str()); DataList.swap(prs->DataList); NumList.swap(prs->NumList); prs->Cmd=0; delete prs; fclose(fp); } else n=1; } } delete []a; return n; } if(!arg[0].compare(L"for")) { n = 1; char ch = arg[1][0]; int r = ch-'0'; if(ch>='a' && ch<='z') r = 10+ch-'a'; // int r = int(a[0].v); if(arg[1][1]==0 && (r>=0 && r<40)) { if(a[1].type==0) { n=0; fval[r] = *(a[1].d); fval[r].nx *= fval[r].ny*fval[r].nz; } else if(a[1].type==2 && a[2].type==2 && a[2].v>a[1].v) { mreal step = a[3].type==2?a[3].v:1; mm = int(step>0 ? (a[2].v-a[1].v)/step : 0); if(mm>0) { n=0; fval[r].Create(mm+1); for(int ii=0;ii<mm+1;ii++) fval[r].a[ii] = a[1].v + step*ii; } } if(n==0) { for(int i=39;i>0;i--) { for_stack[i]=for_stack[i-1]; if_for[i]=if_for[i-1]; } for_stack[0] = r+1; fval[r].nz = pos; if_for[0]=if_pos; wchar_t buf[32]; mglprintf(buf,32,L"%g",fval[r].a[0]); AddParam(r, buf); fval[r].ny = 1; } } delete []a; return n; } // alocate new arrays and execute the command itself n = PreExec(gr, k, arg, a); if(n>0) n--; else if(!arg[0].compare(L"setsize") && !AllowSetSize) n = 2; else n = Exec(gr, arg[0].c_str(),k-1,a, arg[1].c_str(), opt.c_str()); delete []a; } // delete temporary data arrays for(size_t i=0;i<DataList.size();i++) if(DataList[i] && DataList[i]->temp) { mglDataA *u=DataList[i]; DataList[i]=0; delete u; } return n; }
//----------------------------------------------------------------------------- int mglParser::ParseDef(std::wstring &str) { if(!skip() && !str.compare(0,3,L"def") && (str[6]==' ' || str[6]=='\t')) { int res = 1; mreal d; PutArg(str,true); const std::wstring s = mgl_trim_ws(str.substr(7)); if(!str.compare(3,3,L"ine")) { int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1); if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10) { AddParam(nn, mgl_trim_ws(s.substr(2)).c_str()); return 1; } } if(!str.compare(3,3,L"num")) { int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1); if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10) { res = 0; HMDT dd = mglFormulaCalc(mgl_trim_ws(s.substr(2)), this, DataList); d = dd->a[0]; delete dd; char buf[32]; snprintf(buf,32,"%g",d); buf[31] = 0; AddParam(nn, buf); } return res+1; } if(!str.compare(3,3,L"chr")) { int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1); if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10) { res = 0; HMDT dd = mglFormulaCalc(mgl_trim_ws(s.substr(2)), this, DataList); d=dd->a[0]; delete dd; wchar_t buf[2]={0,0}; buf[0] = wchar_t(d); AddParam(nn, buf); } return res+1; } } if(!skip() && !str.compare(0,3,L"ask") && (str[3]==' ' || str[3]=='\t')) { PutArg(str,true); std::wstring s = mgl_trim_ws(str.substr(4)); int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1); if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10) { s = mgl_trim_ws(s.substr(2)); if(s[0]=='\'') s=s.substr(1,s.length()-2); if(mgl_ask_func) { static wchar_t res[1024]; mgl_ask_func(s.c_str(),res); if(*res) AddParam(nn, res); } return mgl_ask_func?1:2; } else return 2; } if(!skip() && !str.compare(0,3,L"for") && (str[3]==' ' || str[3]=='\t')) { size_t i; for(i=4;str[i]<=' ';i++); // if command have format 'for $N ...' then change it to 'for N ...' if(str[i]=='$' && str[i+1]>='0' && str[i+1]<='9') str[i] = ' '; if(str[i]=='$' && str[i+1]>='a' && str[i+1]<='z') str[i] = ' '; } return 0; }