Пример #1
0
//-----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
	mgl_suppress_warn(true);
	mglGraph gr;
	mglParse p(true);
	char buf[2048], iname[256]="", oname[256]="";
	std::vector<std::wstring> var;
	std::wstring str;
	bool none=false;

	while(1)
	{
		int ch = getopt(argc, argv, "1:2:3:4:5:6:7:8:9:hno:L:C:A:s:S:q:v:g:");
		if(ch>='1' && ch<='9')	p.AddParam(ch-'0', optarg);
		else if(ch=='s')
		{
			setlocale(LC_CTYPE, "");
			FILE *fp = fopen(optarg,"r");
			if(fp)
			{
				wchar_t ch;
				while(!feof(fp) && size_t(ch=fgetwc(fp))!=WEOF)	str.push_back(ch);
				fclose(fp);	str += L"\n";
			}
		}
		else if(ch=='n')	none = true;
		else if(ch=='L')	setlocale(LC_CTYPE, optarg);
		else if(ch=='S')	mgl_set_size_scl(atof(optarg));
		else if(ch=='q')	gr.SetQuality(atoi(optarg));
		else if(ch=='v')	p.SetVariant(atoi(optarg));
		else if(ch=='g')	gr.Gray(atoi(optarg));
		else if(ch=='A')
		{
			std::wstring str;
			for(size_t i=0;optarg[i];i++)	str.push_back(optarg[i]);
			var.push_back(str);
		}
		else if(ch=='C')
		{
			double v1,v2,dv=1,v;
			int res=sscanf(optarg,"%lg:%lg:%lg",&v1,&v2,&dv);
			if(res<3)	dv=1;
			wchar_t num[64];
			for(v=v1;v<=v2;v+=dv)
			{
				mglprintf(num,64,L"%g",v);
				var.push_back(num);
			}
		}
		else if(ch=='h' || (ch==-1 && optind>=argc))
		{
			printf("mglconv convert mgl script to bitmap png file.\nCurrent version is 2.%g\n",MGL_VER2);
			printf("Usage:\tmglconv [parameter(s)] scriptfile\n");
			printf(
				"\t-1 str       set str as argument $1 for script\n"
				"\t...          ...\n"
				"\t-9 str       set str as argument $9 for script\n"
				"\t-L loc       set locale to loc\n"
				"\t-s fname     set MGL script for setting up the plot\n"
				"\t-S val       set scaling factor for images\n"
				"\t-q val       set quality for output (val=0...9)\n"
				"\t-g val       set gray-scale mode (val=0|1)\n"
				"\t-v val       set variant of arguments\n"
				"\t-o name      set output file name\n"
				"\t-n           no default output (script should save results by itself)\n"
				"\t-A val       add animation value val\n"
				"\t-C n1:n2:dn  add animation value in range [n1,n2] with step dn\n"
				"\t-C n1:n2     add animation value in range [n1,n2] with step 1\n"
				"\t-            get script from standard input\n"
				"\t-h           print this message\n" );
			return 0;
		}
		else if(ch=='o')	strncpy(oname, optarg,256);
		else if(ch==-1 && optind<argc)
		{	strncpy(iname, argv[optind][0]=='-'?"":argv[optind],256);	break;	}
	}
	if(*oname==0)	{	strncpy(oname,*iname?iname:"out",250);	strcat(oname,".png");	}
	else	none = false;

	mgl_ask_func = mgl_ask_gets;
	// prepare for animation
	setlocale(LC_CTYPE, "");
	FILE *fp = *iname?fopen(iname,"r"):stdin;
	if(!fp)	{	printf("No file for MGL script\n");	return 0;	}
	wchar_t cw;
	while(!feof(fp) && size_t(cw=fgetwc(fp))!=WEOF)	str.push_back(cw);
	if(*iname)	fclose(fp);

	size_t n;
	for(size_t i=0;;)	// collect exact values
	{
		n = str.find(L"##a ",i);
		if (n == mnpos)	break;
		i = n+4;	var.push_back(str.substr(i,str.find('\n',i)));
	}
	n = str.find(L"##c ");
	if (n != mnpos)
		{
		double v1,v2,dv,v;
		wscanf(str.c_str()+n+4,L"%lg%lg%lg",&v1,&v2,&dv);
		wchar_t ss[64];
		for(v=v1;v<=v2;v+=dv)
		{	mglprintf(ss,64,L"%g",v);	var.push_back(ss);	}
	}
	bool gif = !strcmp(oname+strlen(oname)-4,".gif");
	gr.SetSize(600,400);	// specially call for "S" option
	if(var.size()>1)	// there is animation
	{
		if(gif)	gr.StartGIF(oname);
		for(size_t i=0;i<var.size();i++)
		{
			gr.NewFrame();
			printf("frame %zu for $0 = \"%ls\"\n",i,var[i].c_str());
			p.AddParam(0,var[i].c_str());
			p.Execute(&gr,str.c_str());
			if(gr.Message()[0])	printf("%s\n",gr.Message());
			gr.EndFrame();
			snprintf(buf,2048,"%s-%zu",oname,i);	buf[2047]=0;
			if(!gif)	gr.WriteFrame(buf);
		}
		if(gif)	gr.CloseGIF();
	}
	else
	{
		p.Execute(&gr,str.c_str());
		if(gr.Message()[0])	printf("%s\n",gr.Message());
		if(!none)	gr.WriteFrame(oname);
	}
	if(!mglGlobalMess.empty())	printf("%s",mglGlobalMess.c_str());
	if(!none || gif)	printf("Write output to %s\n",oname);
	return 0;
}
Пример #2
0
//-----------------------------------------------------------------------------
// 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;
}
Пример #3
0
//-----------------------------------------------------------------------------
int mglParser::FlowExec(mglGraph *, const std::wstring &com, long m, mglArg *a)
{
	int n=-1;
	if(!ifskip() && !com.compare(L"once"))
	{
		if(a[0].type==2)
		{
			n = 0;
			if(a[0].v)	Skip = !Once;
			else	Skip = Once = false;
		}
		else n = 1;
	}
	else if(!Skip && !com.compare(L"if"))
	{
		int cond;
		if(a[0].type==2)
		{	n = 0;	cond = (a[0].v!=0)?3:0;	}
		else if(a[0].type==0)
		{
			n = 0;	a[1].s.assign(a[1].w.begin(),a[1].w.end());
			cond = a[0].d->FindAny((m>1 && a[1].type==1) ? a[1].s.c_str():"u")?3:0;
		}
		else n = 1;
		if(n==0)
		{	if_stack[if_pos] = cond;	if_pos = if_pos<39 ? if_pos+1 : 39;	}
	}
	else if(!Skip && !com.compare(L"endif"))
	{	if_pos = if_pos>0 ? if_pos-1 : 0;	n = 0;	}
	else if(!Skip && !com.compare(L"else"))
	{
		if(if_pos>0)
		{	n=0; if_stack[if_pos-1] = (if_stack[if_pos-1]&2)?2:3;	}
		else n = 1;
	}
	else if(!Skip && !com.compare(L"elseif"))
	{
		int cond;
		if(if_pos<1 || m<1)	n = 1;
		else if(if_stack[if_pos-1]&2)	{	n = 0;	cond = 2;	}
		else if(a[0].type==2)
		{	n = 0;	cond = (a[0].v!=0)?3:0;	}
		else if(a[0].type==0)
		{
			n = 0;	a[1].s.assign(a[1].w.begin(),a[1].w.end());
			cond = a[0].d->FindAny((m>1 && a[1].type==1) ? a[1].s.c_str():"u")?3:0;
		}
		else n = 1;
		if(n==0)	if_stack[if_pos-1] = cond;
	}
	else if(!ifskip() && !Skip && !com.compare(L"break"))
	{
		if(if_pos==if_for[0])	if_pos = if_pos>0 ? if_pos-1 : 0;
	}
	else if(!skip() && !com.compare(L"return"))
	{
		if(fn_stack.size()<1)	return 2;
		const mglFnStack &fn=fn_stack.back();
		for(int i=0;i<10;i++)	par[i]=fn.par[i];
		n = -fn.pos-1;	fn_stack.pop_back();
	}
	else if(!ifskip() && !Skip && !com.compare(L"next"))
	{
		if(if_pos==if_for[0])	if_pos = if_pos>0 ? if_pos-1 : 0;
		int r = for_stack[0]-1;
		n = for_stack[0] ? 0:1;
		if(for_stack[0])
		{
			if(fval[r].ny<fval[r].nx && !for_br)
			{
				wchar_t buf[32];		mglprintf(buf,32,L"%g",fval[r].a[fval[r].ny]);
				AddParam(r, buf);	fval[r].ny += 1;
				n = -fval[r].nz-1;
			}
			else
			{
				for(int i=0;i<39;i++)
				{	for_stack[i]=for_stack[i+1];	if_for[i]=if_for[i+1];	}
				for_stack[39] = 0;	for_br=false;
			}
		}
	}
	else if(!ifskip() && !Skip && !com.compare(L"continue"))
	{
		if(if_pos==if_for[0])	if_pos = if_pos>0 ? if_pos-1 : 0;
		int r = for_stack[0]-1;
		n = for_stack[0] ? 0:1;
		if(for_stack[0])
		{
			if(fval[r].ny<fval[r].nx)
			{
				wchar_t buf[32];		mglprintf(buf,32,L"%g",fval[r].a[fval[r].ny]);
				AddParam(r, buf);	fval[r].ny += 1;
				n = -fval[r].nz-1;
			}
			else	for_br = true;
		}
	}
	return n+1;
}
Пример #4
0
//-----------------------------------------------------------------------------
// convert substrings to arguments
void mglParser::FillArg(mglGraph *gr, int k, std::wstring *arg, mglArg *a)
{
	register long n;
	for(n=1;n<k;n++)
	{
		mglDataA *v;	mglNum *f;
		a[n-1].type = -1;
		if(arg[n][0]=='|')	a[n-1].type = -1;
		else if(arg[n][0]=='\'')	// this is string (simplest case)
		{
			a[n-1].type = 1;
			std::wstring &w=arg[n],f;
			wchar_t buf[32];
			long i,i1,ll=w.length();
			for(i=1;i<ll;i++)
			{
				if(w[i]=='\'')
				{
					if(i==ll-1)	continue;
					i++;	i1 = i;
					if(w[i1]==',')	i1++;
					if(w[i1]==0)	continue;
					for(;i<ll && w[i]!='\'';i++);
					if(i>i1)
					{
						if(w[i1]=='!')
						{
							HADT d = mglFormulaCalcC(w.substr(i1+1,i-i1-(w[i]=='\''?1:0)), this, DataList);
							mreal di = imag(d->a[0]), dr = real(d->a[0]);
							if(di>0)	mglprintf(buf,32,L"%g+%gi",dr,di);
							else if(di<0)	mglprintf(buf,32,L"%g-%gi",dr,-di);	// TODO use \u2212 ???
							else	mglprintf(buf,32,L"%g",dr);
							a[n-1].w += buf;	delete d;
						}
						else
						{
							HMDT d = mglFormulaCalc(w.substr(i1,i-i1-(w[i]=='\''?1:0)), this, DataList);
							mglprintf(buf,32,L"%g",d->a[0]);	a[n-1].w += buf;	delete d;
						}
					}
				}
				else	a[n-1].w += w[i];
			}
		}
		else if(arg[n][0]=='{')
		{	// this is temp data
			mglData *u=new mglData;
			std::wstring s = arg[n].substr(1,arg[n].length()-2);
			a[n-1].w = u->s = L"/*"+s+L"*/";
			a[n-1].type = 0;
			ParseDat(gr, s, *u);	a[n-1].d = u;
			u->temp=true;	DataList.push_back(u);
		}
		else if((v = FindVar(arg[n].c_str()))!=0)	// try to find normal variables (for data creation)
		{	a[n-1].type=0;	a[n-1].d=v;	a[n-1].w=v->s;	}
		else if((f = FindNum(arg[n].c_str()))!=0)	// try to find normal number (for data creation)
		{	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].w = f->s;	}
		else if(arg[n][0]=='!')	// complex array is asked
		{	// parse all numbers and formulas by unified way
			HADT d = mglFormulaCalcC(arg[n].substr(1), this, DataList);
			if(d->GetNN()==1)
			{
				if(CheckForName(arg[n].substr(1)))
				{	a[n-1].type = 2;	a[n-1].v = d->v(0);	a[n-1].c = d->a[0];	}
				else
				{	a[n-1].type = 0;	a[n-1].d = AddVar(arg[n].c_str());	}
				delete d;
			}
			else
			{
				a[n-1].w = L"/*"+arg[n]+L"*/";
				d->temp=true;	DataList.push_back(d);
				a[n-1].type = 0;	a[n-1].d = d;
			}
		}
		else
		{	// parse all numbers and formulas by unified way
			HMDT d = mglFormulaCalc(arg[n], this, DataList);
			if(d->GetNN()==1)
			{
				if(CheckForName(arg[n]))
				{	a[n-1].type = 2;	a[n-1].c = a[n-1].v = d->v(0);	}
				else
				{	a[n-1].type = 0;	a[n-1].d = AddVar(arg[n].c_str());	}
				delete d;
			}
			else
			{
				a[n-1].w = L"/*"+arg[n]+L"*/";
				d->temp=true;	DataList.push_back(d);
				a[n-1].type = 0;	a[n-1].d = d;
			}
		}
	}
}