/* Steven Andrews, 9/98	*//* Spectrum fitting program *//* See documentation called SpectFit doc *//* Copyright 2003 by Steven Andrews.  Permission is granted   for non-commercial use of and modifications to the code. */#include <ctype.h>#include <stdio.h>#include <string.h>#include <math.h>#include <float.h>#include "errors.h"#include "Rn.h"#include "Cn.h"#include "RnSort.h"#include "Spectra.h"#include "Plot.h"#include "Set.h"#include "BasisFn.h"#include "DiskIO.h"#include "Utility.h"#include "math2.h"#include "VoidComp.h"#include "string2.h"#include "SpectFit.h"#include "errors.h"struct result{	void *val;	void **valptr;	char type;	int temp;	int var;	int er; };int UpdateModels(modelptr m);void drawplot();void mouse();int tweak(modelptr m);void ClearSpect(sptr s,int fre);void ClearBasis(basisptr b);void ClearModel(modelptr m,int fre);void ClearString(char *name);int CreateSpect(sptr s);int CreateModel(modelptr m);int CreateNumber(char *name,float f);int CreateString(char *name,char *str);void ResultFree(struct result ans);int CheckArgs(struct result *ag,int arg,char *str);struct result dosymbol(char *expr,int i);struct result dodots(char *expr,int i);struct result doword(char *cmd,char *expr);struct result evalexpr(char *expr);struct result doassign(char *lhs,char *rhs);int docommand(char *cmd);int doline(char *cmd);void debug();set Spectra,Plotlist,Models,Numbers,Strings;modelptr Model;int Logcmd;int Need2Plot,Need2Update;/* Routines available externally */int UpdateModel(modelptr m) {	void *x,*k;	struct scell *trace;	basisptr b;	char str[STRCHAR];	int i,out;	struct result ans;	float f;	if(!m) return 0;	out=0;	for(trace=SetNext(NULL,&k,&x,m->basis);trace;trace=SetNext(trace,&k,&x,m->basis)) {		b=(basisptr) x;		for(i=0;i<b->n;i++)			if(b->freeze[i]&&strlen(b->eqn[i])) {				strncpy(str,b->eqn[i],STRCHAR);				ans=evalexpr(str);				if(ans.type!='F') out=18;				else if(!((f=*((float*)ans.val))>-FLT_MAX&&f<FLT_MAX)) out=(out>17)?out:17;				else if(b->param[i]!=f) {					b->param[i]=f;					out=out?out:-1; }}}	return out; }int UpdateModels() {	int er;	void *x,*k;	struct scell *trace;	er=0;	for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))		if(er>0) UpdateModel((modelptr)x);		else er=UpdateModel((modelptr)x);	Need2Update=0;	if(er<0) er=0;	return er; }sptr Name2Spec(char *str) {	return (sptr) SetItem((void*)str,Spectra); }/* Drawing routines */void drawplot() {	void *k,*x,*km,*xm;	struct scell *trace,*tracem;		PlotClear();	ShowLimits();	for(trace=SetNext(NULL,&k,&x,Plotlist);trace;trace=SetNext(trace,&k,&x,Plotlist))	{		if(SetMember(k,x,Models))	PlotModel((modelptr) x);		else if(SetMember(k,x,Spectra)) PlotSpect((sptr) x);		else {			for(tracem=SetNext(NULL,&km,&xm,Models);tracem;tracem=SetNext(tracem,&km,&xm,Models))				if(SetMember(k,x,((modelptr) xm)->basis)) PlotBasis((basisptr) x); }}	Need2Plot=0;	return; }void mouse() {	int a,b;	char c,dispstr[STRCHAR];	float x,y;	fprintf(stderr,"Press any key to stop.\n");	c=0;	while(!c)	{		c=Wait4Mouse(&a,&b);		if(!c&&ToPoint(a,b,&x,&y)) {			PlotPt(x,y);			fprintf(stderr,"%f, %f\n",x,y); }}	return; }int tweak(modelptr m) {	char c,oldc,dispstr[2*STRCHAR],cmdstr[STRCHAR];	int i,j,np;	struct scell *trace;	void *k,*item;	float **p,*rate,dispx,dispy;	char **pname,**bname;	int *freeze;	basisptr b;	if(!m) return 0;	np=m->np;	if(!np) return 42;	p=(float **) calloc(np,sizeof(float *));							/* pointers to parameters */	pname=(char **) calloc(np,sizeof(char *));						/* pointers to pnames */	bname=(char **) calloc(np,sizeof(char *));						/* pointers to basis names */	freeze=(int *) calloc(np,sizeof(int));								/* pointers to frozeness */	rate=allocV(np);	if(!p||!pname||!bname||!freeze||!rate) {		if(p) free(p);		if(pname) free(pname);		if(bname) free(bname);		if(freeze) free(freeze);		if(rate) freeV(rate);		return 1; }	if(m->covar) {		freeM(m->covar);		m->covar=NULL; }	j=0;	for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))		for(i=0;i<(b=(basisptr) item)->n;i++)	{			p[j]=&b->param[i];			pname[j]=b->pname[i];			bname[j]=b->name;			freeze[j]=b->freeze[i];			rate[j]=0.01;			j++; }	j=0;	oldc=0;	fprintf(stderr,"Press escape to stop tweaking.\n");	while((c=inkey())!=27) {						/* escape	*/		if(!c);														/* nothing */			else if(c==28)	{									/* left arrow */			if(--j<0)	j=np-1;			oldc=28; }		else if(c==29)	{									/* right arrow */			if(++j>=np)	j=0;			oldc=29; }		else if(c==30)	{									/* up arrow */			if(*p[j]>0)	*p[j]*=(1+rate[j]);			else if(*p[j]<0) *p[j]/=(1+rate[j]);			else *p[j]=0.001;			if(oldc==30) rate[j]*=1.5;			else if(oldc==31) rate[j]/=5;			UpdateModel(m);			oldc=30; }		else if(c==31)	{									/* down arrow */			if(*p[j]>0) *p[j]/=(1+rate[j]);			else if(*p[j]<0) *p[j]*=(1+rate[j]);			else *p[j]=-0.001;			if(oldc==31) rate[j]*=1.5;			else if(oldc==30) rate[j]/=5;			UpdateModel(m);			oldc=31; }		else if(c=='-')	{									/* - sign	*/			*p[j]=-*p[j];			UpdateModel(m);			oldc='-'; }		else if(c=='m'||c=='s'||c=='a') {			if(c=='m') sprintf(cmdstr,"scale %s",m->name);			else if(c=='s'&&m->spec) sprintf(cmdstr,"scale %s",m->spec->name);			else if(c=='a') sprintf(cmdstr,"scale");			else cmdstr[0]='\0';			docommand(cmdstr); }		if(c||!oldc) {			drawplot();			sprintf(dispstr,"%s.%s: %f %s",bname[j],pname[j],*p[j],freeze[j]?"fix":"");			ToPoint(10,10,&dispx,&dispy);			PlotStr(dispx,dispy,dispstr);			if(!oldc) oldc=1; }}	Need2Plot=1;	free(p);	free(pname);	free(bname);	free(freeze);	freeV(rate);	return 0; }/* Set management routines */void ClearSpect(sptr s,int fre) {	void *k,*x,*kb,*xb;	struct scell *trace,*traceb;	modelptr m;	if(!s) return;	if(SetMember((void *) s->name,(void *) s,Plotlist))	{		SetDelete((void *) s->name,(void *) s,Plotlist,0,0);		Need2Plot=1; }	for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))	{		m=(modelptr)x;		if(m->spec==s) m->spec=NULL;		else if(m->uncert==s) m->uncert=NULL;		else			for(traceb=SetNext(NULL,&kb,&xb,m->basis);traceb;traceb=SetNext(traceb,&kb,&xb,m->basis))				if(((basisptr) xb)->spec==s)					ClearBasis((basisptr) xb); }	if(SetMember((void *) s->name,(void *) s,Spectra))		SetDelete((void *) s->name,(void *) s,Spectra,0,0);	if(fre) SpectFree(s);	return; }void ClearBasis(basisptr b) {	if(!b) return;	if(SetDelete((void *) b->name,(void *) b,Plotlist,0,0))		Need2Plot=1;	RemoveBasis(b);	BasisFree(b);	return; }void ClearModel(modelptr m,int fre) {	void *k,*x;	struct scell *trace;	if(!m) return;	if(SetMember((void *) m->name,(void *) m,Plotlist))	{		SetDelete((void *) m->name,(void *) m,Plotlist,0,0);		Need2Plot=1; }	if(SetMember((void *) m->name,(void *) m,Models))		SetDelete((void *) m->name,(void *) m,Models,0,0);	for(trace=SetNext(NULL,&k,&x,m->basis);trace;trace=SetNext(trace,&k,&x,m->basis))		ClearBasis((basisptr) x);	if(Model==m) SetNext(NULL,&k,&((void *) Model),Models);	if(fre) ModelFree(m);	return; }void ClearString(char *name) {	char *str;	if(!name) return;	str=(char*) SetItem((void*)name,Strings);	if(str) SetDelete((void*) name,(void*) str,Strings,1,1);	return; }int CreateSpect(sptr s) {	sptr sold;	void *k,*x,*kb,*xb;	struct scell *trace,*traceb;	modelptr m;	basisptr b;	int er;	er=0;	sold=(sptr) SetItem((void *)s->name,Spectra);	if(sold) {		strncpy(s->color,sold->color,STRCHAR);		if(SetMember((void *) sold->name,(void *) sold,Plotlist))	{			SetDelete((void *) sold->name,(void *) sold,Plotlist,0,0);			if(SetInsert((void *) s->name,(void *) s,Plotlist)!=1) er=1;			Need2Plot=1; }		for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))	{			m=(modelptr)x;			if(m->spec==sold) {				m->spec=s;				if(er=CheckMSpec(m)) m->spec=NULL; }			if(m->uncert==sold) {				m->uncert=s;				if(er=CheckUncert(m)) m->uncert=NULL; }			for(traceb=SetNext(NULL,&kb,&xb,m->basis);traceb;traceb=SetNext(traceb,&kb,&xb,m->basis))				if(((basisptr) xb)->spec==sold) {					b=(basisptr)xb;					b->spec=s;					if(er=CheckBasis(b,NULL)) ClearBasis(b); }}		SetDelete((void *) sold->name,(void *) sold,Spectra,0,0);		SpectFree(sold); }	if(SetInsert((void *) s->name,(void *) s,Spectra)!=1) er=1;	if(er==1) ClearSpect(s,0);	return er; }int CreateModel(modelptr m) {	modelptr mold;	int er;	er=0;	mold=(modelptr) SetItem((void *) m->name,Models);	if(mold) {		strncpy(m->color,mold->color,STRCHAR);		if(SetMember((void *) mold->name,(void *) mold,Plotlist))	{			SetDelete((void *) mold->name,(void *) mold,Plotlist,0,0);			if(SetInsert((void *) m->name,(void *) m,Plotlist)!=1) er=1;			Need2Plot=1; }		ClearModel(mold,1); }	if(SetInsert((void *) m->name,(void *) m,Models)!=1) er=1;	if(!er) Model=m;	if(er) ClearModel(m,0);	return er; }int CreateNumber(char *name,float f) {	int er;	float *fptr;	char *ncpy;	er=0;	fptr=(float *) SetItem((void*)name,Numbers);	if(fptr) *fptr=f;	else {		ncpy=StringCopy(name);		if(!ncpy) return 1;		fptr=(float*) malloc(sizeof(float));		if(!fptr) {free(ncpy);return 1;}		*fptr=f;		if(SetInsert((void *)ncpy,(void*)fptr,Numbers)!=1) er=1; }	return er; }int CreateString(char *name,char *str) {	int er;	char *str2,*name2;	er=0;	str2=(char*) SetItem((void*)name,Strings);	if(str2&&strlen(str2)>=strlen(str)) strcpy(str2,str);	else {		str2=StringCopy(str);		if(!str2) return 1;		name2=StringCopy(name);		if(!name2) {free(str2);return 1;}		ClearString(name);		if(SetInsert((void*)name2,(void*)str2,Strings)!=1) er=1; }	return er; }void ResultFree(struct result ans) {	if(ans.temp&&ans.val)	{		if(ans.type=='F') free(ans.val);		else if(ans.type=='S') SpectFree((sptr) ans.val);		else if(ans.type=='C') free(ans.val);		else if(ans.type=='W') free(ans.val);		else if(ans.type=='B') BasisFree((basisptr) ans.val);		else if(ans.type=='M') ModelFree((modelptr) ans.val); }	return; }int CheckArgs(struct result *ag,int arg,char *str) {	int i,len;	char a,s;	len=strlen(str);	for(i=0;i<arg&&i<len;i++) {		a=ag[i].type;		s=str[i];		if(s=='.') {			for(;i<arg;i++)				if(ag[i].er) return ag[i].er;				else if(ag[i].type=='?') return 999;				else if(ag[i].type!=' '&&!ag[i].val) return 28;			return 0; }		else if(ag[i].er) return ag[i].er;		else if(a=='?') return 999;		else if(a!=' '&&!ag[i].val) return 28;		else if(a==toupper(s));		else if(a==' '&&islower(s));		else if(s=='X'&&a!=' ');		else if(s=='x');		else return 27; }	if(i<arg) return 25;	for(;i<len;i++)		if(str[i]=='.') return 0;		else if(isupper(str[i])) return 26;	return 0; }/* Parsing routines */struct result dosymbol(char *expr,int at) {	char sym;	struct result left,right,ans;	void *vdptr;		ans.val=ans.valptr=NULL;	ans.type='?';	ans.temp=1;	ans.var=0;	ans.er=0;	vdptr=NULL;	sym=expr[at];	expr[at]='\0';	left=evalexpr(expr);	right=evalexpr(expr+at+1);	expr[at]=sym;	if(left.er)		ans.er=left.er;	else if(right.er)		ans.er=right.er;	else if(!left.val&&left.type!=' ')		ans.er=19;	else if(!right.val&&right.type!=' ')		ans.er=19;	else if(left.type=='?'||right.type=='?')		ans.er=999;	else if(right.type==' ')		ans.er=19;	else if(left.type==' '&&right.type=='F')	{		ans.val=malloc(sizeof(float));		if(!ans.val) ans.er=1;		else if(sym=='+')	*((float *) ans.val)=*((float *) right.val);		else if(sym=='-')	*((float *) ans.val)=-*((float *) right.val);		else {free(ans.val);ans.er=20;}		if(!ans.er) ans.type='F'; }	else if(left.type=='F'&&right.type=='F')	{		ans.val=malloc(sizeof(float));		if(!ans.val) ans.er=1;		else if(sym=='+')	*((float *) ans.val)=*((float *) left.val)+*((float *) right.val);		else if(sym=='-')	*((float *) ans.val)=*((float *) left.val)-*((float *) right.val);		else if(sym=='*')	*((float *) ans.val)=*((float *) left.val)**((float *) right.val);		else if(sym=='/')	*((float *) ans.val)=*((float *) left.val)/ *((float *) right.val);		else if(sym=='^') *((float *) ans.val)=pow(*((float *) left.val),*((float *) right.val));		else {free(ans.val);ans.er=20;}		if(!ans.er) ans.type='F'; }	else if(left.type==' '&&right.type=='S')	{		if(sym=='+')	ans.er=SpectMath((sptr) right.val,NULL,&(sptr)ans.val,"copy",0);		else if(sym=='-')	ans.er=SpectMath((sptr) right.val,NULL,&(sptr)ans.val,"s*k",-1);		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='F'&&right.type=='S')	{		if(sym=='+')	ans.er=SpectMath((sptr) right.val,NULL,&(sptr)ans.val,"k+s",*((float *) left.val));		else if(sym=='-')	ans.er=SpectMath((sptr) right.val,NULL,&(sptr)ans.val,"k-s",*((float *) left.val));		else if(sym=='*')	ans.er=SpectMath((sptr) right.val,NULL,&(sptr)ans.val,"k*s",*((float *) left.val));		else if(sym=='/')	ans.er=SpectMath((sptr) right.val,NULL,&(sptr)ans.val,"k/s",*((float *) left.val));		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='S'&&right.type=='F')	{		if(sym=='+')	ans.er=SpectMath((sptr) left.val,NULL,&(sptr)ans.val,"s+k",*((float *) right.val));		else if(sym=='-')	ans.er=SpectMath((sptr) left.val,NULL,&(sptr)ans.val,"s-k",*((float *) right.val));		else if(sym=='*')	ans.er=SpectMath((sptr) left.val,NULL,&(sptr)ans.val,"s*k",*((float *) right.val));		else if(sym=='/')	ans.er=SpectMath((sptr) left.val,NULL,&(sptr)ans.val,"s/k",*((float *) right.val));		else if(sym=='^')	ans.er=SpectMath((sptr) left.val,NULL,&(sptr)ans.val,"s^k",*((float *) right.val));		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='S'&&right.type=='S')	{		if(sym=='+')	ans.er=SpectMath((sptr) left.val,(sptr) right.val,&(sptr)ans.val,"s+s",0);		else if(sym=='-')	ans.er=SpectMath((sptr) left.val,(sptr) right.val,&(sptr)ans.val,"s-s",0);		else if(sym=='*')	ans.er=SpectMath((sptr) left.val,(sptr) right.val,&(sptr)ans.val,"s*s",0);		else if(sym=='/')	ans.er=SpectMath((sptr) left.val,(sptr) right.val,&(sptr)ans.val,"s/s",0);		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type==' '&&right.type=='B')	{		if(sym=='+')	ans.er=BasisMath((basisptr) right.val,NULL,&(sptr)ans.val,0,"k+b");		else if(sym=='-')	ans.er=BasisMath((basisptr) right.val,NULL,&(sptr)ans.val,0,"k-b");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type==' '&&right.type=='M')	{		if(sym=='+')	ans.er=ModelMath((modelptr) right.val,NULL,&(sptr)ans.val,0,"k+m");		else if(sym=='-')	ans.er=ModelMath((modelptr) right.val,NULL,&(sptr)ans.val,0,"k-m");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='B'&&right.type=='S')	{		if(sym=='+')	ans.er=BasisMath((basisptr) left.val,right.val,&(sptr)ans.val,0,"b+s");		else if(sym=='-')	ans.er=BasisMath((basisptr) left.val,right.val,&(sptr)ans.val,0,"b-s");		else if(sym=='*')	ans.er=BasisMath((basisptr) left.val,right.val,&(sptr)ans.val,0,"b*s");		else if(sym=='/')	ans.er=BasisMath((basisptr) left.val,right.val,&(sptr)ans.val,0,"b/s");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='S'&&right.type=='B')	{		if(sym=='+') ans.er=BasisMath((basisptr) right.val,left.val,&(sptr)ans.val,0,"s+b");		else if(sym=='-')	ans.er=BasisMath((basisptr) right.val,left.val,&(sptr)ans.val,0,"s-b");		else if(sym=='*')	ans.er=BasisMath((basisptr) right.val,left.val,&(sptr)ans.val,0,"s*b");		else if(sym=='/')	ans.er=BasisMath((basisptr) right.val,left.val,&(sptr)ans.val,0,"s/b");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='M'&&right.type=='S')	{		if(sym=='+')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m+s");		else if(sym=='-')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m-s");		else if(sym=='*')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m*s");		else if(sym=='/')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m/s");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='S'&&right.type=='M')	{		if(sym=='+')	ans.er=ModelMath((modelptr) right.val,left.val,&(sptr)ans.val,0,"s+m");		else if(sym=='-')	ans.er=ModelMath((modelptr) right.val,left.val,&(sptr)ans.val,0,"s-m");		else if(sym=='*')	ans.er=ModelMath((modelptr) right.val,left.val,&(sptr)ans.val,0,"s*m");		else if(sym=='/')	ans.er=ModelMath((modelptr) right.val,left.val,&(sptr)ans.val,0,"s/m");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='B'&&right.type=='B')	{		if(sym=='+')	ans.er=BasisMath((basisptr) left.val,right.val,&(sptr)ans.val,0,"b+b");		else if(sym=='-')	ans.er=BasisMath((basisptr) left.val,right.val,&(sptr)ans.val,0,"b-b");		else if(sym=='*')	ans.er=BasisMath((basisptr) left.val,right.val,&(sptr)ans.val,0,"b*b");		else if(sym=='/')	ans.er=BasisMath((basisptr) left.val,right.val,&(sptr)ans.val,0,"b/b");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='M'&&right.type=='M')	{		if(sym=='+')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m+m");		else if(sym=='-')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m-m");		else if(sym=='*')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m*m");		else if(sym=='/')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m/m");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='M'&&right.type=='B')	{		if(sym=='+')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m+b");		else if(sym=='-')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m-b");		else if(sym=='*')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m*b");		else if(sym=='/')	ans.er=ModelMath((modelptr) left.val,right.val,&(sptr)ans.val,0,"m/b");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='B'&&right.type=='M')	{		if(sym=='+')	ans.er=ModelMath((modelptr) right.val,left.val,&(sptr)ans.val,0,"b+m");		else if(sym=='-')	ans.er=ModelMath((modelptr) right.val,left.val,&(sptr)ans.val,0,"b-m");		else if(sym=='*')	ans.er=ModelMath((modelptr) right.val,left.val,&(sptr)ans.val,0,"b*m");		else if(sym=='/')	ans.er=ModelMath((modelptr) right.val,left.val,&(sptr)ans.val,0,"b/m");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='B'&&right.type=='F')	{		if(sym=='+')	ans.er=BasisMath((basisptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"b+k");		else if(sym=='-')	ans.er=BasisMath((basisptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"b-k");		else if(sym=='*')	ans.er=BasisMath((basisptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"b*k");		else if(sym=='/')	ans.er=BasisMath((basisptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"b/k");		else if(sym=='^')	ans.er=BasisMath((basisptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"b^k");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='F'&&right.type=='B')	{		if(sym=='+')	ans.er=BasisMath((basisptr) right.val,NULL,&(sptr)ans.val,*((float *) left.val),"k+b");		else if(sym=='-')	ans.er=BasisMath((basisptr) right.val,NULL,&(sptr)ans.val,*((float *) left.val),"k-b");		else if(sym=='*')	ans.er=BasisMath((basisptr) right.val,NULL,&(sptr)ans.val,*((float *) left.val),"k*b");		else if(sym=='/')	ans.er=BasisMath((basisptr) right.val,NULL,&(sptr)ans.val,*((float *) left.val),"k/b");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='M'&&right.type=='F')	{		if(sym=='+')	ans.er=ModelMath((modelptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"m+k");		else if(sym=='-')	ans.er=ModelMath((modelptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"m-k");		else if(sym=='*')	ans.er=ModelMath((modelptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"m*k");		else if(sym=='/')	ans.er=ModelMath((modelptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"m/k");		else if(sym=='^')	ans.er=ModelMath((modelptr) left.val,NULL,&(sptr)ans.val,*((float *) right.val),"m^k");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='F'&&right.type=='M')	{		if(sym=='+')	ans.er=ModelMath((modelptr) right.val,NULL,&(sptr)ans.val,*((float *) left.val),"k+m");		else if(sym=='-')	ans.er=ModelMath((modelptr) right.val,NULL,&(sptr)ans.val,*((float *) left.val),"k-m");		else if(sym=='*')	ans.er=ModelMath((modelptr) right.val,NULL,&(sptr)ans.val,*((float *) left.val),"k*m");		else if(sym=='/')	ans.er=ModelMath((modelptr) right.val,NULL,&(sptr)ans.val,*((float *) left.val),"k/m");		else ans.er=20;		if(!ans.er) ans.type='S'; }	else if(left.type=='C'&&right.type=='C')	{		ans.val=calloc(STRCHAR,sizeof(char));		if(!ans.val) ans.er=1;		else if(sym=='+')	{			strncpy((char *) ans.val,(char *) left.val,STRCHAR);			strncat((char *) ans.val,(char *) right.val,STRCHAR-strlen((char *) ans.val)); }		else {free(ans.val);ans.er=20;}		if(!ans.er) ans.type='C'; }	else		ans.er=21;	ResultFree(left);	ResultFree(right);	return ans; }struct result dodots(char *expr,int at) {	char *mem,*mem2;	float *fptr,f1,f2,f3,f4;	int i;	sptr s;	basisptr b;	modelptr m;	struct result ans,root,memres;	ans.val=ans.valptr=NULL;	ans.type='?';	ans.temp=ans.var=ans.er=0;	fptr=NULL;	mem=expr+at+1;	mem2=NULL;	expr[at]='\0';	root=evalexpr(expr);	if(root.type=='F'||root.type=='?') {      // maybe preceding dot		ResultFree(root);		mem2=strrchr(expr,'.');		if(mem2) {			*mem2='\0';			root=evalexpr(expr);			*mem2='.';			mem2++; }}					// now mem is final member, mem2 is NULL or former member	if(root.er)		ans.er=root.er;	else if(root.type=='?')		ans.er=999;	else if(!root.val)		ans.er=22; 	else if(root.type=='W'&&!strcmp((char*)root.val,"scale")&&!mem2)	{			// scale.mem		if(!strcmp(mem,"xmin"))	ScalePtrs(&((float *) ans.val),&fptr,&fptr,&fptr);		else if(!strcmp(mem,"xmax"))	ScalePtrs(&fptr,&((float *) ans.val),&fptr,&fptr);		else if(!strcmp(mem,"ymin"))	ScalePtrs(&fptr,&fptr,&((float *) ans.val),&fptr);		else if(!strcmp(mem,"ymax"))	ScalePtrs(&fptr,&fptr,&fptr,&((float *) ans.val)); 		else ans.er=23; 		if(!ans.er) { 			ans.type='F'; 			ans.valptr=ans.val; }}	else if(root.type=='S'&&mem2)	{											// S.mem2.F		s=(sptr) root.val;		ans.type='F';		memres=evalexpr(mem);		if(memres.type!='F'||!memres.val)			ans.er=23;		else {			i=*((float *) memres.val)+0.5;			if(i<0) i=0;			else if(i>s->n-1) i=s->n-1; }		ResultFree(memres);		if(ans.er)			ans.type='?';		else if(!strcmp(mem2,"x")) {			ans.temp=1;			ans.val=malloc(sizeof(float));			if(!ans.val) ans.er=1;			else *((float *) ans.val)=s->x[i]; }		else if(!strcmp(mem2,"y")&&!s->cmplx)			ans.val=ans.valptr=(void *) &(s->y[i]);		else if(!strcmp(mem2,"yr")&&s->cmplx)			ans.val=ans.valptr=(void *) &(s->y[2*i]);		else if(!strcmp(mem2,"yi")&&s->cmplx)			ans.val=ans.valptr=(void *) &(s->y[2*i+1]);		else {			ans.type='?';			ans.er=23; }}	else if(root.type=='S')	{													// S.mem		s=(sptr) root.val;		ans.type='C';		if(!strcmp(mem,"name"))			ans.val=(void *) s->name;		else if(!strcmp(mem,"file"))			ans.val=ans.valptr=(void *) s->file;		else if(!strcmp(mem,"desc"))			ans.val=ans.valptr=(void *) s->desc;		else if(!strcmp(mem,"xunit"))			ans.val=ans.valptr=(void *) s->xunit;		else if(!strcmp(mem,"yunit"))			ans.val=ans.valptr=(void *) s->yunit;		else if(!strcmp(mem,"color"))			ans.val=ans.valptr=(void *) s->color;		else if(!strcmp(mem,"n")) {			ans.type='F';			ans.temp=1;			ans.val=malloc(sizeof(float));			if(!ans.val)	{ans.type='?';ans.er=1;}			else *((float *) ans.val)=s->n; }		else if(!strcmp(mem,"cmplx")) {			ans.type='F';			ans.temp=1;			ans.val=malloc(sizeof(float));			if(!ans.val)	{ans.type='?';ans.er=1;}			else *((float *) ans.val)=s->cmplx; }		else if(!strcmp(mem,"xmin")||!strcmp(mem,"xmax")||!strcmp(mem,"ymin")||!strcmp(mem,"ymax"))	{			SpectRange(s,&f1,&f2,&f3,&f4,0);			ans.type='F';			ans.temp=1;			ans.val=malloc(sizeof(float));			if(!ans.val)	{ans.type='?';ans.er=1;}			else if(!strcmp(mem,"xmin")) *((float *) ans.val)=f1;			else if(!strcmp(mem,"xmax")) *((float *) ans.val)=f2;			else if(!strcmp(mem,"ymin")) *((float *) ans.val)=f3;			else *((float *) ans.val)=f4; }		else {			memres=evalexpr(mem);												// S.F			if(memres.type=='F'&&memres.val) {				ans.type='F';				ans.temp=1;				ans.val=malloc(sizeof(float));				if(!ans.val) {ans.type='?';ans.er=1;}				else *((float *) ans.val)=interpolate1(s->x,s->y,s->n,&i,*((float *) memres.val)); }			else {ans.type='?';ans.er=23;}			ResultFree(memres); }}	else if(root.type=='B'&&mem2||root.type=='F'&&root.valptr&&!mem2)	{		// B.mem2.mem or param.mem		if(root.type=='B') {			b=(basisptr) root.val;			i=FindBasisParam(&b,NULL,mem2); }		else {			b=NULL;			i=FindBasisParam2(&b,Model,(float*)root.valptr); }		if(i<0)			ans.er=24;		else if(!strcmp(mem,"eqn")) {			ans.type='C';			ans.val=ans.valptr=(void *) b->eqn[i]; }		else if(!strcmp(mem,"pname"))	{			ans.type='C';			ans.val=ans.valptr=(void *) b->pname[i]; }		else if(!strcmp(mem,"freeze")) {			ans.val=malloc(sizeof(float));			if(!ans.val) ans.er=1;			else {				ans.type='F';				ans.temp=1;				*((float *) ans.val)=b->freeze[i]; }}		else if(!strcmp(mem,"min")) {			ans.type='F';			ans.val=ans.valptr=(void *) &(b->paramlo[i]); }		else if(!strcmp(mem,"max")) {			ans.type='F';			ans.val=ans.valptr=(void *) &(b->paramhi[i]); }		else ans.er=23; }	else if(root.type=='B')	{														// B.mem		b=(basisptr) root.val;		if(!strcmp(mem,"name")) {			ans.type='C';			ans.val=(void *) b->name; }		else if(!strcmp(mem,"proc")) {			ans.type='C';			ans.val=(void *) b->proc; }		else if(!strcmp(mem,"color")) {			ans.type='C';			ans.val=ans.valptr=(void *) b->color; }		else if(!strcmp(mem,"desc")) {			ans.type='C';			ans.val=ans.valptr=(void *) b->desc; }		else if(!strcmp(mem,"model"))	{			ans.type='M';			ans.val=(void *) b->model; }		else if(!strcmp(mem,"n")) {			ans.temp=1;			ans.val=malloc(sizeof(float));			if(!ans.val) ans.er=1;			else {				ans.type='F';				*((float *) ans.val)=b->n; }}		else if(!strcmp(mem,"isspec")) {			ans.temp=1;			ans.val=malloc(sizeof(float));			if(!ans.val) ans.er=1;			else {				ans.type='F';				*((float *) ans.val)=b->isspec; }}		else if(!strcmp(mem,"spec")) {			ans.type='S';			ans.valptr=(void *) &(b->spec);			ans.val=*ans.valptr; }		else {			i=FindBasisParam(&b,NULL,mem);			if(i<0) ans.er=24;			else {				ans.type='F';				ans.val=ans.valptr=(void *) &(b->param[i]); }}}	else if((root.type=='M'||root.type=='W'&&!strcmp((char*)root.val,"model"))&&!mem2) {		if(root.type=='M')																// M.mem or model.mem			m=(modelptr) root.val;		else if(Model)			m=Model;		else ans.er=32;		if(ans.er);		else if((ans.val=SetItem((void *) mem,m->basis))!=NULL)			ans.type='B';		else if(!strcmp(mem,"name")) {			ans.type='C';			ans.val=(void *) m->name; }		else if(!strcmp(mem,"file")) {			ans.type='C';			ans.val=ans.valptr=(void *) m->file; }		else if(!strcmp(mem,"color")) {			ans.type='C';			ans.val=ans.valptr=(void *) m->color; }		else if(!strcmp(mem,"spec")) {			ans.type='S';			ans.valptr=(void *) &(m->spec);			ans.val=*ans.valptr; }		else if(!strcmp(mem,"uncert")) {			ans.type='S';			ans.valptr=(void *) &(m->uncert);			ans.val=*ans.valptr; }		else if(!strcmp(mem,"n"))	{			ans.temp=1;			ans.val=malloc(sizeof(float));			if(!ans.val) ans.er=1;			else {				ans.type='F';				*((float *) ans.val)=m->np; }}		else if(!strcmp(mem,"covar")) {			ans.temp=1;			i=(m->np*m->np+1)*12;			ans.val=calloc(i,sizeof(char));			if(!ans.val) ans.er=1;			else if(m->covar) {				ans.type='C';				sprintM(m->covar,m->np,m->np,"%+1.4e ",(char*) ans.val,i); }			else {				free(ans.val);				ans.er=33; }}		else if(!strcmp(mem,"sigma")) {			ans.type='F';			ans.val=ans.valptr=(void *) &(m->sigma); }		else if(!strcmp(mem,"xmin")) {			ans.type='F';			ans.val=ans.valptr=(void *) &(m->xmin); }		else if(!strcmp(mem,"xmax")) {			ans.type='F';			ans.val=ans.valptr=(void *) &(m->xmax); }		else if(!strcmp(mem,"dx")) {			ans.type='F';			ans.val=ans.valptr=(void *) &(m->dx); }		else			ans.er=23; }	else		ans.er=22;	expr[at]='.';	ResultFree(root);	return ans; }struct result doword(char *cmd,char *expr) {	struct result ans,ag[MAXARG],rlt1;	int prn,qte,i,j,len,arg;	char s[STRCHAR],*cptr;	float num[MAXARG],f1,f2,f3;	sptr s1,s2;	basisptr b;	modelptr m;	arg=prn=qte=0;	s1=s2=NULL;	b=NULL;	m=NULL;	ans.type='S';	ans.temp=1;	ans.val=ans.valptr=NULL;	ans.var=ans.er=0;	for(i=0;i<MAXARG;i++) {ag[i].type=' ';ag[i].er=0;}	len=strlen(expr);	for(i=0,j=0;i<len&&arg<MAXARG-1;i++) {		if(expr[i]=='('&&!qte) prn++;		else if(expr[i]==')'&&!qte)	prn--;		else if(expr[i]=='"') qte=!qte;		else if(expr[i]==','&&!prn&&!qte) {			expr[i]='\0';			ag[arg++]=evalexpr(expr+j);			expr[i]=',';			j=i+1; }}	if(i<len) {		for(i=0;i<arg;i++) ResultFree(ag[i]);		ans.type='?';		ans.er=25;		return ans; }	ag[arg++]=evalexpr(expr+j);	if(!strcmp(cmd,"load")&&!(ans.er=CheckArgs(ag,arg,"Cfff"))) {		f1=(ag[1].type=='F')?*((float*) ag[1].val):1;		f2=(ag[2].type=='F')?*((float*) ag[2].val):2;		f3=(ag[3].type=='F')?*((float*) ag[3].val):0;		ans.er=LoadSpect(&(sptr)ans.val,(char*)ag[0].val,(int)f1,(int)f2,(int)f3); }	else if(!strcmp(cmd,"model")&&!(ans.er=CheckArgs(ag,arg,"s")))		if(ag[0].temp) ans.er=41;		else {			ans.type='M';			s1=(ag[0].type=='S')?(sptr)ag[0].val:NULL;			ans.val=(void*) ModelAlloc(s1);			if(!ans.val) ans.er=1; }	else if(!strcmp(cmd,"loadmodel")&&!(ans.er=CheckArgs(ag,arg,"Cs")))		if(ag[1].type=='S'&&ag[1].temp) ans.er=41;		else {			ans.type='M';			s1=(ag[1].type=='S')?s1=(sptr)ag[1].val:NULL;			ans.er=LoadModel(&(modelptr)ans.val,(char*) ag[0].val,s1); }	else if((!strcmp(cmd,"spec")||!strcmp(cmd,"data"))&&!(ans.er=CheckArgs(ag,arg,"Xfff")))		if(ag[0].type=='S') {			s1=(sptr)ag[0].val;			num[0]=(ag[1].type=='F')?*((float*)ag[1].val):s1->x[0];			num[1]=(ag[2].type=='F')?*((float*)ag[2].val):s1->x[s1->n-1];			num[2]=(ag[3].type=='F')?*((float*)ag[3].val):0;			ans.er=SpectMath2(s1,&(sptr)ans.val,num,3,"copy",""); }		else if(ag[0].type=='B') {			b=(basisptr)ag[0].val;			f1=b->model->xmin;			f2=b->model->xmax;			f3=b->model->dx;			b->model->xmin=(ag[1].type=='F')?*((float*)ag[1].val):f1;			b->model->xmax=(ag[2].type=='F')?*((float*)ag[2].val):f2;			b->model->dx=(ag[3].type=='F')?*((float*)ag[3].val):f3;			ans.er=BasisMath(b,NULL,&(sptr)ans.val,0,"b+k");			b->model->xmin=f1;			b->model->xmax=f2;			b->model->dx=f3; }		else if(ag[0].type=='M') {			m=(modelptr)ag[0].val;			f1=m->xmin;			f2=m->xmax;			f3=m->dx;			m->xmin=(ag[1].type=='F')?*((float*)ag[1].val):f1;			m->xmax=(ag[2].type=='F')?*((float*)ag[2].val):f2;			m->dx=(ag[3].type=='F')?*((float*)ag[3].val):f3;			ans.er=ModelMath(m,NULL,&(sptr)ans.val,0,"m+k");			m->xmin=f1;			m->xmax=f2;			m->dx=f3; }		else if(ag[0].type=='F') {			f1=*((float*)ag[0].val);			num[0]=(ag[1].type=='F')?*((float*)ag[1].val):0;			num[1]=(ag[2].type=='F')?*((float*)ag[2].val):10;			num[2]=(ag[3].type=='F')?*((float*)ag[3].val):0.1;			ans.er=SpectMath2(NULL,&s1,num,3,"new","1");			if(!ans.er) ans.er=SpectMath(s1,NULL,&(sptr)ans.val,"s*k",f1);			SpectFree(s1);			s1=NULL; }		else if(ag[0].type=='C') {			num[0]=(ag[1].type=='F')?*((float*)ag[1].val):0;			num[1]=(ag[2].type=='F')?*((float*)ag[2].val):10;			num[2]=(ag[3].type=='F')?*((float*)ag[3].val):0.1;			rlt1=evalexpr("x");			if(rlt1.er) ans.er=rlt1.er;			else if(rlt1.type=='S'||rlt1.type=='F'||rlt1.type=='B'||rlt1.type=='M') {				sprintf(s,"spec(%s,%f,%f,%f)",(char*) ag[0].val,num[0],num[1],num[2]);				ans=evalexpr(s); }			else if(rlt1.type=='W') {				ans.er=SpectMath2(NULL,&s1,num,3,"new","x");				if(!ans.er) {					strcpy(s1->name,"x");					CreateSpect(s1);					sprintf(s,"spec(%s,%f,%f,%f)",(char*) ag[0].val,num[0],num[1],num[2]);					ans=evalexpr(s);					ClearSpect(s1,1);					s1=NULL; }}			else ans.er=18;			ResultFree(rlt1); }		else ans.er=27;	else if(!strcmp(cmd,"merge")&&!(ans.er=CheckArgs(ag,arg,"SS")))		ans.er=SpectMath((sptr) ag[0].val,(sptr) ag[1].val,&(sptr)ans.val,"merge",0);	else if(!strcmp(cmd,"exp")&&!(ans.er=CheckArgs(ag,arg,"X")))		if(ag[0].type=='F') {			ans.type='F';			ans.val=malloc(sizeof(float));			if(ans.val) *((float *) ans.val)=exp(*((float *) ag[0].val));			else ans.er=1; }		else if(ag[0].type=='S')			ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"exp",0);		else if(ag[0].type=='B')			ans.er=BasisMath((basisptr) ag[0].val,NULL,&(sptr)ans.val,0,"exp b");		else if(ag[0].type=='M')			ans.er=ModelMath((modelptr) ag[0].val,NULL,&(sptr)ans.val,0,"exp m");		else ans.er=27;	else if(!strcmp(cmd,"exp10")&&!(ans.er=CheckArgs(ag,arg,"X")))		if(ag[0].type=='F') {			ans.type='F';			ans.val=malloc(sizeof(float));			if(ans.val) *((float *) ans.val)=pow(10,*((float *) ag[0].val));			else ans.er=1; }		else if(ag[0].type=='S')			ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"10^s",0);		else if(ag[0].type=='B')			ans.er=BasisMath((basisptr) ag[0].val,NULL,&(sptr)ans.val,0,"10^b");		else if(ag[0].type=='M')			ans.er=ModelMath((modelptr) ag[0].val,NULL,&(sptr)ans.val,0,"10^m");		else ans.er=27;	else if(!strcmp(cmd,"ln")&&!(ans.er=CheckArgs(ag,arg,"X")))		if(ag[0].type=='F') {			ans.type='F';			ans.val=malloc(sizeof(float));			if(ans.val) *((float *) ans.val)=log(*((float *) ag[0].val));			else ans.er=1; }		else if(ag[0].type=='S')			ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"ln",0);		else if(ag[0].type=='B')			ans.er=BasisMath((basisptr) ag[0].val,NULL,&(sptr)ans.val,0,"ln b");		else if(ag[0].type=='M')			ans.er=ModelMath((modelptr) ag[0].val,NULL,&(sptr)ans.val,0,"ln m");		else ans.er=27;	else if(!strcmp(cmd,"log")&&!(ans.er=CheckArgs(ag,arg,"X")))		if(ag[0].type=='F') {			ans.type='F';			ans.val=malloc(sizeof(float));			if(ans.val) *((float *) ans.val)=log10(*((float *) ag[0].val));			else ans.er=1; }		else if(ag[0].type=='S')			ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"log",0);		else if(ag[0].type=='B')			ans.er=BasisMath((basisptr) ag[0].val,NULL,&(sptr)ans.val,0,"log b");		else if(ag[0].type=='M')			ans.er=ModelMath((modelptr) ag[0].val,NULL,&(sptr)ans.val,0,"log m");		else ans.er=27;	else if(!strcmp(cmd,"sqrt")&&!(ans.er=CheckArgs(ag,arg,"X")))		if(ag[0].type=='F') {			ans.type='F';			ans.val=malloc(sizeof(float));			if(ans.val) *((float *) ans.val)=sqrt(*((float *) ag[0].val));			else ans.er=1; }		else if(ag[0].type=='S')			ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"sqrt",0);		else if(ag[0].type=='B')			ans.er=BasisMath((basisptr) ag[0].val,NULL,&(sptr)ans.val,0,"sqrt b");		else if(ag[0].type=='M')			ans.er=ModelMath((modelptr) ag[0].val,NULL,&(sptr)ans.val,0,"sqrt m");		else ans.er=27;	else if(!strcmp(cmd,"timesx")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"s*x",0);	else if(!strcmp(cmd,"divx")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"s/x",0);	else if(!strcmp(cmd,"expx")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"exp x",0);	else if(!strcmp(cmd,"exp10x")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"10^x",0);	else if(!strcmp(cmd,"lnx")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"ln x",0);	else if(!strcmp(cmd,"logx")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"log x",0);	else if(!strcmp(cmd,"sqrtx")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"sqrt x",0);	else if(!strcmp(cmd,"shiftx")&&!(ans.er=CheckArgs(ag,arg,"SF")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"x+k",*((float *) ag[1].val));	else if(!strcmp(cmd,"scalex")&&!(ans.er=CheckArgs(ag,arg,"SF")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"x*k",*((float *) ag[1].val));	else if(!strcmp(cmd,"powx")&&!(ans.er=CheckArgs(ag,arg,"SF")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"x^k",*((float *) ag[1].val));	else if(!strcmp(cmd,"deriv1")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"deriv",0);	else if(!strcmp(cmd,"deriv")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"deriv",0);	else if(!strcmp(cmd,"deriv2")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"deriv2",0);	else if(!strcmp(cmd,"xderiv1")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"xderiv1",0);	else if(!strcmp(cmd,"xderiv")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"xderiv1",0);	else if(!strcmp(cmd,"xderiv2")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"xderiv2",0);	else if(!strcmp(cmd,"integral")&&!(ans.er=CheckArgs(ag,arg,"Sf"))) {		s1=(sptr)ag[0].val;		if(s1->x[0]<=0&&s1->x[s1->n-1]>=0) f1=0;		else f1=s1->x[0];		f1=(ag[1].type=='F')?*((float*)ag[1].val):f1;		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"integ",f1); }	else if(!strcmp(cmd,"integrate")&&!(ans.er=CheckArgs(ag,arg,"Sff")))	{		s1=(sptr)ag[0].val;		f1=(ag[1].type=='F')?*((float*)ag[1].val):s1->x[0];		ans.er=SpectMath((sptr) ag[0].val,NULL,&s2,"integ",f1);		f2=(ag[2].type=='F')?*((float*)ag[2].val):s2->x[s2->n-1];		j=-2;		f3=interpolate1(s2->x,s2->y,s2->n,&j,f2);		SpectFree(s2);		s2=NULL;		ans.type='F';		ans.val=(float*) malloc(sizeof(float));		if(!ans.val) ans.er=1;		else *((float*)ans.val)=f3; }	else if(!strcmp(cmd,"smooth")&&!(ans.er=CheckArgs(ag,arg,"SF")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"smooth",*((float *) ag[1].val));	else if(!strcmp(cmd,"complex")&&!(ans.er=CheckArgs(ag,arg,"Ss"))) {		s1=(sptr)ag[0].val;		s2=(ag[1].type=='S')?(sptr)ag[1].val:NULL;		ans.er=SpectMath(s1,s2,&(sptr)ans.val,"complex",0); }	else if(!strcmp(cmd,"real")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"real",0);	else if(!strcmp(cmd,"imag")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"imag",0);	else if(!strcmp(cmd,"fourier")&&!(ans.er=CheckArgs(ag,arg,"Sf"))) {		s1=(sptr) ag[0].val;		f1=(ag[1].type=='F')?*((float*) ag[1].val):FTStartDflt(s1->x,s1->n);		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"fourier",f1); }	else if(!strcmp(cmd,"invfourier")&&!(ans.er=CheckArgs(ag,arg,"Sf"))) {		s1=(sptr) ag[0].val;		f1=(ag[1].type=='F')?*((float*) ag[1].val):FTStartDflt(s1->x,s1->n);		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"invfourier",f1); }	else if(!strcmp(cmd,"ftpower")&&!(ans.er=CheckArgs(ag,arg,"S")))		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"ftpower",0);	else if(!strcmp(cmd,"fft")&&!(ans.er=CheckArgs(ag,arg,"Sf"))) {		s1=(sptr) ag[0].val;		f1=(ag[1].type=='F')?*((float*) ag[1].val):FTStartDflt(s1->x,s1->n);		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"fft",f1); }	else if(!strcmp(cmd,"invfft")&&!(ans.er=CheckArgs(ag,arg,"Sf"))) {		s1=(sptr) ag[0].val;		f1=(ag[1].type=='F')?*((float*) ag[1].val):FTStartDflt(s1->x,s1->n);		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"invfft",f1); }	else if(!strcmp(cmd,"hankel")&&!(ans.er=CheckArgs(ag,arg,"Sf"))) {		f1=(ag[1].type=='F')?*((float*) ag[1].val):10;		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"hankel",f1); }	else if(!strcmp(cmd,"noise")&&!(ans.er=CheckArgs(ag,arg,"Sf"))) {		f1=(ag[1].type=='F')?*((float*) ag[1].val):1;		ans.er=SpectMath((sptr) ag[0].val,NULL,&(sptr)ans.val,"noise",f1); }	else if(!strcmp(cmd,"convolve")&&!(ans.er=CheckArgs(ag,arg,"SS")))		ans.er=SpectMath((sptr)ag[0].val,(sptr)ag[1].val,&(sptr)ans.val,"convolve",0);	else if(!strcmp(cmd,"realft")&&!(ans.er=CheckArgs(ag,arg,"Sf")))	{		ans.er=SpectMath((sptr) ag[0].val,NULL,&s1,"complex",0);		if(ans.er);		else f1=(ag[1].type=='F')?*((float*) ag[1].val):FTStartDflt(s1->x,s1->n);		if(!ans.er) ans.er=SpectMath(s1,NULL,&s2,"fourier",f1);		if(!ans.er) ans.er=SpectMath(s2,NULL,&(sptr)ans.val,"real",0);		SpectFree(s1);		SpectFree(s2);		s1=s2=NULL; }	else if(!strcmp(cmd,"realift")&&!(ans.er=CheckArgs(ag,arg,"Sf")))	{		ans.er=SpectMath((sptr) ag[0].val,NULL,&s1,"complex",0);		if(ans.er);		else f1=(ag[1].type=='F')?*((float*) ag[1].val):FTStartDflt(s1->x,s1->n);		if(!ans.er) ans.er=SpectMath(s1,NULL,&s2,"invfourier",f1);		if(!ans.er) ans.er=SpectMath(s2,NULL,&(sptr)ans.val,"real",0);		SpectFree(s1);		SpectFree(s2);		s1=s2=NULL; }	else if(!strcmp(cmd,"input")&&!(ans.er=CheckArgs(ag,arg,"C"))) {		fprintf(stderr,"%s?",(char *) ag[0].val);		scanf("%s",s);		ans=evalexpr(s); }	else if(!strcmp(cmd,"write")&&!(ans.er=CheckArgs(ag,arg,"C.")))	{		ans.type='F';		ans.val=malloc(sizeof(float));		if(!ans.val) ans.er=1;		s[0]='\0';		for(i=1;i<arg&&!ans.er;i++)			if(ag[i].type=='F'&&ag[i].val)				if(STRCHAR-strlen(s)<10) ans.er=34;				else sprintf(s+strlen(s),"%f ",*((float*)ag[i].val));			else if(ag[i].type=='C'&&ag[i].val)				if(STRCHAR-strlen(s)<strlen((char*)ag[i].val)) ans.er=34;				else sprintf(s+strlen(s),"%s ",(char*)ag[i].val);			else				ans.er=27;		if(!ans.er)			*((float*)ans.val)=SaveString(s,(char*)ag[0].val,1); }	else if(!CheckArgs(ag,arg,"SC.")) {						// cmd(S,C,F,F,É)		for(i=0;i<arg;i++)			num[i]=(ag[i+2].type=='F'&&ag[i+2].val)?*((float*)ag[i+2].val):0;		for(;i<MAXARG;i++) num[i]=0;		ans.er=SpectMath2((sptr) ag[0].val,&(sptr)ans.val,num,arg-2,cmd,(char*)ag[1].val); }	else		if(!ans.er) ans.er=7;			if(ans.er) ans.type='?';	for(i=0;i<arg;i++) ResultFree(ag[i]);	return ans; }struct result evalexpr(char *expr) {	int i,len;	struct result ans;	basisptr b;//	printf("eval: #%s#\n",expr);									// useful line for debugging	ans.type='?';	ans.val=ans.valptr=NULL;	ans.temp=ans.var=ans.er=0;	b=NULL;	len=strlen(expr);	if(!len) {																									/* blank */		ans.type=' ';		return ans; }	if(expr[0]==' ')																						/* pre-space */		return evalexpr(expr+1);	if(expr[len-1]==' ') {																			/* post-space */		expr[len-1]='\0';		ans=evalexpr(expr);		expr[len-1]=' ';		return ans; }	if(isnumber(expr)) {																				/* float */		ans.type='F';		ans.temp=1;		ans.val=malloc(sizeof(float));		if(!ans.val) {ans.type='?';ans.er=1;}		else *((float*)ans.val)=atof(expr);		return ans; }	i=StrrChrPQuote(expr,'"');	if(i==-3) {ans.er=30;return ans;}	if(i==-2) {ans.er=29;return ans;}	i=StrChrPQuote(expr,'=');	if(i>=0) {		expr[i]='\0';		ans=doassign(expr,expr+i+1);		expr[i]='=';		return ans; }	i=StrrChrPQuote(expr,'+');	if(i>=0) return dosymbol(expr,i);	i=StrrChrPQuote(expr,'-');	if(i>=0) return dosymbol(expr,i);	i=StrrChrPQuote(expr,'*');	if(i>=0) return dosymbol(expr,i);	i=StrrChrPQuote(expr,'/');	if(i>=0) return dosymbol(expr,i);	i=StrrChrPQuote(expr,'^');	if(i>=0) return dosymbol(expr,i);	i=StrrChrPQuote(expr,'.');	if(i>=0) return dodots(expr,i);	if(expr[0]=='('&&expr[len-1]==')') {													/* ( ) */		expr[0]=expr[len-1]='\0';		ans=evalexpr(expr+1);		expr[0]='(';		expr[len-1]=')';		return ans; }	if(expr[0]=='"'&&expr[len-1]=='"') {												/* " " */		expr[len-1]='\0';		if(strchr(expr+1,'"')) {			expr[len-1]='"';			ans.er=30;			return ans; }		ans.type='C';		ans.temp=1;		ans.val=(void*) StringCopy(expr+1);		expr[len-1]='"';		if(!ans.val) {ans.type='?';ans.er=1;}		return ans; }	if(expr[len-1]==')') {																			/* word( ) */		i=strchr(expr,'(')-expr;		expr[i]=expr[len-1]='\0';		ans=doword(expr,expr+i+1);		expr[i]='(';		expr[len-1]=')';		return ans; }	if(strpbrk(expr," ()\"")) {ans.er=31;return ans;}			/* spare delimiters */	ans.var=1;	if((ans.val=SetItem((void *) expr,Spectra))!=NULL) ans.type='S';	else if((ans.val=SetItem((void *) expr,Models))!=NULL) ans.type='M';	else if((ans.val=SetItem((void *) expr,Numbers))!=NULL) ans.type='F';	else if((ans.val=SetItem((void *) expr,Strings))!=NULL) ans.type='C';	else if(Model&&(ans.val=SetItem((void *) expr,Model->basis))!=NULL)	{		ans.var=0;		ans.type='B'; }	else if ((i=FindBasisParam(&b,Model,expr))>=0) {		ans.var=0;		ans.type='F';		ans.val=ans.valptr=(void*) &(b->param[i]); }	else {		ans.type='W';		ans.temp=1;		ans.var=0;		ans.val=(void *) StringCopy(expr);		if(!ans.val) {ans.er=1;ans.type='?';}}	return ans; }struct result doassign(char *lhs,char *rhs) {	struct result left,right;	void *copy;	int er;	er=0;//	printf("doassign: '%s' = '%s'\n",lhs,rhs);	left=evalexpr(lhs);	right=evalexpr(rhs);	copy=NULL;	if(right.er) er=right.er;	else if(left.er) er=left.er;	else if(right.type=='?') er=999;	else if(left.type=='?') er=999;	else if(left.type==' ') er=35;	else if(right.type==' ') er=36;	else if(!right.val) er=36;	else if(left.type=='W'&&!left.val) er=35;	else if(left.type=='W'&&!strcmp((char*)left.val,"model"))	{		// W=		if(right.type=='M'&&!right.temp)			Model=(modelptr) right.val;		else if(right.type=='M') er=36;		else er=37; }	else if(left.type=='W'&&!strcmp((char*)left.val,"null"))		er=35;	else if(left.type=='W'&&okname((char*)left.val)) {		if(right.type=='S'&&right.temp)	{			strncpy(((sptr)right.val)->name,(char*)left.val,STRCHAR);			er=CreateSpect((sptr) right.val);			if(!er) right.temp=0; }		else if(right.type=='S') {			er=SpectMath((sptr) right.val,NULL,&(sptr)copy,"copy",0);			if(!er) {				strncpy(((sptr) copy)->name,(char*)left.val,STRCHAR);				er=CreateSpect((sptr) copy); }}		else if(right.type=='F')			er=CreateNumber((char*)left.val,*((float*)right.val));		else if(right.type=='C')			er=CreateString((char*)left.val,(char*)right.val);		else if(right.type=='M'&&right.temp) {			strncpy(((modelptr) right.val)->name,(char*) left.val,STRCHAR);			er=CreateModel((modelptr) right.val);			if(!er) right.temp=0; }		else if(right.type=='M') {			copy=(void*) ModelCopy((modelptr) right.val);			if(copy) {				strncpy(((modelptr) copy)->name,(char*) left.val,STRCHAR);				er=CreateModel((modelptr) copy); }			else er=1; }		else if(right.type=='W'&&!strcmp((char*)right.val,"model")) {			if(!Model) er=32;			else {				copy=(void*) ModelCopy(Model);				if(copy) {					strncpy(((modelptr) copy)->name,(char*) left.val,STRCHAR);					er=CreateModel((modelptr) copy); }}}		else er=36; }	else if(left.type=='W')		er=35;	else if(left.type=='S')	{																	// S=		if(left.temp)	er=35;		else if(left.var&&right.type=='S'&&right.temp) {			strcpy(((sptr) right.val)->name,((sptr) left.val)->name);			er=CreateSpect((sptr) right.val);			if(!er) right.temp=0; }		else if(left.var&&right.type=='S')	{			er=SpectMath((sptr) right.val,NULL,&(sptr)copy,"copy",0);			if(!er)	{				strcpy(((sptr) copy)->name,((sptr) left.val)->name);				er=CreateSpect((sptr) copy); }}		else if(left.var) er=37;		else if(left.valptr&&right.type=='S'&&!right.temp)			*left.valptr=right.val;		else if(left.valptr&&right.type=='S') er=36;		else if(left.valptr&&right.type=='W'&&!strcmp((char*)right.val,"null"))			*left.valptr=NULL;		else er=37; }	else if(left.type=='F')	{																	// F=		if(left.temp)	er=35;		else if(right.type!='F') er=37;		else if(left.var&&left.val)			*((float*) left.val)=*((float *) right.val);		else if(left.var) er=999;		else if(left.valptr)			*((float*) left.valptr)=*((float*) right.val);		else er=35; }	else if(left.type=='C') {																	// C=		if(left.temp)	er=35;		else if(right.type!='C') er=37;		else if(left.var)	{			copy=SetKey(left.val,Strings);			if(copy) er=CreateString((char*)copy,(char*)right.val);			else er=999; }		else if(left.valptr) {			strncpy((char*)left.valptr,(char*)right.val,STRCHAR); }		else er=35; }	else if(left.type=='B') {																	// B=		if(left.temp) er=35;		else if(right.type=='B') {			RemoveBasis((basisptr)left.val);			copy=(void*) AddBasis((basisptr)right.val,NULL,((basisptr)right.val)->spec,((basisptr)left.val)->model);			if(copy)				strcpy((char*)copy,((basisptr)left.val)->name);			else er=1;			BasisFree((basisptr)left.val); }		else er=37; }	else if(left.type=='M')	{																	// M=		if(left.temp) er=35;		else if(left.var&&right.type=='M'&&right.temp)	{			strcpy(((modelptr)right.val)->name,((modelptr)left.val)->name);			er=CreateModel((modelptr) right.val);			if(!er) right.temp=0; }		else if(left.var&&right.type=='M') {			copy=(void *) ModelCopy((modelptr) right.val);			if(copy) {				strcpy(((modelptr) copy)->name,((modelptr) left.val)->name);				er=CreateModel((modelptr) copy); }}		else if(left.var&&right.type=='W'&&!strcmp((char*)right.val,"model")) {			copy=(void *) ModelCopy(Model);			if(copy) {				strcpy(((modelptr) copy)->name,((modelptr) left.val)->name);				er=CreateModel((modelptr) copy); }}		else if(left.var) er=37;		else if(left.valptr&&right.type=='M'&&!right.temp)			*left.valptr=right.val;		else if(left.valptr&&right.type=='M') er=36;		else if(left.valptr&&right.type=='W'&&!strcmp((char*)right.val,"null"))			*left.valptr=NULL;		else er=37; }	else er=999;	ResultFree(left);	if(er) {		ResultFree(right);		right.type='?';		right.er=er; }	else Need2Plot=Need2Update=1;	return right; }int docommand(char *cmd) {	void *k,*x,*k2,*x2;	struct result ans;	int items,i,j,er,ok,lett;	char op[STRCHAR],*lhs;	char str1[STRCHAR];	char *rhs,*cmd2;	float f1,f2,f3,f4,f5,f6;	basisptr base;	struct scell *trace,*trace2;	er=0;	items=sscanf(cmd,"%s",&op);	lett=strlen(op);	ans=evalexpr(cmd+lett);	if(ans.er) return ans.er;	if(!items||!strlen(cmd)||!lett);	else if(!strncmp(op,"help",lett))											/* OP: help */		printf("No.\n");	else if(!strcmp(op,"exit"))														/* OP: exit */		er=-1;	else if(!strcmp(op,"log"))														/* OP: log */		Logcmd=1;	else if(!strcmp(op,"unlog"))													/* OP: unlog */		Logcmd=0;	else if(op[0]=='/');																	/* OP: /	*/	else if(!strcmp(op,"kill")) {													/* OP: kill	*/		if(ans.type=='C'&&ans.val) {			fprintf(stderr,"File %s will be killed from disk.  Are you sure?",(char*)ans.val);			items=scanf("%s",str1);			if(items&&str1[0]=='y') er=KillData((char*)ans.val);			else er=2; }		else er=38; }	else if(!strncmp(op,"exec",lett))	{										/* OP: exec */		if(ans.type=='C'&&ans.val) er=docommand((char*)ans.val);		else er=38; }	else if(!strncmp(op,"eval",lett)) {										/* op: eval */		printf("type: %c, val: %lx, valptr: %lx, temp: %i, var: %i\n",ans.type,ans.val,ans.valptr,ans.temp,ans.var);		if(ans.type=='S') printf("spectrum name: %s\n",((sptr) ans.val)->name);		else if(ans.type=='F') printf("float value: %f\n",*((float *) ans.val));		else if(ans.type=='W') printf("word: %s\n",((char *) ans.val));		else if(ans.type=='C') printf("string: #%s#\n",((char *) ans.val));		else if(ans.type=='B') printf("basis function name: %s\n",((basisptr) ans.val)->name);		else if(ans.type=='M') printf("model name: %s\n",((modelptr) ans.val)->name);		else er=38; }	else if(!strncmp(op,"clear",lett)) {									/* OP: clear */		if(!ans.val) er=39;		else if(!ans.var&&(ans.type=='S'||ans.type=='M'||ans.type=='F'||ans.type=='C'))			er=41;		else if(ans.type=='S') ClearSpect((sptr) ans.val,1);		else if(ans.type=='B') ClearBasis((basisptr) ans.val);		else if(ans.type=='M') ClearModel((modelptr) ans.val,1);		else if(ans.type=='F')			SetDelete(SetKey(ans.val,Numbers),ans.val,Numbers,1,1);		else if(ans.type=='C')			SetDelete(SetKey(ans.val,Strings),ans.val,Strings,1,1);		else if(ans.type=='W')	{			if(!strcmp((char *) ans.val,"model")&&Model) ClearModel(Model,1);			else if(!strcmp((char *) ans.val,"model")) er=32;			else if(!strcmp((char *) ans.val,"spectra"))				for(trace=SetNext(NULL,&k,&x,Spectra);trace;trace=SetNext(trace,&k,&x,Spectra))					ClearSpect((sptr) x,1);			else if(!strcmp((char *) ans.val,"models"))				for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))					ClearModel((modelptr) x,1);			else if(!strcmp((char *) ans.val,"numbers"))				SetNull(Numbers,1,1);			else if(!strcmp((char *) ans.val,"strings"))				SetNull(Strings,1,1);			else if(!strcmp((char *) ans.val,"plot"))				SetNull(Plotlist,0,0);			else if(!strcmp((char *) ans.val,"all"))	{				for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))					ClearModel((modelptr) x,1);				for(trace=SetNext(NULL,&k,&x,Spectra);trace;trace=SetNext(trace,&k,&x,Spectra))					ClearSpect((sptr) x,1);				SetNull(Numbers,1,1);				SetNull(Strings,1,1); }			else er=31; }		else er=38;		Need2Plot=Need2Update=1; }	else if(!strncmp(op,"scale",lett)) {										/* OP: scale */		GetScales(&f1,&f2,&f3,&f4);		i=0;		if(ans.type==' ')			for(trace=SetNext(NULL,&k,&x,Plotlist);trace;trace=SetNext(trace,&k,&x,Plotlist))	{				if(SetMember(k,x,Models))	ModelRange((modelptr) x,&f1,&f2,&f3,&f4,i++);				else if(SetMember(k,x,Spectra))	SpectRange((sptr) x,&f1,&f2,&f3,&f4,i++); }		else if(!ans.val) er=39;		else if(ans.type=='S') SpectRange((sptr) ans.val,&f1,&f2,&f3,&f4,0);		else if(ans.type=='M') ModelRange((modelptr) ans.val,&f1,&f2,&f3,&f4,0);		else if(ans.type=='B') BasisRange((basisptr) ans.val,&f1,&f2,&f3,&f4,0);		else if(ans.type=='F') {			f5=f1-(f2-f1)*(*((float *) ans.val)-1)/2;			f2=f2+(f2-f1)*(*((float *) ans.val)-1)/2;			f1=f5;			f5=f3-(f4-f3)*(*((float *) ans.val)-1)/2;			f4=f4+(f4-f3)*(*((float *) ans.val)-1)/2;			f3=f5; }		else if(ans.type=='W') {			if(!strcmp((char*) ans.val,"model")&&Model) ModelRange(Model,&f1,&f2,&f3,&f4,0);			else if(!strcmp((char*) ans.val,"model")) er=32;			else if(!strcmp((char*) ans.val,"models")&&Model)				for(trace=SetNext(NULL,&k,&x,Plotlist);trace;trace=SetNext(trace,&k,&x,Plotlist)) {					if(SetMember(k,x,Models)) ModelRange((modelptr) x,&f1,&f2,&f3,&f4,i++); }			else if(!strcmp((char*) ans.val,"models")) er=32;			else if(!strcmp((char*) ans.val,"spectra"))				for(trace=SetNext(NULL,&k,&x,Plotlist);trace;trace=SetNext(trace,&k,&x,Plotlist)) {					if(SetMember(k,x,Spectra)) SpectRange((sptr) x,&f1,&f2,&f3,&f4,i++); }			else if(!strcmp((char*) ans.val,"all"))				for(trace=SetNext(NULL,&k,&x,Plotlist);trace;trace=SetNext(trace,&k,&x,Plotlist))	{					if(SetMember(k,x,Models))	ModelRange((modelptr) x,&f1,&f2,&f3,&f4,i++);					else if(SetMember(k,x,Spectra))	SpectRange((sptr) x,&f1,&f2,&f3,&f4,i++); }			else if(!strcmp((char*) ans.val,"y"))				for(trace=SetNext(NULL,&k,&x,Plotlist);trace;trace=SetNext(trace,&k,&x,Plotlist))	{					if(SetMember(k,x,Models))	ModelRange((modelptr) x,&f5,&f6,&f3,&f4,i++);					else if(SetMember(k,x,Spectra))	SpectRange((sptr) x,&f5,&f6,&f3,&f4,i++); }			else if(!strcmp((char*) ans.val,"x"))				for(trace=SetNext(NULL,&k,&x,Plotlist);trace;trace=SetNext(trace,&k,&x,Plotlist))	{					if(SetMember(k,x,Models))	ModelRange((modelptr) x,&f1,&f2,&f5,&f6,i++);					else if(SetMember(k,x,Spectra))	SpectRange((sptr) x,&f1,&f2,&f5,&f6,i++); }			else er=31; }		else er=38;		if(f1==f2) {f1-=0.0001;f2+=0.0001;}		if(f3==f4) {f3-=0.0001;f4+=0.0001;}		SetScales(f1,f2,f3,f4);		Need2Plot=1; }	else if(!strncmp(op,"save",lett)) {										/* OP: save */		if(!ans.val) er=39;		else if(ans.type=='S') SaveSpect((sptr) ans.val);		else if(ans.type=='M') SaveModel((modelptr) ans.val);		else if(ans.type=='W') {			if(!strcmp((char*)ans.val,"model")&&Model) SaveModel(Model);			else if(!strcmp((char*) ans.val,"model")) er=32;			else if(!strcmp((char*) ans.val,"spectra"))				for(trace=SetNext(NULL,&k,&x,Spectra);trace;trace=SetNext(trace,&k,&x,Spectra))					SaveSpect((sptr) x);			else if(!strcmp((char*) ans.val,"models"))				for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))					SaveModel((modelptr) x);			else if(!strcmp((char*) ans.val,"all")) {				for(trace=SetNext(NULL,&k,&x,Spectra);trace;trace=SetNext(trace,&k,&x,Spectra))					SaveSpect((sptr) x);				for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))					SaveModel((modelptr) x); }			else er=31; }		else er=38; }	else if(!strncmp(op,"plot",lett)) {										/* OP: plot */		if(ans.type==' ')			drawplot();		else if(!ans.val) er=39;		else if(ans.type=='W') {			if(!strcmp((char*)ans.val,"model")&&Model)				SetInsert((void *) (Model)->name,(void *) Model,Plotlist);			else if(!strcmp((char*)ans.val,"model"))				er=32;			else if(!strcmp((char *) ans.val,"all")) {				for(trace=SetNext(NULL,&k,&x,Spectra);trace;trace=SetNext(trace,&k,&x,Spectra))					SetInsert(k,x,Plotlist);				for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))					SetInsert(k,x,Plotlist); }			else er=31; }		else if(ans.temp) er=41;		else if(ans.type=='S')			SetInsert((void *) ((sptr) ans.val)->name,ans.val,Plotlist);		else if(ans.type=='B')			SetInsert((void *) ((basisptr) ans.val)->name,ans.val,Plotlist);		else if(ans.type=='M')			SetInsert((void *) ((modelptr) ans.val)->name,ans.val,Plotlist);		else er=38;		Need2Plot=1; }	else if(!strncmp(op,"unplot",lett)) {										/* OP: unplot */		if(!ans.val) er=39;		else if(ans.type=='W') {			if(!strcmp((char*) ans.val,"model")&&Model)				SetDelete((void*) (Model)->name,(void*) Model,Plotlist,0,0);			else if(!strcmp((char *) ans.val,"model"))				er=32;			else if(!strcmp((char *) ans.val,"all"))				SetNull(Plotlist,0,0);			else er=31; }		else if(ans.type=='S'&&!ans.temp)			SetDelete((void *) ((sptr) ans.val)->name,ans.val,Plotlist,0,0);		else if(ans.type=='B'&&!ans.temp)			SetDelete((void *) ((basisptr) ans.val)->name,ans.val,Plotlist,0,0);		else if(ans.type=='M'&&!ans.temp)			SetDelete((void *) ((modelptr) ans.val)->name,ans.val,Plotlist,0,0);		else er=38;		Need2Plot=1; }	else if(!strncmp(op,"print",lett)||!strcmp(op,"?"))	{	/* OP: print, ? */		if(ans.type==' ') printf("\n");		else if(!ans.val) er=39;		else if(ans.type=='S') TypeSpect((sptr) ans.val);		else if(ans.type=='M') TypeModel((modelptr) ans.val);		else if(ans.type=='B') TypeBasis((basisptr) ans.val);		else if(ans.type=='F') printf("%f\n",*((float *) ans.val));		else if(ans.type=='C') printf("%s\n",(char *) ans.val);		else if(ans.type=='W') {			if(!strcmp((char *) ans.val,"spectra"))	{				printf("%i spectra loaded.\n",SetCard(Spectra));				for(trace=SetNext(NULL,&k,&x,Spectra);trace;trace=SetNext(trace,&k,&x,Spectra))					printf("%s\t\t%s\n",(char*) k,((sptr) x)->desc); }			else if(!strcmp((char *) ans.val,"basis")) TypeAllBasis();			else if(!strcmp((char *) ans.val,"models"))	{				printf("%i models defined.\n",SetCard(Models));				for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))					printf("%s for %s\n",(char*) k,((modelptr)x)->spec?((modelptr)x)->spec->name:"NULL"); }			else if(!strcmp((char*) ans.val,"numbers")) {				printf("%i numbers defined.\n",SetCard(Numbers));				for(trace=SetNext(NULL,&k,&x,Numbers);trace;trace=SetNext(trace,&k,&x,Numbers))					printf("%s = %f\n",(char*) k,*((float*) x)); }			else if(!strcmp((char *) ans.val,"strings")) {				printf("%i strings defined.\n",SetCard(Strings));				for(trace=SetNext(NULL,&k,&x,Strings);trace;trace=SetNext(trace,&k,&x,Strings))					printf("%s = %s\n",(char *) k,(char *) x); }			else if(!strcmp((char *) ans.val,"all")) {				printf("%i spectra loaded.\n",SetCard(Spectra));				for(trace=SetNext(NULL,&k,&x,Spectra);trace;trace=SetNext(trace,&k,&x,Spectra))					printf("%s\t\t%s\n",(char *) k,((sptr) x)->desc);				printf("%i models defined.\n",SetCard(Models));				for(trace=SetNext(NULL,&k,&x,Models);trace;trace=SetNext(trace,&k,&x,Models))					printf("%s for %s\n",(char*) k,((modelptr)x)->spec?((modelptr)x)->spec->name:"NULL");				printf("%i numbers defined.\n",SetCard(Numbers));				for(trace=SetNext(NULL,&k,&x,Numbers);trace;trace=SetNext(trace,&k,&x,Numbers))					printf("%s = %f\n",(char*) k,*((float*) x));				printf("%i strings defined.\n",SetCard(Strings));				for(trace=SetNext(NULL,&k,&x,Strings);trace;trace=SetNext(trace,&k,&x,Strings))					printf("%s = %s\n",(char*) k,(char*) x); }			else if(!strcmp((char *) ans.val,"model")&&Model) TypeModel(Model);			else if(!strcmp((char *) ans.val,"model")) er=32;			else if(!strcmp((char *) ans.val,"params")&&Model) {				for(trace=SetNext(NULL,&k,&x,Model->basis);trace;trace=SetNext(trace,&k,&x,Model->basis))					for(i=0;i<((basisptr) x)->n;i++)						printf("%s.%s=%f\n",((basisptr)x)->name,((basisptr)x)->pname[i],((basisptr)x)->param[i]); }			else if(!strcmp((char *) ans.val,"params")) er=32;			else if(!strcmp((char *) ans.val,"plot"))	{				printf("%i things plotted.\n",SetCard(Plotlist));				for(trace=SetNext(NULL,&k,&x,Plotlist);trace;trace=SetNext(trace,&k,&x,Plotlist))					printf("%s\n",(char *) k); }			else if(!strcmp((char *) ans.val,"scale")) {				GetScales(&f1,&f2,&f3,&f4);				printf("Scale limits: %f %f %f %f\n",f1,f2,f3,f4); }			else er=31; }		else er=38; }	else if(!strncmp(op,"add",lett)) {											/* OP: add */		base=NULL;		if(!ans.val) er=39;		else if(!Model) er=32;		else if(ans.type=='B')			base=AddBasis((basisptr)ans.val,((basisptr)ans.val)->proc,((basisptr)ans.val)->spec,Model);		else if(ans.type=='S') {			sprintf(str1,"%s:0",((sptr)ans.val)->name);			if(SetItem((void*)str1,Model->basis)) er=43;			else {				base=AddBasis(NULL,"spectrum",(sptr)ans.val,Model);				if(base) strncpy(base->name,str1,STRCHAR);				else er=1; }}		else if(ans.type=='W') {			base=AddBasis(NULL,(char*)ans.val,NULL,Model);			if(!base) er=40; }		else if(ans.type=='M'&&(modelptr)ans.val!=Model)			for(trace=SetNext(NULL,&k,&x,((modelptr)ans.val)->basis);trace;trace=SetNext(trace,&k,&x,((modelptr)ans.val)->basis))				base=AddBasis((basisptr)x,((basisptr)x)->proc,((basisptr)x)->spec,Model);		else if(ans.type=='M') er=43;		else er=38;		if(!er&&!base) er=1;		if(base&&Model&&Model->covar) {			freeM(Model->covar);			Model->covar=NULL; }		Need2Plot=Need2Update=1; }	else if(!strncmp(op,"remove",lett)) {									/* OP: remove */		if(!Model) er=32;		else if(!ans.val) er=39;		else if(ans.type=='B') ClearBasis((basisptr)ans.val);		else er=38;		if(Model&&Model->covar) {			freeM(Model->covar);			Model->covar=NULL; }		Need2Plot=Need2Update=1; }	else if(!strncmp(op,"tweak",lett)) {											/* OP: tweak */		if(!Model) er=32;		else if(ans.type==' ') er=tweak(Model);		else if(!ans.val) er=39;		else if(ans.type=='M') er=tweak((modelptr)ans.val);		else if(ans.type=='W') {			if(!strcmp((char*)ans.val,"model")) er=tweak(Model);			else er=31; }		else er=38;		Need2Plot=Need2Update=1; }	else if(!strncmp(op,"mouse",lett)) {											/* OP: mouse */		mouse(); }	else if(!strncmp(op,"fit",lett)) {												/* OP: fit */		if(!Model) er=32;		else if(ans.type==' ')			er=LMFit(Model);		else if(!ans.val) er=39;		else if(ans.type=='M')			er=LMFit((modelptr)ans.val);		else if(ans.type=='W'&&!strcmp((char*)ans.val,"model"))			er=LMFit(Model);		else if(ans.type=='W'&&!strcmp((char*)ans.val,"linear"))			er=LinearFit(Model);		else if(ans.type=='W'&&!strcmp((char*)ans.val,"random"))			er=RandomFit(Model);		else if(ans.type=='W'&&!strcmp((char*)ans.val,"LM"))			er=LMFit(Model);		else if(ans.type=='W'&&!strcmp((char*)ans.val,"all"))			er=RandMultiFit(Models);		else er=38;		Need2Plot=Need2Update=1; }	else if(!strncmp(op,"unfit",lett)) {												/* OP: unfit */		if(!Model) er=32;		else if(ans.type==' ')			unfit(Model);		else if(!ans.val) er=39;		else if(ans.type=='M')			unfit((modelptr)ans.val);		else if(ans.type=='W'&&!strcmp((char*)ans.val,"model"))			unfit(Model);		else er=38;		Need2Plot=Need2Update=1; }	else if(!strncmp(op,"fix",lett)||!strncmp(op,"free",lett))	{	/* OP: fix/free */		j=strncmp(op,"fix",lett)?0:1;		if(!ans.val) er=39;		if(ans.type=='B') {			base=(basisptr) ans.val;			for(i=0;i<base->n;i++) base->freeze[i]=j; }		else if(ans.type=='M') {			for(trace=SetNext(NULL,&k,&x,((modelptr)ans.val)->basis);trace;trace=SetNext(trace,&k,&x,((modelptr)ans.val)->basis))				for(i=0;i<((basisptr)x)->n;i++)	((basisptr)x)->freeze[i]=j; }		else if(ans.type=='W'&&!strcmp((char*)ans.val,"model")&&Model) {			for(trace=SetNext(NULL,&k,&x,Model->basis);trace;trace=SetNext(trace,&k,&x,Model->basis))				for(i=0;i<((basisptr) x)->n;i++) ((basisptr) x)->freeze[i]=j; }		else if(ans.type=='W'&&(!strcmp((char*)ans.val,"models")||!strcmp((char*)ans.val,"all"))) {			for(trace2=SetNext(NULL,&k2,&x2,Models);trace2;trace2=SetNext(trace2,&k2,&x2,Models))				for(trace=SetNext(NULL,&k,&x,((modelptr)x2)->basis);trace;trace=SetNext(trace,&k,&x,((modelptr)x2)->basis))					for(i=0;i<((basisptr)x)->n;i++)						((basisptr)x)->freeze[i]=j; }		else if(ans.type=='F'&&ans.valptr) {			ok=1;			for(trace2=SetNext(NULL,&k2,&x2,Models);trace2&&ok;trace2=SetNext(trace2,&k2,&x2,Models))				for(trace=SetNext(NULL,&k,&x,((modelptr)x2)->basis);trace&&ok;trace=SetNext(trace,&k,&x,((modelptr)x2)->basis))					for(i=0;i<((basisptr)x)->n&&ok;i++) {						base=(basisptr)x;						if(&(base->param[i])==(float*)ans.valptr) {							base->freeze[i]=j;							ok=0; }}			if(ok) er=24; }		else er=38;		Need2Plot=Need2Update=1; }	else er=31;	ResultFree(ans);	return er; }int doline(char *cmd) {	int er;	char *cmd2,*rhs;//	printf("doline: '%s'\n",cmd);	cmd2=StrChrQuote(cmd,';');	if(cmd2) {		*cmd2++='\0';		er=doline(cmd);		if(!er) er=doline(cmd2);		*(--cmd2)=';';		return er; }	rhs=strchr(cmd,'=');	cmd2=strnword(cmd,2);	if(!rhs||cmd2&&rhs>cmd2) return docommand(cmd);	*rhs++='\0';	er=(doassign(cmd,rhs)).er;	*(--rhs)='=';	return er; }/* main segment */void debug() {	return; }int main() {	int er;	char cmd[256];	SiouxWindow(0.1,0.1,70,50,0);	printf("Welcome to SpectFit 2.0\n");	InitPlot();	MakeWindow(0.5,0.95,0.1,0.95);	EndPlot();	Model=NULL;	Logcmd=1;	Need2Plot=Need2Update=1;	Spectra=SetAlloc(&StringCmp,NULL);	Plotlist=SetAlloc(&StringCmp,NULL);	Models=SetAlloc(&StringCmp,NULL);	Numbers=SetAlloc(&StringCmp,&PtrCmp);	Strings=SetAlloc(&StringCmp,&PtrCmp);	setupbasis();	debug();	printf("Ready\n");		er=0;	while(er!=-1)	{		er=Need2Update?UpdateModels():0;		if(er>0) displayerr(er);		if(Need2Plot) drawplot();		printf(">");		gets(cmd);		if(Logcmd) SaveString(cmd,"SFlog",1);		er=doline(cmd);		if(er>0) displayerr(er); }			docommand("clear all");	SetFree(Spectra,0,0);	SetFree(Plotlist,0,0);	SetFree(Models,0,0);	SetFree(Numbers,0,0);	SetFree(Strings,0,0);	endbasis();	printf("Bye.\n\n");	printf("Press command-q to quit.\n");	return 0; }