
/*
	SMParser
	Just use it
	
	(c) 1993 Michael Friedel
	Disclaimer: This program is not intended to do anything useful. 
	I am sure there are at least 99 bugs in this version. Use it as an exmaple 
	for something useful, but don't try to make something useful out of it.
	
*/

#include <stdio.h>
#include <stdlib.h>

#include <smii/smlib.h>
#include <smii/smtuner.h>

#include "smparser.h"
#ifdef SCO
#include <sys/time.h>
#endif
#define NXSetRect(rect,x,y,w,h) (	(rect)->origin.x = (x);\
									(rect)->origin.y = (y);\
									(rect)->size.width = (w);\
									(rect)->size.height = (h);)
static NXRect theWindowFrame[4],theZoomFrame[4];
static short nRed[4],nGreen[4],nBlue[4];
static int	 numsm,swdt,shgt;
static short sms[4],sm;
static char logging=NO;
static FILE *fpLog;
static SMTVControl smtv[4];
static int prog[4];
static int freq[4] = {0,0,0,0};
static SMAFCTable* afcTables[4] = {0,0,0,0};

/* Commands*/

static char tksname[NUMTOKENS][4] = 
	{
		"gai","win","vfr","inp","fie","boa","cli","pll","xof","yof",
		"xxx","xxx","lum","chr","mov","siz","vid","qui","ope","zoo",
		"sys","rem","sta","sto","mix","inf","set","sat","bri","con",
		"gra","sha","pre","sle","pat","cle","pan","run","rea","clo",
		"dis","aud","vol","fad","bal","bas","tre","ain","cll","log",
		"ask","hel","say","hue","yre","ydi","rtv","inc","dec","afc",
		"sea"
	};

static char *tkshelp[NUMTOKENS+1] =
	{
		"No such command try Help",
		"Gain <red|green|blue> <0-63>",
		"Window <x> <y> <width> <height>",
		"Vframe <x> <y> <width> <height>",
		"Input <black|red|yellow|svhs>",
		"Fields <odd|even|both>",
		"Board <boardnum>",
		"Clipping <on|off>",
		"PLL <0-1024>",
		"Xoff <0-256>",
		"Yoff <0-256>",
		"Not implemented",
		"Not implemented",
		"Lumaintensity <-50 - +50>",
		"Chromainstensity <-50 - +50>",
		"Move <x> <y> ",
		"Size <width> <height>",
		"Video <on|off>",
		"Quit",
		"Open <0-3>",
		"Zoom <x> <y> <width> <height>",
		"System <pal|secam|ntsc>",
		"Remove <clipnum>",
		"Start",
		"Stop",
		"Mixer <on|off>",
		"Info",
		"Setclip <x> <y> <width> <height><num> ",
		"Saturation <0-63>",
		"Brightness <0-63>",
		"Contrast <0-63>",
		"Not supported",
		"Sharpness <0-63>",
		"Prefilter <on|off>",
		"Sleep <seconds>",
		"Pattern <0-8192>",
		"Clearclips",
		"Pan <x> <y>",
		"Run <filename>",
		"Readimage <filename>",
		"Close <0-3>",
		"Displayimage <filename>",
		"Audio <on|off>",
		"Volume <0-100>",
		"Fader <-50 - +50>",
		"Balance <-50 - +50>",
		"Bass <-50 - +50>",
		"Treble <-50 - +50>",
		"Audioinput <0-2>",
		"Cllist",
		"Log <filename>",
		"Ask <question>",
		"Help [<command>]",
		"Say <Text>",
		"Hue <0-255>",
		"YReadImage <filename>",
		"YDisplay <filename>",
		"RTV [<filename>]",
		"Inc ",
		"Dec ",
		"Afc [<filename>]",
		"Search"
	};

main(int argc, char**argv)
{
	char tmp[128],c,w = 0;
	Token tokens[16],lasttokens[16];
	int numtokens,i,lOff,sWidth,numlasttokens=0,error=0;
	
	sm =-1;
	
	if(argc > 2)
	{
		swdt = atoi(argv[1]);
		shgt = atoi(argv[2]);
	}
	else
	{
		swdt = 1024;
		shgt = 768;
	}
	/* Find out how many sms are there*/
	numsm = smInit(0x380, (short) swdt, (short) shgt);
	
	/* Wait for keypress*/
	/* Parser prompt*/
	printf("SM(%d):",sm);
	while(fgets(tmp,128,stdin))
	{
		/* Check for return, then repeat last command*/
		if(*tmp == '\n')
		{
			bcopy(lasttokens,tokens,sizeof(Token)*numlasttokens);
			numtokens = numlasttokens;
		}
		else
		{
			/* Parse into tokens*/
			tokenize(tmp,tokens,&numtokens);
			numlasttokens = numtokens;
			bcopy(tokens,lasttokens,sizeof(Token)*numlasttokens);
		}
		action(numtokens,tokens);
		
		printf("SM(%d):",sm);
	}
}

void action(int numtokens, Token *tokens)
{
	NXRect aRect,bRect;
	BOOL bVal;
	float fVal;
	SMClip theClip;
	char tmp[128];
	Token filetokens[16];
	int numfiletokens,i,error;
	FILE *fp = 0;
	
	if(numtokens && tokens[0].type == COMMAND)
	{
		fVal = 0.0;
		switch(tokens[0].val.t)
		{
			case GAIN:
				i = 1;
				smGetRGB(sm,&nRed[sm],&nGreen[sm],&nBlue[sm]);
				while(i+2 <= numtokens)
				{
					if(tokens[i].type & NARG)
					{
						/* Find out which*/
						switch(tokens[i].val.s[0])
						{
							case 'r':
							case 'R':
								if(getfval(&tokens[i+1],numtokens-i-1,&fVal))
								{
									nRed[sm] = (short) fVal;
								}
								break;
							case 'g':
							case 'G':
								if(getfval(&tokens[i+1],numtokens-i-1,&fVal))
								{
									nGreen[sm] = (short) fVal;;
								}
								break;
							case 'b':
							case 'B':
								if(getfval(&tokens[i+1],numtokens-i-1,&fVal))
								{
									nBlue[sm] = (short) fVal;
								}
								break;
						}
					}
					i += 2;
				}
				if(logging)
				{
					fprintf(fpLog,"SetRGB[%d]: Red = %d, Green = %d, Blue = %d\n",
						sm,nRed[sm],nGreen[sm],nBlue[sm]);
				}
				smSetRGB(sm,nRed[sm],nGreen[sm],nBlue[sm]);
				break;
			case WFRAME:
				aRect = theWindowFrame[sm];
				if(numtokens > 4 && getframe(&tokens[1],numtokens-1,&aRect))
				{
					theWindowFrame[sm] = aRect;
					smSetWindowFrame(sm, (short) aRect.origin.x,
						(short) (shgt - (short) (aRect.size.height+aRect.origin.y)),
						(short) aRect.size.width,
						(short) aRect.size.height);
					if(logging)
					{
						fprintf(fpLog,"SetWindowframe[%d]: (%3.f,%3.f) (%3.f,%3.f)\n",
							sm, theWindowFrame[sm].origin.x, theWindowFrame[sm].origin.y,
							theWindowFrame[sm].size.width, theWindowFrame[sm].size.height);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case MOVE:
				aRect.origin = theWindowFrame[sm].origin;
				if(numtokens > 1 && getpos(&tokens[1],numtokens-1,&aRect.origin))
				{
					theWindowFrame[sm].origin = aRect.origin;
					smSetWindowFrame(sm, (short) theWindowFrame[sm].origin.x,
						(short) (shgt - (short) (theWindowFrame[sm].size.height+theWindowFrame[sm].origin.y)),
						(short) theWindowFrame[sm].size.width,
						(short) theWindowFrame[sm].size.height);
					if(logging)
					{
						fprintf(fpLog,"MoveWindowframe[%d]: to (%3.f,%3.f) (%3.f,%3.f)\n",
							sm, theWindowFrame[sm].origin.x, theWindowFrame[sm].origin.y,
							theWindowFrame[sm].size.width, theWindowFrame[sm].size.height);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case SIZE:
				aRect.size = theWindowFrame[sm].size;
				if(numtokens > 1 && getsize(&tokens[1],numtokens-1,&aRect.size))
				{
					theWindowFrame[sm].size = aRect.size;
					smSetWindowFrame(sm, (short) theWindowFrame[sm].origin.x,
						(short) (shgt - (short) (theWindowFrame[sm].size.height+theWindowFrame[sm].origin.y)),
						(short) theWindowFrame[sm].size.width,
						(short) theWindowFrame[sm].size.height);

					if(logging)
					{
						fprintf(fpLog,"SizeWindowframe[%d]: to (%d,%d) (%d,%d)\n",
							sm, theWindowFrame[sm].origin.x, theWindowFrame[sm].origin.y,
							theWindowFrame[sm].size.width, theWindowFrame[sm].size.height);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case ZOOM:
				aRect = theZoomFrame[sm];
				if(numtokens > 4 && getframe(&tokens[1],numtokens-1,&aRect))
				{
					theZoomFrame[sm] = aRect;
					smSetZoomFrame(sm, (short) aRect.origin.x,
						(short) (100 - (short) (aRect.size.height+aRect.origin.y)),
						(short) (aRect.origin.x + aRect.size.width),
						(short) (100 - (short) aRect.origin.y));
					if(logging)
					{
						fprintf(fpLog,"SetZoomframe[%d]: (%d,%d) (%d,%d)\n",
							sm, theZoomFrame[sm].origin.x, theZoomFrame[sm].origin.y,
							theZoomFrame[sm].size.width, theZoomFrame[sm].size.height);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case PAN:
				aRect.origin = theZoomFrame[sm].origin;
				if(numtokens > 2 && getpos(&tokens[1],numtokens-1,&aRect.origin))
				{
					theZoomFrame[sm].origin = aRect.origin;
					smSetZoomFrame(sm, (short) aRect.origin.x,
						(short) (100 - (short) (aRect.size.height+aRect.origin.y)),
						(short) (aRect.origin.x + aRect.size.width),
						(short) (100 - (short) aRect.origin.y));
					if(logging)
					{
						fprintf(fpLog,"MoveZoomframe[%d]: to (%d,%d) (%d,%d)\n",
							sm, theZoomFrame[sm].origin.x, theZoomFrame[sm].origin.y,
							theZoomFrame[sm].size.width, theZoomFrame[sm].size.height);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case VFRAME:
				if(numtokens > 4 && getframe(&tokens[1],numtokens-1,&aRect))
				{
					smSetVideoFrame(sm, (short) aRect.origin.x,
						(short) aRect.origin.y,
						(short) (aRect.origin.x + aRect.size.width),
						(short) (aRect.size.height+aRect.origin.y));
					if(logging)
					{
						printf("SetVideoFrame:[%d] to (%d,%d),(%d,%d)\n",
						aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case INPUT:
				if(numtokens > 1)
				{
					if(tokens[1].type & IARG)
					{
						smSetInput(sm,(short) tokens[1].val.i);
					}
					else if(tokens[1].type & NARG)
					{
						switch(tokens[1].val.s[0])
						{
							case 'b':
							case 'B':
								smSetInput(sm,SM_INPUT_BLACK);
								break;
							case 'r':
							case 'R':
								smSetInput(sm,SM_INPUT_RED);
								break;
							case 'y':
							case 'Y':
								smSetInput(sm,SM_INPUT_YELLOW);
								break;
							case 's':
							case 'S':
								smSetInput(sm,SM_INPUT_SVHS);
								break;
						}
					}
					if(logging)
					{
						fprintf(fpLog,"SetInput[%d]: to %d\n",
							sm, smGetInput(sm));
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case OPEN:
				if(numtokens > 1 )
				{
					if((tokens[1].type & IARG)  && (tokens[1].val.i < numsm))
					{
						smOpen((short) tokens[1].val.i);
						sms[tokens[1].val.i] = tokens[1].val.i;
						/* Check if Tuner is present */
						if(smIsTunerConnected(tokens[1].val.i))
						{
							/* Initialize */
							smInitTuner(tokens[1].val.i,&smtv[tokens[1].val.i]);
						}
						prog[tokens[1].val.i] = 0;
					}
					if(logging)
					{
						fprintf(fpLog,"OpenSM: %d\n",tokens[1].val.i);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;					
			case CLOSE:
				if(numtokens > 1 )
				{
					if((tokens[1].type & IARG)  && (tokens[1].val.i < numsm))
					{
						smClose((short) tokens[1].val.i);
						sms[tokens[1].val.i] = -1;
					}
					if(logging)
					{
						fprintf(fpLog,"CloseSM: %d\n",tokens[1].val.i);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;					
			case FIELDS:
				if(numtokens > 1 )
				{
					if(tokens[1].type & IARG)
					{
						smSetInputFields(sm, (short)  tokens[1].val.i);
						if(logging)
						{
							fprintf(fpLog,"SetInputFields:[%d] %d\n",sm,tokens[1].val.i);
						}
					}
					else if(tokens[1].type & NARG)
					{
						switch(tokens[1].val.s[0])
						{
							case 'o':
							case 'O':
								smSetInputFields(sm,SM_FIELD_ODD);
								break;
							case 'e':
							case 'E':
								smSetInputFields(sm,SM_FIELD_EVEN);
								break;
							case 'b':
							case 'B':
								smSetInputFields(sm,SM_FIELD_BOTH);
								break;
						}
						if(logging)
						{
							fprintf(fpLog,"SetInputFields:[%d] %d\n",sm,smGetInputFields(sm));
						}
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case SM:
				if(numtokens > 1)
				{
					if((tokens[1].type & IARG) && (numsm > tokens[1].val.i))
					{
						sm = sms[tokens[1].val.i];
					}
					if(logging)
					{
						fprintf(fpLog,"SelectSM: %d\n",sm);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case HUE:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetHue(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetHue:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case LUMA:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetLumaIntensity(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetLumaIntensity:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case CHROMA:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetChromaIntensity(sm, (short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetChromaIntensity:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case ONOFF:
				if(numtokens > 1 && getonoff(&tokens[1],numtokens-1,&bVal))
				{
					smSetVideo(sm, bVal);
					if(logging)
					{
						fprintf(fpLog,"SetVideo:[%d] %d\n",sm,bVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case QUIT:
				/* Free all SMs*/
				if(logging)
				{
					fprintf(fpLog,"Quit:[%d] \n",sm);
				}
				for(i=0;i<numsm;i++)
				{
					smClose(sms[i]);
				}
				if(logging)
				{
					fclose(fpLog);
					logging = NO;
				}
				exit(0);
			case START:
				smSetLive(sm, YES);
				if(logging)
				{
					fprintf(fpLog,"Start:[%d]\n",sm);
				}
				break;
			case STOP:
				smSetLive(sm, NO);
				if(logging)
				{
					fprintf(fpLog,"Stop:[%d]\n",sm);
				}
				break;
			case MIXER:
				if(numtokens > 1 && getonoff(&tokens[1],numtokens-1,&bVal))
				{
					smSetMixer(sm,bVal);
					if(logging)
					{
						fprintf(fpLog,"Mixer:[%d] %d\n",sm,bVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case PREFILTER:
				if(numtokens > 1 && getonoff(&tokens[1],numtokens-1,&bVal))
				{
					smSetPreFilter(sm, bVal);
					if(logging)
					{
						fprintf(fpLog,"SetPreFilter:[%d] %d\n",sm,bVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case INFO:
				/* Test Get Functions*/
				printInfo(stdout);
				if(logging)
				{
					printInfo(fpLog);
				}
				break;
			case BRIGHTNESS:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetBrightness(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetBrightness:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case SHARPNESS:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetSharpness(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetSharpness:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case CONTRAST:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetContrast(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetContrast:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case SATURATION:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetSaturation(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetSaturation:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case SYSTEM:
				if(numtokens > 1)
				{
					/* Get system*/
					if(tokens[1].type & IARG)
					{
						tokens[1].type = NARG;
						if(tokens[1].val.i == SM_SYSTEM_NTSC)
						{
							tokens[1].val.s[0] = 'n';
						}
						else if(tokens[1].val.i == SM_SYSTEM_PAL)
						{
							tokens[1].val.s[0] = 'p';
						}
						else if(tokens[1].val.i == SM_SYSTEM_SECAM)
						{
							tokens[1].val.s[0] = 's';
						}
					}
					if(tokens[1].type & NARG)
					{
						switch(tokens[1].val.s[0])
						{
							case 'n':
							case 'N':
								smSetSystem(sm, SM_SYSTEM_NTSC);
								if(logging)
								{
									fprintf(fpLog,"SetSystem:[%d] NTSC\n",sm);
								}
								break;
							case 'p':
							case 'P':
								smSetSystem(sm, SM_SYSTEM_PAL);
								if(logging)
								{
									fprintf(fpLog,"SetSystem:[%d] PAL\n",sm);
								}
								break;
							case 's':
							case 'S':
								smSetSystem(sm, SM_SYSTEM_SECAM);
								if(logging)
								{
									fprintf(fpLog,"SetSystem:[%d] SECAM\n",sm);
								}
								break;
						}
					}
				} 
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case PLL:
				fVal = smGetPll(sm);
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetPll(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetPLL:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case XOFF:
				fVal = smGetXofs(sm);
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetXofs(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetXOFF:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case YOFF:
				fVal = smGetYofs(sm);
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetYofs(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetYOFF:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case PATTERN:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smPatternFill(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetPattern:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case WRITEIMAGE:
				if(numtokens > 1 && (tokens[1].type & NARG) )
				{					
					#if defined(SCO) || defined(LINUX)
						FILE *fp;
						unsigned char *imagedata,buf[64];
						int imagesize,width,height;
						if((fp = fopen(tokens[1].val.s,"r")))
						{
							if(!fread(buf,64,1,fp))
							{
								fclose(fp);
								break;
							}
							width	=	(buf[10]+(buf[11]<<8));
							height	=	(buf[12]+(buf[13]<<8));
							
							if(buf[14] == 6)
							{
								imagesize = width*height*2+64;
							}
							else if(buf[14] == 1)
							{
								imagesize = width*height+64;
							}
							else
							{
								printf("Image not in mode 6 or 1\n");
								fclose(fp);
								break;
							}
							imagedata = malloc(imagesize);
							bcopy(buf,imagedata,64);
							if(!fread(imagedata+64, imagesize-64, 1, fp))
							{
								fclose(fp);
								break;
							}
							fclose(fp);
							smWriteImage(sm,imagedata, imagesize);
							free(imagedata);
							if(logging)
							{
								fprintf(fpLog,"DisplayImage:[%d] %s of size (%d,%d)\n",sm,tokens[1].val.s,
									width,height);
							}
						}
						else
						{
							printf("\n\tERROR: Couldn't open image %s\n",tokens[1].val.s);
							if(logging)
							{
								fprintf(fpLog,"ERROR: Couldn't open image %s\n",tokens[1].val.s);
							}
						}
					#else
						printf("Displaying an Image is not supported on this platform\n");
						if(logging)
						{
							fprintf(fpLog,"Displaying an Image is not supported on this platform\n");
						}
					#endif
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case WRITEYIMAGE:
				if(numtokens > 1 && (tokens[1].type & NARG) )
				{					
					#if defined(SCO) || defined(LINUX)
						FILE *fp;
						unsigned char *imagedata,buf[64];
						int imagesize,width,height;
						if((fp = fopen(tokens[1].val.s,"r")))
						{
							if(!fread(buf,64,1,fp))
							{
								fclose(fp);
								break;
							}
							width	=	(buf[10]+(buf[11]<<8));
							height	=	(buf[12]+(buf[13]<<8));
							imagesize = width*height+64;
							imagedata = malloc(imagesize);
							bcopy(buf,imagedata,64);
							if(!fread(imagedata+64, imagesize-64, 1, fp))
							{
								fclose(fp);
								break;
							}
							fclose(fp);
							smWriteYImage(sm,imagedata, imagesize);
							free(imagedata);
							if(logging)
							{
								fprintf(fpLog,"DisplayImage:[%d] %s of size (%d,%d)\n",sm,tokens[1].val.s,
									width,height);
							}
						}
						else
						{
							printf("\n\tERROR: Couldn't open image %s\n",tokens[1].val.s);
							if(logging)
							{
								fprintf(fpLog,"ERROR: Couldn't open image %s\n",tokens[1].val.s);
							}
						}
					#else
						printf("Displaying an Image is not supported on this platform\n");
						if(logging)
						{
							fprintf(fpLog,"Displaying an Image is not supported on this platform\n");
						}
					#endif
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case READIMAGE:
				if(numtokens > 1 && (tokens[1].type & NARG) )
				{
					#ifdef ONSITE
						smReadImage(sm,tokens[1].val.s);
					#endif
					
					#if defined(SCO) || defined(LINUX)
						FILE *fp;
						char *imagedata;
						int imagesize;
						if((fp = fopen(tokens[1].val.s,"w")))
						{
							imagedata = malloc(1024*1024);
							if(imagedata)
							{
								smReadImage(sm,imagedata,&imagesize);
							}
							if(imagesize < 1024*1024)
							{
								fwrite(imagedata,imagesize,1,fp);
							}
							fclose(fp);
							if(logging)
							{
								fprintf(fpLog,"SavedImage:[%d] %s \n",sm,tokens[1].val.s);
							}
							free(imagedata);
						}
						else
						{
							printf("\n\tERROR: Couldn't save image %s\n",tokens[1].val.s);
							if(logging)
							{
								fprintf(fpLog,"ERROR: Couldn't save image %s\n",tokens[1].val.s);
							}
						}
					#else
						printf("Saving an Image is not supported on this platform\n");
						if(logging)
						{
							fprintf(fpLog,"Saving an Image is not supported on this platform\n");
						}
					#endif
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case READYIMAGE:
				if(numtokens > 1 && (tokens[1].type & NARG) )
				{
					#ifdef ONSITE
						smReadYImage(sm,tokens[1].val.s);
					#endif
					
					#if defined(SCO) || defined(LINUX)
						FILE *fp;
						char *imagedata;
						int imagesize;
						if((fp = fopen(tokens[1].val.s,"w")))
						{
							imagedata = malloc(1024*1024);
							if(imagedata)
							{
								smReadYImage(sm,imagedata,&imagesize);
							}
							if(imagesize < 1024*1024)
							{
								fwrite(imagedata,imagesize,1,fp);
							}
							fclose(fp);
							if(logging)
							{
								fprintf(fpLog,"SavedImage:[%d] %s \n",sm,tokens[1].val.s);
							}
							free(imagedata);
						}
						else
						{
							printf("\n\tERROR: Couldn't save image %s\n",tokens[1].val.s);
							if(logging)
							{
								fprintf(fpLog,"ERROR: Couldn't save image %s\n",tokens[1].val.s);
							}
						}
					#else
						printf("Saving an Image is not supported on this platform\n");
						if(logging)
						{
							fprintf(fpLog,"Saving an Image is not supported on this platform\n");
						}
					#endif
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case SETCLIP:
				if(numtokens > 5 && getframe(&tokens[1],numtokens-1,&aRect) &&
					getfval(&tokens[5],numtokens-5,&fVal))
				{
					theClip[CLIP_LEFT] = (short) aRect.origin.x;
					theClip[CLIP_TOP] = (short) aRect.origin.y;
					theClip[CLIP_RIGHT] = (short) (aRect.origin.x + aRect.size.width);
					theClip[CLIP_BOTTOM] = (short) (aRect.size.height + aRect.origin.y);
					theClip[CLIP_NUM] = (short) fVal;
					smSetClip(sm,theClip);
					if(logging)
					{
						fprintf(fpLog,"SetClip:[%d] TopLeft:(%d,%d) BottomRight:(%d,%d) Num:%d\n",sm,
							theClip[CLIP_TOP],theClip[CLIP_LEFT],theClip[CLIP_BOTTOM],
							theClip[CLIP_RIGHT],theClip[CLIP_NUM]);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case SETCLIPLIST:
				{
					SMClip	clipList[4];
					
					for(i=0;i<4;i++)
					{
						clipList[i][CLIP_LEFT] = (swdt / 4) * i;
						clipList[i][CLIP_TOP] = ((shgt / 4) * i);
						clipList[i][CLIP_RIGHT] = (swdt / 4) * (i+1);
						clipList[i][CLIP_BOTTOM] = ((shgt / 4) * (i+1));
						clipList[i][CLIP_NUM] = i;
						clipList[i][CLIP_STATE] = SM_SET_CLIP;
					}
					smSetClipList(sm, clipList,4);
				}
				break;
			case REMOVECLIP:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smRemoveClip(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"RemoveClip:[%d] Num:%3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case CLEARCLIPS:
				smClearClips(sm);
				if(logging)
				{
					fprintf(fpLog,"Cleared All Clips:[%d] \n",sm);
				}
				break;
			case RUN:
				if(numtokens > 1)
				{
					if((fp = fopen(tokens[1].val.s,"r")))
					{ 
						if(logging)
						{
							fprintf(fpLog,"Executing commands from file:[%d] %s\n",sm,tokens[1].val.s);
						}
						while(fgets(tmp,128,fp))
						{
							/* Parse into tokens*/
							tokenize(tmp,filetokens,&numfiletokens);
							if(numfiletokens && (filetokens[0].type == COMMAND))
							{
								action(numfiletokens,filetokens);
							}
						}
						fclose(fp);
					}
					else
					{
						printf("\n\tERROR: Can't open file %s\n",tokens[1].val.s);
						if(logging)
						{
							fprintf(fpLog,"ERROR: Can't open file %s\n for RUN",tokens[1].val.s);
						}
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case VOLUME:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetAudioVolume(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetAudioVolume:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case BALANCE:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetAudioBalance(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetAudioBalance:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case FADER:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetAudioFader(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetAudioFader:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case BASS:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetAudioBass(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetAudioBass:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case TREBLE:
				if(numtokens > 1 && getfval(&tokens[1],numtokens-1,&fVal))
				{
					smSetAudioTreble(sm,(short) fVal);
					if(logging)
					{
						fprintf(fpLog,"SetAudioTreble:[%d] %3.f\n",sm,fVal);
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case AUDIO:
				if(numtokens > 1 && getonoff(&tokens[1],numtokens-1,&bVal))
				{
					smSetAudio(sm, bVal);
					if(logging)
					{
						fprintf(fpLog,"SetAudio:[%d] %d\n",sm,bVal);
					}
				}
				break;
			case AUDIO_INPUT:
				if(numtokens > 1)
				{
					if(tokens[1].type & IARG)
					{
						smSetAudioInput(sm,(short) tokens[1].val.i);
						if(logging)
						{
							fprintf(fpLog,"SetAudio:[%d] %d\n",sm,tokens[1].val.i);
						}
					}
				}
				else
				{
					error = tokens[0].val.t;
				}
				break;
			case READ_STATIONS:
				if(numtokens > 1 && (tokens[1].type & NARG))
				{
					smReadProgs(sm,&smtv[sm],tokens[1].val.s);
					if(logging)
					{
						fprintf(fpLog,"ReadStations:[%d] %s\n",sm,tokens[1].val.s);
					}
				}
				else /* ~/.stations */
				{
					smReadProgs(sm,&smtv[sm],"");
					if(logging)
					{
						fprintf(fpLog,"ReadStations:[%d] ~/.stations\n");
					}
				}
				break;
			case NEXT_STATION:
				prog[sm] = smNextProgFor(sm,&smtv[sm],prog[sm],1);
				smSetProg(sm,&smtv[sm],prog[sm]);
				break;
			case PREV_STATION:
				prog[sm] = smNextProgFor(sm,&smtv[sm],prog[sm],0);
				smSetProg(sm,&smtv[sm],prog[sm]);
				break;
			case AFC:
				if(!afcTables[sm])
				{
					afcTables[sm] = (SMAFCTable*) malloc(sizeof(SMAFCTable));
				}
				if(numtokens > 1 && (tokens[1].type & NARG))
				{
					if(!smAFC_InitTableFromFile(afcTables[sm],tokens[1].val.s))
					{
						free(afcTables[sm]);
						afcTables[sm] = 0;
					}		
					else
					{
						smSetAFCTable(sm,&smtv[sm], afcTables[sm]);
					}
					
					if(logging)
					{
						fprintf(fpLog,"ReadAFC:[%d] %s\n",sm,tokens[1].val.s);
					}
				}
				else /* CCIR_Cable.afcTable */
				{
					if(!smAFC_InitTableFromFile(afcTables[sm],"./CCIR_Cable.afcTable"))
					{
						free(afcTables[sm]);
						afcTables[sm] = 0;
					}		
					else
					{
						smSetAFCTable(sm,&smtv[sm], afcTables[sm]);
					}

					if(logging)
					{
						fprintf(fpLog,"ReadAFC:[%d] CCIR_Cable.afcTable\n");
					}
				}
				break;
			case SEARCH:
				if(afcTables[sm])
				{
					freq[sm] = smAfcSearch(sm, &smtv[sm],freq[sm],smGetSystem(sm) , smNorm(sm,&smtv[sm]));
					if(logging)
					{
						fprintf(fpLog,"SearchAFC:[%d] %d\n",sm,freq[sm]);
					}
				}
				else
				{
					freq[sm] = smSearch(sm, &smtv[sm],freq[sm],smGetSystem(sm) , smNorm(sm,&smtv[sm]));
					if(logging)
					{
						fprintf(fpLog,"Search:[%d] %d\n",sm,freq[sm]);
					}
				}
				break;
			case LOG:
				if(numtokens > 1)
				{
					if(!logging)
					{
						if((fpLog = fopen(tokens[1].val.s,"w")))
						{ 
							char name[64];
							
							fprintf(fpLog,"SMParser Log\n");
							bVal = 0;
							i = time(0);
							fprintf(fpLog,"Date: %s\n",ctime(&i));
							gethostname(name,64);
							fprintf(fpLog,"Hostname: %s\n",name);
							#ifdef SCO
								fprintf(fpLog,"OS: SCO\n");
							#endif
							#ifdef LINUX
								fprintf(fpLog,"OS: LINUX\n");
							#endif
							#ifdef ONSITE
								fprintf(fpLog,"OS: SystemV 4.3\n");
							#endif
							logging = YES;
							break;
						}
						else
						{
							printf("\nError: Bad file %s\n",tokens[1].val.s);
						}
					}
				}
				else if(logging)
				{
					fprintf(fpLog,"Closing log\n");
					fclose(fpLog);
					logging = NO;
				}
				break;
			case ASK:
				if(logging && numtokens > 1)
				{
					printf("%s:",tokens[1].val.s);
					fgets(tmp,128,stdin);
					fprintf(fpLog,"Asked:%s = %s",tokens[1].val.s,tmp);
				}
				break;
			case SAY:
				if(logging && numtokens > 1)
				{
					printf("%s\n",tokens[1].val.s);
					fprintf(fpLog,"%s\n",tokens[1].val.s);
				}
				break;
			case HELP:
				if(numtokens > 1)
				{
					printf("HELP: %s\n",tkshelp[findcommand(tokens[1].val.s)]);
				}
				else
				{
					printf("Commands:\n");
					for(i=0;i<NUMTOKENS;i++)
					{
						printf("%s\n",tkshelp[i+1]);
					}
				}
				break;
			default:
				printf("Bad command: %d\n",tokens[0].val.t);
				break;
		}
		if(error)
		{
			print_error(stdout,error);
			if(logging)
			{
				print_error(fpLog,error);
			}
			error = 0;
		}
	}
	else
	{
		printf("Bad command\n");
	}
}

unsigned int findcommand(char *s)
{
	int i,l;
	
	if(s)
	{
		l = strlen(s);
		/* Convert command to lower*/
		for(i=0;i<l;i++)
		{
			if(isupper(s[i]))
			{
				s[i] = tolower(s[i]);
			}
		}
		for(i=0;i<NUMTOKENS;i++)
		{
			if(!strncmp(s,tksname[i],3))
			{
				return i+1;
				break;
			}
		}
	}
	return 0;

}

void tokenize(char *tmp, Token *tokens, int *numtks)
{
	char *cur=tmp,tk[128];
	int l,len = strlen (tmp),pos = 0,i,ival;
	float fval;
	*numtks = 0;
	/* Parse string*/
	if(len  < 1)
	{
		return;
	}

	while(pos+1 < len)
	{
		/* Get string*/
		sscanf(cur,"%s",&tk);
		l =  strlen(tk);
		if(pos == 0 && l > 1) /* First one has to be a command*/
		{
			tokens[*numtks].type = COMMAND;
			tokens[*numtks].val.t = findcommand(tk);
			++(*numtks);
		}
		else /* Arguments*/
		{
			if(l<1)
			{
				break;
			}
			/* Determine type*/
			if(isdigit(tk[0]) || tk[0] == '%' || tk[0] == '+' || tk[0] == '-')
			{
				if(tk[0] == '%')
				{
					#ifdef DEBUG
					fprintf(stderr,"Percent\n");
					#endif
					tokens[*numtks].type = PERCENT;
					fval = (float) strtod (&tk[1], (char**) NULL);
				}
				else if(tk[0] == '+' || tk[0] == '-')
				{
					#ifdef DEBUG
					fprintf(stderr,"Relative\n");
					#endif
					tokens[*numtks].type = RELATIVE;
					fval = (float) strtod (tk, (char**) NULL);
				}
				else
				{
					tokens[*numtks].type = 0;
					fval = (float) strtod (tk, (char**) NULL);
				}
				ival = (int) fval;
				#ifdef DEBUG
				printf("Conv: %s = %f,%d\n",tk,fval,ival);
				#endif
				if( (fval - (float) ival ) != 0.0) /* Float*/
				{
					tokens[*numtks].type |= FARG;
					tokens[*numtks].val.f = fval;
					++(*numtks);
				}
				else /* Int*/
				{
					tokens[*numtks].type |= IARG;
					tokens[*numtks].val.i = ival;
					++(*numtks);
				}
			}
			else /* Is name*/
			{
				tokens[*numtks].type = NARG;
				if(*tk == '"')
				{
					strncpy(tokens[*numtks].val.s,tk+1,64);
					while((tk[l-1] != '"') && (pos+1 < len) )
					{
						pos += l+1;
						cur = (tmp + pos);
						sscanf(cur,"%s",&tk);
						l =  strlen(tk);
						strcat(tokens[*numtks].val.s," ");
						strcat(tokens[*numtks].val.s,tk);
					}
					tokens[*numtks].val.s[strlen(tokens[*numtks].val.s)-1] = 0;
				}
				else
				{
					strncpy(tokens[*numtks].val.s,tk,64);
				}
				tokens[*numtks].val.s[63] = 0;
				++(*numtks);
			}
		}
		pos += l+1;
		cur = (tmp + pos);
	}
}

void printInfo(FILE *fp)
{
	short nLft,nTop,nHgt,nWdt;
	
	if(numsm == 1)
	{
		fprintf(fp,"There is 1 Screen Machine board.\n");
	}
	else
	{
		fprintf(fp,"There are %d Screen Machine boards.\n",numsm);	
	}

	if(sm != -1)
	{
		smGetWindowFrame ( sm, &nLft, &nTop, &nWdt, &nHgt);
		fprintf(fp,"Windowframe (%d,%d),(%d,%d)\n",nLft,nTop,nWdt,nHgt);
		
		smGetVideoFrame ( sm, &nLft, &nTop, &nWdt, &nHgt);
		fprintf(fp,"Videoframe (%d,%d),(%d,%d)\n",nLft,nTop,nWdt,nHgt);
		
		smGetZoomFrame ( sm, &nLft, &nTop, &nWdt, &nHgt);
		fprintf(fp,"Zoomframe (%d,%d),(%d,%d)\n",nLft,nTop,nWdt,nHgt);
	
		fprintf(fp,"Board %d is accepting commands \n",sm);
		fprintf(fp,"Mixers is %s\n",smGetMixer(sm) ? "On" : "Off");
		fprintf(fp,"Video from input %d is %s and %s\n",
			smGetInput(sm),smGetVideo(sm) ? "On" : "Off",smGetLive(sm) ? "Live" : "Still");
		fprintf(fp,"Hue = %d, Saturation = %d, Brightness = %d\n", smGetHue(sm), smGetSaturation(sm),
			smGetBrightness(sm));
			smGetRGB(sm,&nLft,&nTop,&nHgt);
		fprintf(fp,"Red = %d, Green = %d, Blue = %d\n", nLft,nTop,nHgt);
		fprintf(fp,"Contrast = %d, Sharpness = %d, Prefiler is %s \n", smGetContrast(sm), 
			smGetSharpness(sm),smGetPreFilter(sm) ? "On" : "Off");
		fprintf(fp,"Noise = %d, Input = %d, Bandpass = %d \n", smGetNoiseFilter(sm), 
			smGetInputFilter(sm),smGetBandPass(sm));
		fprintf(fp,"PLL = %d, XOFF = %d, YOFF = %d \n", smGetPll(sm), 
			smGetXofs(sm),smGetYofs(sm));
		fprintf(fp,"Fields = %d, Source is %s, is %s Color\n", smGetInputFields(sm), 
			smGetVideoSource(sm) ? "VCR" : "TV" ,smGetColor(sm) ? "" : "not");
		fprintf(fp,"Audio is %s from input %d\n\tVolume %d\n\tBalance %d\n", 
			smGetAudio(sm) ? "ON" : "OFF", smGetAudioInput(sm),smGetAudioVolume(sm),
			smGetAudioBalance(sm));
		fprintf(fp,"\n\tTreble %d\n\tBass %d\n\tFader %d\n", 
			smGetAudioTreble(sm), smGetAudioBass(sm), smGetAudioFader(sm));
	}
	
}

void print_error(FILE *fp,int error)
{
	fprintf(fp,"ERROR: Not enough arguments for %s\n",tkshelp[error]);
}

BOOL getframe(Token* tokens,int numtokens,NXRect *paRect)
{
	if(!getpos(tokens,numtokens,&paRect->origin))
	{
		return NO;
	}
	if(!getsize(&tokens[2],numtokens-2,&paRect->size))
	{
		return NO;
	}
	return YES;
}

BOOL getsize(Token* tokens,int numtokens,NXSize *paSize)
{
	if(numtokens > 1)
	{
		if(tokens[0].type & PERCENT)
		{
			if(tokens[0].type & FARG)
			{
				paSize->width = swdt * ( tokens[0].val.f / 100.0);
			}
			else if(tokens[0].type & IARG)
			{
				paSize->width = swdt * (float) ( (float) tokens[0].val.i / 100.0);
			}
			else
			{
				return NO;
			}
		}
		else
		{
			if(!(tokens[0].type & RELATIVE))
			{
				paSize->width = 0.0;
			}
			if(tokens[0].type & FARG)
			{
				paSize->width += tokens[0].val.f;
			}
			else if(tokens[0].type & IARG)
			{
				paSize->width +=  tokens[0].val.i;
			}
			else
			{
				return NO;
			}
		}
		if(tokens[1].type & PERCENT)
		{
			if(tokens[0].type & FARG)
			{
				paSize->height = shgt * ( tokens[1].val.f / 100.0);
			}
			else if(tokens[0].type & IARG)
			{
				paSize->height = shgt * (float) ( (float) tokens[1].val.i / 100.0);
			}
			else
			{
				return NO;
			}
		}
		else
		{
			if(!(tokens[1].type & RELATIVE))
			{
				paSize->height = 0.0;
			}
			if(tokens[1].type & FARG)
			{
				paSize->height +=  tokens[1].val.f;
			}
			else if(tokens[1].type & IARG)
			{
				paSize->height +=  tokens[1].val.i;
			}
			else
			{
				return NO;
			}
		}
		return YES;
	}
	return NO;

}

BOOL getpos(Token* tokens,int numtokens,NXPoint *paPoint)
{
	if(numtokens > 1)
	{
		if(tokens[0].type & PERCENT)
		{
			if(tokens[0].type & FARG)
			{
					paPoint->x = swdt * ( tokens[0].val.f / 100.0);
			}
			else if(tokens[0].type & IARG)
			{
					paPoint->x = swdt * ( tokens[0].val.i / 100.0);
			}
		}
		else
		{
			if(!(tokens[0].type & RELATIVE))
			{
				paPoint->x = 0.0; 
			} 
			if(tokens[0].type & FARG)
			{
				paPoint->x +=  (NXCoord) tokens[0].val.f;
			}
			else if(tokens[0].type & IARG)
			{
				paPoint->x +=  (NXCoord) tokens[0].val.i;
			}
			else
			{
				return NO;
			}
		}
		if(tokens[1].type & PERCENT)
		{
			if(tokens[0].type & FARG)
			{
			paPoint->y = shgt * ( tokens[1].val.f / 100.0);
			}
			else if(tokens[0].type & IARG)
			{
			paPoint->y = shgt * ( tokens[1].val.i / 100.0);
			}
		}
		else
		{
			if(!(tokens[1].type & RELATIVE))
			{
				paPoint->y = 0.0;
			}
			if(tokens[1].type & FARG)
			{
				paPoint->y +=  (NXCoord) tokens[1].val.f;
			}
			else if(tokens[1].type & IARG)
			{
				paPoint->y +=  (NXCoord) tokens[1].val.i;
			}
			else
			{
				return NO;
			}
		}
		return YES;
	}
	return NO;
}

BOOL getonoff(Token* tokens,int numtokens,BOOL *pOnOff)
{
	if(numtokens)
	{
		if(tokens[0].type & IARG)
		{
			*pOnOff = (BOOL) tokens[0].val.i;
		}
		else if(tokens[0].type & NARG)
		{
			switch(tokens[0].val.s[1])
			{
				case 'N': /* On*/
				case 'n': /* On*/
					*pOnOff = YES;
					break;
				case 'F': /* Off*/
				case 'f': /* Off*/
					*pOnOff = NO;
					break;
				case 'E': /* Yes*/
				case 'e': /* Yes*/
					*pOnOff = YES;
					break;
				case 'O': /* No*/
				case 'o': /* No*/
					*pOnOff = NO;
					break;
			}
		}
		else
		{
			return NO;
		}
		return YES;
	}
	return NO;
}

BOOL getfval(Token* tokens,int numtokens,float *pfVal)
{
	if(numtokens)
	{
		if(tokens[0].type & IARG)
		{
			tokens[0].type += FARG-IARG;
			tokens[0].val.f = (float) tokens[0].val.i;
		}
		else if(tokens[0].type & NARG)
		{
			tokens[0].type = FARG;
			switch(tokens[0].val.s[2])
			{
				case 'x': /* Max*/
				case 'X': /* Max*/
					tokens[0].val.f = 1.0;
					break;
				case 'N': /* Min*/
				case 'n': /* Min*/
					tokens[0].val.f = 0.0;
					break;
				case 'd': /* Mid*/
				case 'D': /* Mid*/
					tokens[0].val.f = 0.5;
					break;
				default:
					return NO;		
			}
		}
		
		if(tokens[0].type & FARG)
		{
			if(tokens[0].type & RELATIVE)
			{
				*pfVal += tokens[0].val.f;
			}
			else if(tokens[0].type & PERCENT)
			{
				*pfVal *= (1.0 +  tokens[0].val.f);
			}
			else
			{
				*pfVal = tokens[0].val.f;
			}
		}
		else 
		{
			return NO;
		}	
		return YES;	
	}
	return NO;
}
