1 // Token Interpreter
2 //
3 //	-- jweier
4 
5 #ifdef _WIN32
6 	#include <direct.h>	//For getcwd()
7 	#include <conio.h>	//For getch()
8 #else
9 	#include <curses.h>
10 	#include <unistd.h>
11 #endif
12 
13 #include <stdio.h>
14 
15 #include "tokenizer.h"
16 #include "blockstream.h"
17 #include "interpreter.h"
18 
19 /*
20 ===================================================================================================
21 
22   Table Definitions
23 
24 ===================================================================================================
25 */
26 
27 //FIXME: The following tables should be passed in to the interpreter for flexibility
28 
29 //Symbol Table
30 
31 keywordArray_t CInterpreter::m_symbolKeywords[] =
32 {
33 	//Blocks
34 	"{",	TK_BLOCK_START,
35 	"}",	TK_BLOCK_END,
36 
37 	//Vectors
38 	"<",	TK_VECTOR_START,
39 	">",	TK_VECTOR_END,
40 
41 	//Groups
42 	"(",	TK_OPEN_PARENTHESIS,
43 	")",	TK_CLOSED_PARENTHESIS,
44 
45 	"=",	TK_EQUALS,
46 	"!",	TK_NOT,
47 
48 	//End
49 	"",		TK_EOF,
50 };
51 
52 keywordArray_t CInterpreter::m_conditionalKeywords[] =
53 {
54 	"",		TK_EOF,
55 };
56 
57 //ID Table
58 
59 keywordArray_t CInterpreter::m_IDKeywords[] =
60 {
61 	"AFFECT",		ID_AFFECT,
62 	"SOUND",		ID_SOUND,
63 	"MOVE",			ID_MOVE,
64 	"ROTATE",		ID_ROTATE,
65 	"WAIT",			ID_WAIT,
66 	"SET",			ID_SET,
67 	"LOOP",			ID_LOOP,
68 	"PRINT",		ID_PRINT,
69 	"TAG",			ID_TAG,
70 	"USE",			ID_USE,
71 	"FLUSH",		ID_FLUSH,
72 	"RUN",			ID_RUN,
73 	"KILL",			ID_KILL,
74 	"REMOVE",		ID_REMOVE,
75 	"CAMERA",		ID_CAMERA,
76 	"GET",			ID_GET,
77 	"RANDOM",		ID_RANDOM,
78 	"IF",			ID_IF,
79 	"ELSE",			ID_ELSE,
80 	"REM",			ID_REM,
81 	"FLOAT",		TK_FLOAT,
82 	"VECTOR",		TK_VECTOR,
83 	"STRING",		TK_STRING,
84 	"TASK",			ID_TASK,
85 	"DO",			ID_DO,
86 	"DECLARE",		ID_DECLARE,
87 	"FREE",			ID_FREE,
88 	"DOWAIT",		ID_DOWAIT,
89 	"SIGNAL",		ID_SIGNAL,
90 	"WAITSIGNAL",	ID_WAITSIGNAL,
91 	"PLAY",			ID_PLAY,
92 
93 	"",			ID_EOF,
94 };
95 
96 //Type Table
97 
98 keywordArray_t CInterpreter::m_typeKeywords[] =
99 {
100 	//Set types
101 	"ANGLES",		TYPE_ANGLES,
102 	"ORIGIN",		TYPE_ORIGIN,
103 
104 	//Affect types
105 	"INSERT",		TYPE_INSERT,
106 	"FLUSH",		TYPE_FLUSH,
107 
108 	//Get types
109 	"FLOAT",		TK_FLOAT,
110 	"INT",			TK_INT,
111 	"VECTOR",		TK_VECTOR,
112 	"STRING",		TK_STRING,
113 
114 	"PAN",			TYPE_PAN,
115 	"ZOOM",			TYPE_ZOOM,
116 	"MOVE",			TYPE_MOVE,
117 	"FADE",			TYPE_FADE,
118 	"PATH",			TYPE_PATH,
119 	"ENABLE",		TYPE_ENABLE,
120 	"DISABLE",		TYPE_DISABLE,
121 	"SHAKE",		TYPE_SHAKE,
122 	"ROLL",			TYPE_ROLL,
123 	"TRACK",		TYPE_TRACK,
124 	"FOLLOW",		TYPE_FOLLOW,
125 	"DISTANCE",		TYPE_DISTANCE,
126 
127 	//End
128 	"",				TYPE_EOF,
129 };
130 
131 
132 /*
133 ===================================================================================================
134 
135   Constructor / Destructor
136 
137 ===================================================================================================
138 */
139 
CInterpreter()140 CInterpreter::CInterpreter()
141 {
142 }
143 
~CInterpreter()144 CInterpreter::~CInterpreter()
145 {
146 }
147 
148 /*
149 ===================================================================================================
150 
151 	Error Handling
152 
153 ===================================================================================================
154 */
155 
Error(char * format,...)156 int CInterpreter::Error( char *format, ... )
157 {
158 	va_list		argptr;
159 	char		*error_file, error_msg[1024]="", work_dir[1024]="", out_msg[1024]="";
160 	int			error_line = m_iCurrentLine;	// m_tokenizer->GetCurLine();
161 
162 	m_tokenizer->GetCurFilename( &error_file );
163 	if (!error_file)
164 	{
165 		// 99% of the time we'll get here now, because of pushed parse streams
166 		//
167 		error_file = (char *)m_sCurrentFile.c_str();
168 	}
169 
170 	va_start (argptr, format);
171 	vsprintf (error_msg, format, argptr);
172 	va_end (argptr);
173 
174 	strcpy((char *) work_dir, getcwd( (char *) &work_dir, 1024 ) );
175 
176 	if (error_file[1] == ':')
177 	{
178 		sprintf((char *) out_msg, "%s (%d) : error: %s\n", error_file, error_line, error_msg);
179 	}
180 	else
181 	{
182 		sprintf((char *) out_msg, "%s\\%s (%d) : error: %s\n", work_dir, error_file, error_line, error_msg);
183 	}
184 
185 	if (m_sCurrentLine.length())
186 	{
187 		strcat(out_msg, "\nLine:\n\n");
188 		strcat(out_msg, m_sCurrentLine.c_str());
189 		strcat(out_msg, "\n");
190 	}
191 
192 #ifdef __POP_UPS__
193 
194 	MessageBox( NULL, out_msg, "Error", MB_OK );
195 
196 #else
197 
198 	printf(out_msg);
199 
200 #endif
201 
202 	// A bit of kludge code that takes care of the case where there's some garbage at the beginning of the file
203 	//	before any blocks are read as valid. This is needed because ints are incapable of containing 0
204 	//
205 	// This'll mean that technically it's saying block 1 is wrong, rather than the one in between them, but I can
206 	//	live with that.
207 	//
208 	if (m_iBadCBlockNumber == 0)
209 	{
210 		m_iBadCBlockNumber = 1;
211 	}
212 	return false;
213 }
214 
215 /*
216 ===================================================================================================
217 
218 	Local Variable Functions
219 
220 ===================================================================================================
221 */
222 
223 /*
224 -------------------------
225 InitVars
226 -------------------------
227 */
228 
InitVars(void)229 void CInterpreter::InitVars( void )
230 {
231 	m_vars.clear();
232 	m_varMap.clear();
233 }
234 
235 /*
236 -------------------------
237 FreeVars
238 -------------------------
239 */
240 
FreeVars(void)241 void CInterpreter::FreeVars( void )
242 {
243 	variable_v::iterator	vi;
244 
245 	for ( vi = m_vars.begin(); vi != m_vars.end(); ++vi )
246 	{
247 		delete (*vi);
248 	}
249 
250 	InitVars();
251 }
252 
253 /*
254 -------------------------
255 AddVar
256 -------------------------
257 */
258 
AddVar(const char * name,int type)259 variable_t *CInterpreter::AddVar( const char *name, int type )
260 {
261 	variable_t	*var;
262 
263 	var = new variable_t;
264 
265 	if ( var == NULL )
266 		return NULL;
267 
268 	//Specify the type
269 	var->type = type;
270 
271 	//Retain the name internally
272 	strncpy( (char *) var->name, name, MAX_VAR_NAME );
273 
274 	//Associate it
275 	m_varMap[ name ] = var;
276 
277 	return var;
278 }
279 
280 /*
281 -------------------------
282 FindVar
283 -------------------------
284 */
285 
FindVar(const char * name)286 variable_t *CInterpreter::FindVar( const char *name )
287 {
288 	variable_m::iterator	vmi;
289 
290 	vmi = m_varMap.find( name );
291 
292 	if ( vmi == m_varMap.end() )
293 		return NULL;
294 
295 	return (*vmi).second;
296 }
297 
298 /*
299 -------------------------
300 GetVariable
301 -------------------------
302 */
303 
GetVariable(int type)304 int CInterpreter::GetVariable( int type )
305 {
306 	const char	*varName;
307 	variable_t	*var;
308 	CToken		*token;
309 
310 	//Get the variable's name
311 	token = m_tokenizer->GetToken( 0, 0 );
312 	varName = token->GetStringValue();
313 
314 	//See if we already have a variable by this name
315 	var = FindVar( varName );
316 
317 	//Variable names must be unique on creation
318 	if ( var )
319 		return Error( "\"%s\" : already exists\n", varName );
320 
321 	//Add the variable
322 	AddVar( varName, type );
323 
324 	//Insert the variable into the stream
325 
326 	CBlock	block;
327 
328 	block.Create( TYPE_VARIABLE );
329 	block.Write( TK_FLOAT, (float) type );
330 	block.Write( TK_STRING, varName );
331 
332 	m_blockStream->WriteBlock( &block );
333 
334 	token->Delete();
335 
336 	return true;
337 }
338 
339 /*
340 ===================================================================================================
341 
342 	ID Table Functions
343 
344 ===================================================================================================
345 */
346 
GetVector(CBlock * block)347 int CInterpreter::GetVector( CBlock *block )
348 {
349 	//Look for a tag
350 	if ( MatchTag() )
351 	{
352 		return GetTag( block );
353 	}
354 
355 	//Look for a get
356 	if ( MatchGet() )
357 	{
358 		return GetGet( block );
359 	}
360 
361 	if ( Match( TK_VECTOR_START ) )
362 	{
363 		//Get the vector
364 		block->Write( TK_VECTOR, (float) TK_VECTOR );
365 
366 		for (int i=0; i<3; i++)
367 			GetFloat( block );
368 
369 		if (!Match( TK_VECTOR_END ))
370 		{
371 			return Error("syntax error : expected end of vector");
372 		}
373 
374 		return true;
375 	}
376 
377 	return false;
378 }
379 
380 /*
381 ===================================================================================================
382 
383   MatchTag()
384 
385   Attempts to match to a tag identifier.
386 
387 ===================================================================================================
388 */
389 
MatchTag(void)390 int CInterpreter::MatchTag( void )
391 {
392 	CToken		*token;
393 	const char	*idName;
394 	int			id;
395 
396 	token = m_tokenizer->GetToken( 0, 0 );
397 	idName = token->GetStringValue();
398 	id = FindSymbol( idName, m_IDKeywords );
399 
400 	if ( id != ID_TAG )
401 	{
402 		//Return the token
403 		m_tokenizer->PutBackToken( token );
404 		return false;
405 	}
406 
407 	token->Delete();
408 	return true;
409 }
410 
411 /*
412 ===================================================================================================
413 
414   MatchGet()
415 
416   Attempts to match to a get identifier.
417 
418 ===================================================================================================
419 */
420 
MatchGet(void)421 int CInterpreter::MatchGet( void )
422 {
423 	CToken		*token;
424 	const char	*idName;
425 	int			id;
426 
427 	token = m_tokenizer->GetToken( 0, 0 );
428 	idName = token->GetStringValue();
429 	id = FindSymbol( idName, m_IDKeywords );
430 
431 	if ( id != ID_GET )
432 	{
433 		//Return the token
434 		m_tokenizer->PutBackToken( token );
435 		return false;
436 	}
437 
438 	token->Delete();
439 	return true;
440 }
441 
442 /*
443 ===================================================================================================
444 
445   MatchRandom()
446 
447   Attempts to match to a random identifier.
448 
449 ===================================================================================================
450 */
451 
MatchRandom(void)452 int CInterpreter::MatchRandom( void )
453 {
454 	CToken		*token;
455 	const char	*idName;
456 	int			id;
457 
458 	token = m_tokenizer->GetToken( 0, 0 );
459 	idName = token->GetStringValue();
460 	id = FindSymbol( idName, m_IDKeywords );
461 
462 	if ( id != ID_RANDOM )
463 	{
464 		//Return the token
465 		m_tokenizer->PutBackToken( token );
466 		return false;
467 	}
468 
469 	token->Delete();
470 	return true;
471 }
472 
473 /*
474 ===================================================================================================
475 
476   FindSymbol()
477 
478   Searches the symbol table for the given name.  Returns the ID if found.
479 
480 ===================================================================================================
481 */
482 
FindSymbol(const char * name,keywordArray_t * table)483 int CInterpreter::FindSymbol( const char *name,  keywordArray_t *table)
484 {
485 	keywordArray_t *ids;
486 
487 	for (ids = table; (strcmp(ids->m_keyword, "")); ids++)
488 	{
489 		if (!stricmp(name, ids->m_keyword))
490 			return ids->m_tokenvalue;
491 	}
492 
493 	return -1;
494 }
495 
496 
497 /*
498 ===================================================================================================
499 
500   Match()
501 
502   Looks ahead to the next token to try and match it to the passed token, consumes token on success.
503 
504 ===================================================================================================
505 */
506 
507 //NOTENOTE:  LookAhead() was separated from Match() for clarity
508 
Match(int token_id)509 int CInterpreter::Match( int token_id )
510 {
511 	CToken	*token;
512 
513 	token = m_tokenizer->GetToken( 0, 0 );
514 
515 	if ( token->GetType() != token_id )
516 	{
517 		//This may have been a check, so don't loose the token
518 		m_tokenizer->PutBackToken( token );
519 
520 		return false;
521 	}
522 
523 	return true;
524 }
525 
526 /*
527 -------------------------
528 GetNextType
529 -------------------------
530 */
531 
GetNextType(void)532 int CInterpreter::GetNextType( void )
533 {
534 	CToken	*token = m_tokenizer->GetToken( 0, 0 );
535 	int		id = token->GetType();
536 
537 	m_tokenizer->PutBackToken( token );
538 
539 	return id;
540 }
541 
542 /*
543 ===================================================================================================
544 
545   LookAhead()
546 
547   Looks ahead without consuming on success.
548 
549 ===================================================================================================
550 */
551 
LookAhead(int token_id)552 int CInterpreter::LookAhead( int token_id )
553 {
554 	CToken	*token;
555 
556 	token = m_tokenizer->GetToken( 0, 0 );
557 
558 	if ( token->GetType() != token_id )
559 	{
560 		m_tokenizer->PutBackToken( token );
561 
562 		return false;
563 	}
564 
565 	m_tokenizer->PutBackToken( token );
566 
567 	return true;
568 }
569 
570 /*
571 ===================================================================================================
572 
573   GetTokenName()
574 
575   Returns the name of a token.
576 
577 ===================================================================================================
578 */
579 
GetTokenName(int token_id)580 const char *CInterpreter::GetTokenName( int token_id )
581 {
582 	switch ( token_id )
583 	{
584 	case TK_STRING:
585 		return "STRING";
586 		break;
587 
588 	case TK_CHAR:
589 		return "CHARACTER";
590 		break;
591 
592 	case TK_IDENTIFIER:
593 		return "IDENTIFIER";
594 		break;
595 
596 	case TK_FLOAT:
597 		return "FLOAT";
598 		break;
599 
600 	case TK_INTEGER:
601 		return "INTEGER";
602 		break;
603 
604 	default:
605 		return "UNKNOWN";
606 		break;
607 	}
608 }
609 
610 /*
611 ===================================================================================================
612 
613 	Token Value Functions
614 
615 ===================================================================================================
616 */
617 
618 /*
619 ===================================================================================================
620 
621   GetFloat()
622 
623   Attempts to match and retrieve the value of a float token.
624 
625 ===================================================================================================
626 */
627 
GetFloat(CBlock * block)628 int CInterpreter::GetFloat( CBlock *block )
629 {
630 	CToken	*token;
631 	int		type;
632 
633 	//Look for a get
634 	if ( MatchGet() )
635 	{
636 		return GetGet( block );
637 	}
638 
639 	//Look for a random
640 	if ( MatchRandom() )
641 	{
642 		return GetRandom( block );
643 	}
644 
645 	token = m_tokenizer->GetToken(0,0);
646 	type = token->GetType();
647 
648 	//Floats can accept either int or float values
649 	if ( ( type != TK_FLOAT ) && ( type != TK_INT ) )
650 	{
651 		return Error("syntax error : expected float; found %s", GetTokenName(type) );
652 	}
653 
654 	if (type == TK_FLOAT)
655 	{
656 		block->Write( TK_FLOAT, (float) token->GetFloatValue() );
657 	}
658 	else
659 	{
660 		block->Write( TK_FLOAT, (float) token->GetIntValue() );
661 	}
662 
663 	token->Delete();
664 
665 	return true;
666 }
667 
668 /*
669 ===================================================================================================
670 
671   GetInteger()
672 
673   Attempts to match and retrieve the value of an integer token.
674 
675 ===================================================================================================
676 */
677 
GetInteger(CBlock * block)678 int CInterpreter::GetInteger( CBlock *block )
679 {
680 	return GetFloat( block );
681 }
682 
683 /*
684 ===================================================================================================
685 
686   GetString()
687 
688   Attempts to match and retrieve the value of a string token.
689 
690 ===================================================================================================
691 */
692 
GetString(CBlock * block)693 int CInterpreter::GetString( CBlock *block )
694 {
695 	CToken	*token;
696 	int		type;
697 
698 	//Look for a get
699 	if ( MatchGet() )
700 	{
701 		return GetGet( block );
702 	}
703 
704 	//Look for a random
705 	if ( MatchRandom() )
706 	{
707 		return GetRandom( block );
708 	}
709 
710 	token = m_tokenizer->GetToken(0, 0);
711 	type = token->GetType();
712 
713 	if ( (type != TK_STRING) && (type != TK_CHAR) )
714 	{
715 		return Error("syntax error : expected string; found %s", GetTokenName(type));
716 	}
717 
718 //UGLY HACK!!!
719 
720 	const char	*temptr;
721 	char		temp[1024];
722 
723 	temptr = token->GetStringValue();
724 
725 	if ( strlen(temptr)+1 > sizeof( temp ) )
726 	{
727 		return false;
728 	}
729 
730 	for ( int i = 0; i < strlen( temptr ); i++ )
731 	{
732 		if ( temptr[i] == '#' )
733 			temp[i] = '\n';
734 		else
735 			temp[i] = temptr[i];
736 	}
737 
738 	temp[ strlen( temptr ) ] = 0;
739 
740 //UGLY HACK END!!!
741 
742 	block->Write( TK_STRING, (const char *) &temp );
743 
744 	token->Delete();
745 
746 	return true;
747 }
748 
749 /*
750 ===================================================================================================
751 
752   GetIdentifier()
753 
754   Attempts to match and retrieve the value of an indentifier token.
755 
756 ===================================================================================================
757 */
758 
GetIdentifier(CBlock * block)759 int CInterpreter::GetIdentifier( CBlock *block )
760 {
761 	CToken	*token;
762 	int		type;
763 
764 	//FIXME: Should identifiers do this?
765 	if ( MatchGet() )
766 	{
767 		if ( GetGet( block ) == false )
768 			return false;
769 
770 		return true;
771 	}
772 
773 	token = m_tokenizer->GetToken(0, 0);
774 	type = token->GetType();
775 
776 	if ( type != TK_IDENTIFIER )
777 	{
778 		return Error("syntax error : expected indentifier; found %s", GetTokenName(type));
779 	}
780 
781 	block->Write( TK_IDENTIFIER, (const char *) token->GetStringValue() );
782 
783 	token->Delete();
784 
785 	return true;
786 }
787 
788 /*
789 ===================================================================================================
790 
791   GetEvaluator()
792 
793   Attempts to match and retrieve the value of an evaluator token.
794 
795 ===================================================================================================
796 */
797 
GetEvaluator(CBlock * block)798 int CInterpreter::GetEvaluator( CBlock *block )
799 {
800 	CToken	*token;
801 	int		type;
802 
803 	if ( MatchGet() )
804 		return false;
805 
806 	if ( MatchRandom() )
807 		return false;
808 
809 	token = m_tokenizer->GetToken(0, 0);
810 	type = token->GetType();
811 	token->Delete();
812 
813 	switch ( type )
814 	{
815 	case TK_GREATER_THAN:
816 	case TK_LESS_THAN:
817 	case TK_EQUALS:
818 	case TK_NOT:
819 		break;
820 
821 	case TK_VECTOR_START:
822 		type = TK_LESS_THAN;
823 		break;
824 
825 	case TK_VECTOR_END:
826 		type = TK_GREATER_THAN;
827 		break;
828 
829 	default:
830 		return Error("syntax error : expected operator type, found %s", GetTokenName( type ) );
831 	}
832 
833 	block->Write( type, 0 );
834 
835 	return true;
836 }
837 
838 /*
839 ===================================================================================================
840 
841   GetAny()
842 
843   Attempts to match and retrieve any valid data type.
844 
845 ===================================================================================================
846 */
847 
GetAny(CBlock * block)848 int CInterpreter::GetAny( CBlock *block )
849 {
850 	CToken	*token;
851 	int		type;
852 
853 	if ( MatchGet() )
854 	{
855 		if ( GetGet( block ) == false )
856 			return false;
857 
858 		return true;
859 	}
860 
861 	if ( MatchRandom() )
862 	{
863 		if ( GetRandom( block ) == false )
864 			return false;
865 
866 		return true;
867 	}
868 
869 	if ( MatchTag() )
870 	{
871 		if ( GetTag( block ) == false )
872 			return false;
873 
874 		return true;
875 	}
876 
877 	token = m_tokenizer->GetToken(0, 0);
878 	type = token->GetType();
879 
880 	switch ( type )
881 	{
882 	case TK_FLOAT:
883 		m_tokenizer->PutBackToken( token );
884 		if ( GetFloat( block ) == false )
885 			return false;
886 
887 		break;
888 
889 	case TK_INT:
890 		m_tokenizer->PutBackToken( token );
891 		if ( GetInteger( block ) == false )
892 			return false;
893 
894 		break;
895 
896 	case TK_VECTOR_START:
897 		m_tokenizer->PutBackToken( token );
898 		if ( GetVector( block ) == false )
899 			return false;
900 
901 		break;
902 
903 	case TK_STRING:
904 	case TK_CHAR:
905 		m_tokenizer->PutBackToken( token );
906 		if ( GetString( block ) == false )
907 			return false;
908 
909 		break;
910 
911 	case TK_IDENTIFIER:
912 		m_tokenizer->PutBackToken( token );
913 		if ( GetIdentifier( block ) == false )
914 			return false;
915 
916 		break;
917 
918 	default:
919 		return false;
920 	}
921 
922 	return true;
923 }
924 
925 /*
926 ===================================================================================================
927 
928   GetType()
929 
930   Attempts to match and retrieve the value of a type token.
931 
932 ===================================================================================================
933 */
934 
GetType(char * get)935 int CInterpreter::GetType( char *get )
936 {
937 	CToken	*token;
938 	char	*string;
939 	int		type;
940 
941 	token = m_tokenizer->GetToken(0, 0);
942 	type = token->GetType();
943 
944 	if ( type != TK_IDENTIFIER )
945 	{
946 		return Error("syntax error : expected identifier; found %s", GetTokenName(type));
947 	}
948 
949 	string = (char *) token->GetStringValue();
950 
951 	if ( (strlen(string) + 1) > MAX_STRING_LENGTH)
952 	{
953 		Error("string exceeds 256 character limit");
954 		return false;
955 	}
956 
957 	strcpy(get, string);
958 
959 	return true;
960 }
961 
962 /*
963 ===================================================================================================
964 
965   GetID()
966 
967   Attempts to match and interpret an identifier.
968 
969 ===================================================================================================
970 */
971 
972 //FIXME: This should use an externally defined table to match ID and functions
973 
GetID(char * id_name)974 int CInterpreter::GetID( char *id_name )
975 {
976 	int		id;
977 
978 	id = FindSymbol( id_name, m_IDKeywords );
979 
980 	if ( id == -1 )
981 		return Error("'%s' : unknown identifier", id_name);
982 
983 	//FIXME: Function pointers would be awfully nice.. but not inside a class!  Weee!!
984 
985 	switch (id)
986 	{
987 
988 	//Affect takes control of an entity
989 
990 	case ID_AFFECT:
991 		return GetAffect();
992 		break;
993 
994 	//Wait for a specified amount of time
995 
996 	case ID_WAIT:
997 		return GetWait();
998 		break;
999 
1000 	//Generic set call
1001 
1002 	case ID_SET:
1003 		return GetSet();
1004 		break;
1005 
1006 	case ID_LOOP:
1007 		return GetLoop();
1008 		break;
1009 
1010 	case ID_PRINT:
1011 		return GetPrint();
1012 		break;
1013 
1014 	case ID_USE:
1015 		return GetUse();
1016 		break;
1017 
1018 	case ID_FLUSH:
1019 		return GetFlush();
1020 		break;
1021 
1022 	case ID_RUN:
1023 		return GetRun();
1024 		break;
1025 
1026 	case ID_KILL:
1027 		return GetKill();
1028 		break;
1029 
1030 	case ID_REMOVE:
1031 		return GetRemove();
1032 		break;
1033 
1034 	case ID_CAMERA:
1035 		return GetCamera();
1036 		break;
1037 
1038 	case ID_SOUND:
1039 		return GetSound();
1040 		break;
1041 
1042 	case ID_MOVE:
1043 		return GetMove();
1044 		break;
1045 
1046 	case ID_ROTATE:
1047 		return GetRotate();
1048 		break;
1049 
1050 	case ID_IF:
1051 		return GetIf();
1052 		break;
1053 
1054 	case ID_ELSE:
1055 		//return Error("syntax error : else without matching if");
1056 		return GetElse();	//FIXME: Protect this call so that floating else's aren't allowed
1057 		break;
1058 
1059 	case ID_GET:
1060 		return Error("syntax error : illegal use of \"get\"");
1061 		break;
1062 
1063 	case ID_TAG:
1064 		return Error("syntax error : illegal use of \"tag\"");
1065 		break;
1066 
1067 	case ID_TASK:
1068 		return GetTask();
1069 		break;
1070 
1071 	case ID_DO:
1072 		return GetDo();
1073 		break;
1074 
1075 	case ID_DECLARE:
1076 		return GetDeclare();
1077 		break;
1078 
1079 	case ID_FREE:
1080 		return GetFree();
1081 		break;
1082 
1083 	case ID_REM:
1084 		GetRem();
1085 		break;
1086 
1087 	case ID_DOWAIT:
1088 		GetDoWait();
1089 		break;
1090 
1091 	case ID_SIGNAL:
1092 		GetSignal();
1093 		break;
1094 
1095 	case ID_WAITSIGNAL:
1096 		GetWaitSignal();
1097 		break;
1098 
1099 	case ID_PLAY:
1100 		GetPlay();	//Bad eighties slang joke...  yeah, it's not really funny, I know...
1101 		break;
1102 
1103 		//Local variable types
1104 	case TK_FLOAT:
1105 	case TK_INT:
1106 	case TK_STRING:
1107 	case TK_VECTOR:
1108 		GetVariable( id );
1109 		break;
1110 
1111 	//Unknown ID
1112 
1113 	default:
1114 	case -1:
1115 		return Error("'%s' : unknown identifier", id_name);
1116 		break;
1117 	}
1118 
1119 	return true;
1120 }
1121 
1122 /*
1123 ===================================================================================================
1124 
1125 	ID Interpreting Functions
1126 
1127 ===================================================================================================
1128 */
1129 
1130 /*
1131 -------------------------
1132 GetDeclare
1133 -------------------------
1134 */
1135 
GetDeclare(void)1136 int CInterpreter::GetDeclare( void )
1137 {
1138 	CBlock	block;
1139 	char	typeName[MAX_STRING_LENGTH];
1140 	int		type;
1141 
1142 	block.Create( ID_DECLARE );
1143 
1144 	if (!Match( TK_OPEN_PARENTHESIS ))
1145 		return Error("syntax error : '(' not found");
1146 
1147 	if ( GetType( (char *) typeName ) == false )
1148 		return false;
1149 
1150 	type = FindSymbol( typeName, m_typeKeywords);
1151 
1152 	switch ( type )
1153 	{
1154 	case TK_FLOAT:
1155 	case TK_VECTOR:
1156 	case TK_STRING:
1157 		block.Write( TK_FLOAT, (float) type );
1158 		break;
1159 
1160 	default:
1161 		return Error("unknown identifier %s", typeName );
1162 		break;
1163 	}
1164 
1165 	if ( GetString( &block ) == false )
1166 		return false;
1167 
1168 	if (!Match( TK_CLOSED_PARENTHESIS ))
1169 		return Error("declare : too many parameters");
1170 
1171 	m_blockStream->WriteBlock( &block );
1172 
1173 	return true;
1174 }
1175 
1176 
1177 /*
1178 -------------------------
1179 GetFree
1180 -------------------------
1181 */
1182 
GetFree(void)1183 int CInterpreter::GetFree( void )
1184 {
1185 	CBlock	block;
1186 
1187 	block.Create( ID_FREE );
1188 
1189 	if ( Match( TK_OPEN_PARENTHESIS ) == false )
1190 		return Error("syntax error : '(' not found");
1191 
1192 	if ( GetString( &block ) == false )
1193 		return false;
1194 
1195 	if ( Match( TK_CLOSED_PARENTHESIS ) == false )
1196 		return Error("free : too many parameters");
1197 
1198 	m_blockStream->WriteBlock( &block );
1199 
1200 	return true;
1201 }
1202 
1203 /*
1204 ===================================================================================================
1205 
1206   GetIf()
1207 
1208   Handles the if() conditional statement.
1209 
1210 ===================================================================================================
1211 */
1212 
1213 // if ( STRING ? STRING )
1214 
GetIf(void)1215 int CInterpreter::GetIf( void )
1216 {
1217 	CBlock	block;
1218 
1219 	block.Create( ID_IF );
1220 
1221 	if ( Match( TK_OPEN_PARENTHESIS ) == false )
1222 		return Error("syntax error : '(' not found");
1223 
1224 	if ( GetAny( &block ) == false )
1225 		return false;
1226 
1227 	if ( GetEvaluator( &block ) == false )
1228 		return false;
1229 
1230 	if ( GetAny( &block ) == false )
1231 		return false;
1232 
1233 	if ( Match( TK_CLOSED_PARENTHESIS ) == false )
1234 		return Error("if : too many parameters");
1235 
1236 	m_blockStream->WriteBlock( &block );
1237 
1238 	return true;
1239 }
1240 
1241 /*
1242 ===================================================================================================
1243 
1244   GetElse()
1245 
1246   Handles the else() conditional statement.
1247 
1248 ===================================================================================================
1249 */
1250 
1251 // else
1252 
GetElse(void)1253 int CInterpreter::GetElse( void )
1254 {
1255 	CBlock	block;
1256 
1257 	block.Create( ID_ELSE );
1258 
1259 	/*
1260 	if ( Match( TK_OPEN_PARENTHESIS ) == false )
1261 		return Error("syntax error : '(' not found");
1262 	*/
1263 
1264 	/*
1265 	if ( GetAny( &block ) == false )
1266 		return false;
1267 
1268 	if ( GetEvaluator( &block ) == false )
1269 		return false;
1270 
1271 	if ( GetAny( &block ) == false )
1272 		return false;
1273 	*/
1274 
1275 	/*
1276 	if ( Match( TK_CLOSED_PARENTHESIS ) == false )
1277 		return Error("sound : too many parameters");
1278 	*/
1279 
1280 	m_blockStream->WriteBlock( &block );
1281 
1282 	return true;
1283 }
1284 
1285 /*
1286 ===================================================================================================
1287 
1288   GetTask()
1289 
1290   Handles the task() sequence specifier.
1291 
1292 ===================================================================================================
1293 */
1294 
1295 //task ( name ) { }
1296 
GetTask(void)1297 int CInterpreter::GetTask( void )
1298 {
1299 	CBlock	block;
1300 
1301 	block.Create( ID_TASK );
1302 
1303 	if (!Match( TK_OPEN_PARENTHESIS ))
1304 		return Error("syntax error : '(' not found");
1305 
1306 	if ( GetString( &block ) == false )
1307 		return false;
1308 
1309 	if (!Match( TK_CLOSED_PARENTHESIS ))
1310 		return Error("GetTask: too many parameters");
1311 
1312 	m_blockStream->WriteBlock( &block );
1313 
1314 	return true;
1315 
1316 }
1317 
1318 /*
1319 ===================================================================================================
1320 
1321   GetDo()
1322 
1323   Handles the do() function.
1324 
1325 ===================================================================================================
1326 */
1327 
1328 //do ( taskName )
1329 
GetDo(void)1330 int CInterpreter::GetDo( void )
1331 {
1332 	CBlock	block;
1333 
1334 	block.Create( ID_DO );
1335 
1336 	if (!Match( TK_OPEN_PARENTHESIS ))
1337 		return Error("syntax error : '(' not found");
1338 
1339 	if ( GetString( &block ) == false )
1340 		return false;
1341 
1342 	if (!Match( TK_CLOSED_PARENTHESIS ))
1343 		return Error("do : too many parameters");
1344 
1345 	m_blockStream->WriteBlock( &block );
1346 
1347 	return true;
1348 }
1349 
1350 /*
1351 ===================================================================================================
1352 
1353   GetGet()
1354 
1355   Handles the get() function.
1356 
1357 ===================================================================================================
1358 */
1359 
1360 // get( TYPE, NAME );
1361 
GetGet(CBlock * block)1362 int CInterpreter::GetGet( CBlock *block )
1363 {
1364 	char	typeName[MAX_STRING_LENGTH];
1365 	int		type;
1366 
1367 	block->Write( ID_GET, (float) ID_GET );
1368 
1369 	if (!Match( TK_OPEN_PARENTHESIS ))
1370 		return Error("syntax error : '(' not found");
1371 
1372 	if ( GetType( (char *) typeName ) == false )
1373 		return false;
1374 
1375 	type = FindSymbol( typeName, m_typeKeywords);
1376 
1377 	switch ( type )
1378 	{
1379 	case TK_FLOAT:
1380 	case TK_INT:
1381 	case TK_VECTOR:
1382 	case TK_STRING:
1383 		block->Write( TK_FLOAT, (float) type );
1384 		break;
1385 
1386 	default:
1387 		return Error("unknown identifier %s", typeName );
1388 		break;
1389 	}
1390 
1391 	if ( GetString( block ) == false )
1392 		return false;
1393 
1394 	if (!Match( TK_CLOSED_PARENTHESIS ))
1395 		return Error("affect : too many parameters");
1396 
1397 	return true;
1398 }
1399 
1400 /*
1401 ===================================================================================================
1402 
1403   GetRandom()
1404 
1405   Handles the random() function.
1406 
1407 ===================================================================================================
1408 */
1409 
1410 // random( low, high );
1411 
GetRandom(CBlock * block)1412 int CInterpreter::GetRandom( CBlock *block )
1413 {
1414 	block->Write( ID_RANDOM, (float) ID_RANDOM );
1415 
1416 	if (!Match( TK_OPEN_PARENTHESIS ))
1417 		return Error("syntax error : '(' not found");
1418 
1419 	if ( GetFloat( block ) == false )
1420 		return false;
1421 
1422 	if ( GetFloat( block ) == false )
1423 		return false;
1424 
1425 	if (!Match( TK_CLOSED_PARENTHESIS ))
1426 		return Error("affect : too many parameters");
1427 
1428 	return true;
1429 }
1430 
1431 /*
1432 ===================================================================================================
1433 
1434   GetSound()
1435 
1436   Handles the sound() function.
1437 
1438 ===================================================================================================
1439 */
1440 
1441 // sound( NAME );
1442 
GetSound(void)1443 int CInterpreter::GetSound( void )
1444 {
1445 	CBlock	block;
1446 
1447 	block.Create( ID_SOUND );
1448 
1449 	if (!Match( TK_OPEN_PARENTHESIS ))
1450 		return Error("syntax error : '(' not found");
1451 
1452 	if ( GetIdentifier( &block ) == false )
1453 		return false;
1454 
1455 	if ( GetString( &block ) == false )
1456 		return false;
1457 
1458 	if (!Match( TK_CLOSED_PARENTHESIS ))
1459 		return Error("sound : too many parameters");
1460 
1461 	m_blockStream->WriteBlock( &block );
1462 
1463 	return true;
1464 }
1465 
1466 /*
1467 ===================================================================================================
1468 
1469   GetMove()
1470 
1471   Handles the move() function.
1472 
1473 ===================================================================================================
1474 */
1475 
1476 // move( ORIGIN, ANGLES, DURATION );
1477 
GetMove(void)1478 int CInterpreter::GetMove( void )
1479 {
1480 	CBlock	block;
1481 
1482 	block.Create( ID_MOVE );
1483 
1484 	if (!Match( TK_OPEN_PARENTHESIS ))
1485 		return Error("syntax error : '(' not found");
1486 
1487 	if ( GetVector( &block ) == false )
1488 		return false;
1489 
1490 	//Angles are optional
1491 	if ( LookAhead( TK_VECTOR_START ) || LookAhead( TK_IDENTIFIER ) )
1492 	{
1493 		if ( GetVector( &block ) == false )
1494 			return false;
1495 	}
1496 
1497 	if ( GetFloat( &block ) == false )
1498 		return false;
1499 
1500 	if (!Match( TK_CLOSED_PARENTHESIS ))
1501 		return Error("move : too many parameters");
1502 
1503 	m_blockStream->WriteBlock( &block );
1504 
1505 	return true;
1506 }
1507 
1508 /*
1509 ===================================================================================================
1510 
1511   GetRotate()
1512 
1513   Handles the rotate() function.
1514 
1515 ===================================================================================================
1516 */
1517 
1518 // move( ANGLES, DURATION );
1519 
GetRotate(void)1520 int CInterpreter::GetRotate( void )
1521 {
1522 	CBlock	block;
1523 
1524 	block.Create( ID_ROTATE );
1525 
1526 	if (!Match( TK_OPEN_PARENTHESIS ))
1527 		return Error("syntax error : '(' not found");
1528 
1529 	if ( GetVector( &block ) == false )
1530 		return false;
1531 
1532 	if ( GetFloat( &block ) == false )
1533 		return false;
1534 
1535 	if (!Match( TK_CLOSED_PARENTHESIS ))
1536 		return Error("move : too many parameters");
1537 
1538 	m_blockStream->WriteBlock( &block );
1539 
1540 	return true;
1541 }
1542 
1543 /*
1544 ===================================================================================================
1545 
1546   GetAffect()
1547 
1548   Handles the affect() function.
1549 
1550 ===================================================================================================
1551 */
1552 
1553 //FIXME:  This should be externally defined
1554 
GetAffect(void)1555 int CInterpreter::GetAffect( void )
1556 {
1557 	CBlock			block;
1558 	char			typeName[MAX_STRING_SIZE];
1559 	int				type;
1560 
1561 	block.Create( ID_AFFECT );
1562 
1563 	if (!Match( TK_OPEN_PARENTHESIS ))
1564 		return Error("syntax error : '(' not found");
1565 
1566 	if ( GetString( &block ) == false )
1567 		return false;
1568 
1569 	if (!LookAhead( TK_IDENTIFIER ))
1570 		return Error("syntax error : identifier not found");
1571 
1572 	if ( MatchGet() )
1573 		return Error("syntax error : illegal use of \"get\"");
1574 
1575 	if ( GetType( (char *) typeName ) == false )
1576 		return false;
1577 
1578 	type = FindSymbol( typeName, m_typeKeywords);
1579 
1580 	switch ( type )
1581 	{
1582 	case TYPE_INSERT:
1583 	case TYPE_FLUSH:
1584 
1585 		block.Write( TK_FLOAT, (float) type );
1586 		break;
1587 
1588 	default:
1589 		return Error("'%s': unknown affect type", typeName );
1590 		break;
1591 
1592 	}
1593 
1594 	if (!Match( TK_CLOSED_PARENTHESIS ))
1595 		return Error("affect : too many parameters");
1596 
1597 	if (!LookAhead( TK_BLOCK_START ))
1598 		return Error("syntax error : '{' not found");
1599 
1600 	m_blockStream->WriteBlock( &block );
1601 
1602 	return true;
1603 }
1604 
1605 /*
1606 ===================================================================================================
1607 
1608   GetWait()
1609 
1610   Handles the wait() function.
1611 
1612 ===================================================================================================
1613 */
1614 
1615 //FIXME:  This should be externally defined
1616 
GetWait(void)1617 int CInterpreter::GetWait( void )
1618 {
1619 	CBlock			block;
1620 
1621 	block.Create( ID_WAIT );
1622 
1623 	if (!Match( TK_OPEN_PARENTHESIS ))
1624 		return Error("syntax error : '(' not found");
1625 
1626 	if ( LookAhead( TK_STRING ) )
1627 	{
1628 		if ( GetString( &block ) == false )
1629 			return false;
1630 	}
1631 	else
1632 	{
1633 		if ( GetFloat( &block ) == false )
1634 			return false;
1635 	}
1636 
1637 	if (!Match( TK_CLOSED_PARENTHESIS ))
1638 		return Error("wait : too many parameters");
1639 
1640 	m_blockStream->WriteBlock( &block );
1641 
1642 	return true;
1643 }
1644 
1645 /*
1646 ===================================================================================================
1647 
1648   GetSet()
1649 
1650   Handles the set() function.
1651 
1652 ===================================================================================================
1653 */
1654 
1655 //FIXME:  This should be externally defined
1656 
GetSet(void)1657 int CInterpreter::GetSet( void )
1658 {
1659 	CBlock		block;
1660 
1661 	block.Create( ID_SET );
1662 
1663 	if (!Match( TK_OPEN_PARENTHESIS ))
1664 		return Error("syntax error : '(' not found");
1665 
1666 	if ( GetString( &block ) == false )
1667 		return false;
1668 
1669 	//Check for get placement
1670 	if ( MatchGet() )
1671 	{
1672 		if ( GetGet( &block ) == false )
1673 			return false;
1674 	}
1675 	else
1676 	{
1677 		switch( GetNextType() )
1678 		{
1679 		case TK_INT:
1680 
1681 			if ( GetInteger( &block ) == false )
1682 				return false;
1683 
1684 			break;
1685 
1686 		case TK_FLOAT:
1687 
1688 			if ( GetFloat( &block ) == false )
1689 				return false;
1690 
1691 			break;
1692 
1693 		case TK_STRING:
1694 
1695 			if ( GetString( &block ) == false )
1696 				return false;
1697 
1698 			break;
1699 
1700 		case TK_VECTOR_START:
1701 
1702 			if ( GetVector( &block ) == false )
1703 				return false;
1704 
1705 			break;
1706 
1707 		default:
1708 
1709 			if ( MatchTag() )
1710 			{
1711 				GetTag( &block );
1712 				break;
1713 			}
1714 
1715 			if ( MatchRandom() )
1716 			{
1717 				GetRandom( &block );
1718 				break;
1719 			}
1720 
1721 			return Error("unknown parameter type");
1722 			break;
1723 		}
1724 	}
1725 
1726 	if (!Match( TK_CLOSED_PARENTHESIS ))
1727 		return Error("set : too many parameters");
1728 
1729 	m_blockStream->WriteBlock( &block );
1730 
1731 	return true;
1732 }
1733 
1734 /*
1735 ===================================================================================================
1736 
1737   GetLoop()
1738 
1739   Handles the loop() function.
1740 
1741 ===================================================================================================
1742 */
1743 
GetLoop(void)1744 int CInterpreter::GetLoop( void )
1745 {
1746 	CBlock			block;
1747 
1748 	block.Create( ID_LOOP );
1749 
1750 	if (!Match( TK_OPEN_PARENTHESIS ))
1751 		return Error("syntax error : '(' not found");
1752 
1753 	if ( LookAhead( TK_CLOSED_PARENTHESIS ) )
1754 	{
1755 		//-1 denotes an infinite loop
1756 		block.Write( TK_FLOAT, (float) -1);
1757 	}
1758 	else
1759 	{
1760 		if ( GetInteger( &block ) == false )
1761 			return false;
1762 	}
1763 
1764 	if (!Match( TK_CLOSED_PARENTHESIS ))
1765 		return Error("GetLoop : too many parameters");
1766 
1767 	m_blockStream->WriteBlock( &block );
1768 
1769 	return true;
1770 }
1771 
1772 /*
1773 ===================================================================================================
1774 
1775   GetPrint()
1776 
1777   Handles the print() function.
1778 
1779 ===================================================================================================
1780 */
1781 
GetPrint(void)1782 int CInterpreter::GetPrint( void )
1783 {
1784 	CBlock			block;
1785 
1786 	block.Create( ID_PRINT );
1787 
1788 	if (!Match( TK_OPEN_PARENTHESIS ))
1789 		return Error("syntax error : '(' not found");
1790 
1791 	if ( GetString( &block ) == false )
1792 		return false;
1793 
1794 	if (!Match( TK_CLOSED_PARENTHESIS ))
1795 		return Error("print : too many parameters");
1796 
1797 	m_blockStream->WriteBlock( &block );
1798 
1799 	return true;
1800 }
1801 
1802 /*
1803 ===================================================================================================
1804 
1805   GetUse()
1806 
1807   Handles the use() function.
1808 
1809 ===================================================================================================
1810 */
1811 
GetUse(void)1812 int CInterpreter::GetUse( void )
1813 {
1814 	CBlock			block;
1815 
1816 	block.Create( ID_USE );
1817 
1818 	if (!Match( TK_OPEN_PARENTHESIS ))
1819 		return Error("syntax error : '(' not found");
1820 
1821 	if ( GetString( &block ) == false )
1822 		return false;
1823 
1824 	if (!Match( TK_CLOSED_PARENTHESIS ))
1825 		return Error("use : too many parameters");
1826 
1827 	m_blockStream->WriteBlock( &block );
1828 
1829 	return true;
1830 }
1831 
1832 /*
1833 ===================================================================================================
1834 
1835   GetFlush()
1836 
1837   Handles the flush() function.
1838 
1839 ===================================================================================================
1840 */
1841 
GetFlush(void)1842 int CInterpreter::GetFlush( void )
1843 {
1844 	CBlock	block;
1845 
1846 	block.Create( ID_FLUSH );
1847 
1848 	if (!Match( TK_OPEN_PARENTHESIS ))
1849 		return Error("syntax error : '(' not found");
1850 
1851 	if (!Match( TK_CLOSED_PARENTHESIS ))
1852 		return Error("flush : too many parameters");
1853 
1854 	m_blockStream->WriteBlock( &block );
1855 
1856 	return true;
1857 }
1858 
1859 /*
1860 ===================================================================================================
1861 
1862   GetRun()
1863 
1864   Handles the run() function.
1865 
1866 ===================================================================================================
1867 */
1868 
GetRun(void)1869 int CInterpreter::GetRun( void )
1870 {
1871 	CBlock	block;
1872 
1873 	block.Create( ID_RUN );
1874 
1875 	if (!Match( TK_OPEN_PARENTHESIS ))
1876 		return Error("syntax error : '(' not found");
1877 
1878 	if ( GetString( &block ) == false )
1879 		return false;
1880 
1881 	if (!Match( TK_CLOSED_PARENTHESIS ))
1882 		return Error("run : too many parameters");
1883 
1884 	m_blockStream->WriteBlock( &block );
1885 
1886 	return true;
1887 }
1888 
1889 /*
1890 ===================================================================================================
1891 
1892   GetKill()
1893 
1894   Handles the kill() function.
1895 
1896 ===================================================================================================
1897 */
1898 
GetKill(void)1899 int CInterpreter::GetKill( void )
1900 {
1901 	CBlock	block;
1902 
1903 	block.Create( ID_KILL );
1904 
1905 	if (!Match( TK_OPEN_PARENTHESIS ))
1906 		return Error("syntax error : '(' not found");
1907 
1908 	if ( GetString( &block ) == false )
1909 		return false;
1910 
1911 	if (!Match( TK_CLOSED_PARENTHESIS ))
1912 		return Error("kill : too many parameters");
1913 
1914 	m_blockStream->WriteBlock( &block );
1915 
1916 	return true;
1917 }
1918 
1919 /*
1920 ===================================================================================================
1921 
1922   GetRemove()
1923 
1924   Handles the remove() function.
1925 
1926 ===================================================================================================
1927 */
1928 
GetRemove(void)1929 int CInterpreter::GetRemove( void )
1930 {
1931 	CBlock	block;
1932 
1933 	block.Create( ID_REMOVE );
1934 
1935 	if (!Match( TK_OPEN_PARENTHESIS ))
1936 		return Error("syntax error : '(' not found");
1937 
1938 	if ( GetString( &block ) == false )
1939 		return false;
1940 
1941 	if (!Match( TK_CLOSED_PARENTHESIS ))
1942 		return Error("remove : too many parameters");
1943 
1944 	m_blockStream->WriteBlock( &block );
1945 
1946 	return true;
1947 }
1948 
1949 /*
1950 ===================================================================================================
1951 
1952   GetRem()
1953 
1954   Handles the rem() function.
1955 
1956 ===================================================================================================
1957 */
1958 
1959 // this is just so people can put comments in scripts in BehavEd and not have them lost as normal comments would be.
1960 //
GetRem(void)1961 int CInterpreter::GetRem( void )
1962 {
1963 	CBlock	block;
1964 
1965 	block.Create( ID_REM );
1966 
1967 	if (!Match( TK_OPEN_PARENTHESIS ))
1968 		return Error("syntax error : '(' not found");
1969 
1970 	// optional string?
1971 
1972 	if (Match( TK_CLOSED_PARENTHESIS ))
1973 		return true;
1974 
1975 	GetString( &block );
1976 
1977 	if (!Match( TK_CLOSED_PARENTHESIS ))
1978 		return Error("rem : function only takes 1 optional parameter");
1979 
1980 	return true;
1981 }
1982 
1983 
1984 /*
1985 ===================================================================================================
1986 
1987   GetCamera()
1988 
1989   Handles the camera() function.
1990 
1991 ===================================================================================================
1992 */
1993 
GetCamera(void)1994 int CInterpreter::GetCamera( void )
1995 {
1996 	CBlock	block;
1997 	char	typeName[MAX_STRING_SIZE];
1998 	int		type;
1999 
2000 	block.Create( ID_CAMERA );
2001 
2002 	if (!Match( TK_OPEN_PARENTHESIS ))
2003 		return Error("syntax error : '(' not found");
2004 
2005 	if ( GetType( (char *) typeName ) == false )
2006 		return false;
2007 
2008 	type = FindSymbol( typeName, m_typeKeywords);
2009 
2010 	switch ( type )
2011 	{
2012 	case TYPE_PAN:		//PAN  ( ANGLES, DURATION )
2013 
2014 		block.Write( TK_FLOAT, (float) type );
2015 
2016 		if ( GetVector( &block ) == false )
2017 			return false;
2018 
2019 		if ( GetVector( &block ) == false )
2020 			return false;
2021 
2022 		if ( GetFloat( &block ) == false )
2023 			return false;
2024 
2025 		break;
2026 
2027 	case TYPE_ZOOM:		//ZOOM ( FOV, DURATION )
2028 
2029 		block.Write( TK_FLOAT, (float) type );
2030 
2031 		if ( GetFloat( &block ) == false )
2032 			return false;
2033 
2034 		if ( GetFloat( &block ) == false )
2035 			return false;
2036 
2037 		break;
2038 
2039 	case TYPE_MOVE:		//MOVE ( ORIGIN, DURATION )
2040 
2041 		block.Write( TK_FLOAT, (float) type );
2042 
2043 		if ( GetVector( &block ) == false )
2044 			return false;
2045 
2046 		if ( GetFloat( &block ) == false )
2047 			return false;
2048 
2049 		break;
2050 
2051 	case TYPE_FADE:		//FADE ( SOURCE(R,G,B,A), DEST(R,G,B,A), DURATION )
2052 
2053 		block.Write( TK_FLOAT, (float) type );
2054 
2055 		//Source color
2056 		if ( GetVector( &block ) == false )
2057 			return false;
2058 		if ( GetFloat( &block ) == false )
2059 			return false;
2060 
2061 		//Dest color
2062 		if ( GetVector( &block ) == false )
2063 			return false;
2064 		if ( GetFloat( &block ) == false )
2065 			return false;
2066 
2067 		//Duration
2068 		if ( GetFloat( &block ) == false )
2069 			return false;
2070 
2071 		break;
2072 
2073 	case TYPE_PATH:		//PATH ( FILENAME )
2074 
2075 		block.Write( TK_FLOAT, (float) type );
2076 
2077 		//Filename
2078 		if ( GetString( &block ) == false )
2079 			return false;
2080 
2081 		break;
2082 
2083 	case TYPE_ENABLE:
2084 	case TYPE_DISABLE:
2085 
2086 		block.Write( TK_FLOAT, (float) type );
2087 		break;
2088 
2089 	case TYPE_SHAKE:	//SHAKE ( INTENSITY, DURATION )
2090 
2091 		block.Write( TK_FLOAT, (float) type );
2092 
2093 		//Intensity
2094 		if ( GetFloat( &block ) == false )
2095 			return false;
2096 
2097 		//Duration
2098 		if ( GetFloat( &block ) == false )
2099 			return false;
2100 
2101 		break;
2102 
2103 	case TYPE_ROLL:		//ROLL ( ANGLE, TIME )
2104 
2105 		block.Write( TK_FLOAT, (float) type );
2106 
2107 		//Angle
2108 		if ( GetFloat( &block ) == false )
2109 			return false;
2110 
2111 		//Time
2112 		if ( GetFloat( &block ) == false )
2113 			return false;
2114 
2115 		break;
2116 
2117 	case TYPE_TRACK:	//TRACK ( TARGETNAME, SPEED, INITLERP )
2118 
2119 		block.Write( TK_FLOAT, (float) type );
2120 
2121 		//Target name
2122 		if ( GetString( &block ) == false )
2123 			return false;
2124 
2125 		//Speed
2126 		if ( GetFloat( &block ) == false )
2127 			return false;
2128 
2129 		//Init lerp
2130 		if ( GetFloat( &block ) == false )
2131 			return false;
2132 
2133 		break;
2134 
2135 	case TYPE_FOLLOW:	//FOLLOW ( CAMERAGROUP, SPEED, INITLERP )
2136 
2137 		block.Write( TK_FLOAT, (float) type );
2138 
2139 		//Camera group
2140 		if ( GetString( &block ) == false )
2141 			return false;
2142 
2143 		//Speed
2144 		if ( GetFloat( &block ) == false )
2145 			return false;
2146 
2147 		//Init lerp
2148 		if ( GetFloat( &block ) == false )
2149 			return false;
2150 
2151 		break;
2152 
2153 	case TYPE_DISTANCE:	//DISTANCE ( DISTANCE, INITLERP )
2154 
2155 		block.Write( TK_FLOAT, (float) type );
2156 
2157 		//Distance
2158 		if ( GetFloat( &block ) == false )
2159 			return false;
2160 
2161 		//Init lerp
2162 		if ( GetFloat( &block ) == false )
2163 			return false;
2164 
2165 		break;
2166 	}
2167 
2168 	if (!Match( TK_CLOSED_PARENTHESIS ))
2169 		return Error("camera : too many parameters");
2170 
2171 	m_blockStream->WriteBlock( &block );
2172 
2173 	return true;
2174 }
2175 
2176 /*
2177 -------------------------
2178 GetDoWait
2179 -------------------------
2180 */
2181 
GetDoWait(void)2182 int CInterpreter::GetDoWait( void )
2183 {
2184 	CBlock	block;
2185 
2186 	//Write out the "do" portion
2187 	block.Create( ID_DO );
2188 
2189 	if (!Match( TK_OPEN_PARENTHESIS ))
2190 		return Error("syntax error : '(' not found");
2191 
2192 	if ( GetString( &block ) == false )
2193 		return false;
2194 
2195 	if (!Match( TK_CLOSED_PARENTHESIS ))
2196 		return Error("do : too many parameters");
2197 
2198 	//Write out the accompanying "wait"
2199 	char	*str = (char *) block.GetMemberData( 0 );
2200 
2201 	CBlock	block2;
2202 
2203 	block2.Create( ID_WAIT );
2204 
2205 	block2.Write( TK_STRING, (char *) str );
2206 
2207 	m_blockStream->WriteBlock( &block );
2208 	m_blockStream->WriteBlock( &block2 );
2209 
2210 	return true;
2211 }
2212 
2213 /*
2214 -------------------------
2215 GetSignal
2216 -------------------------
2217 */
2218 
GetSignal(void)2219 int CInterpreter::GetSignal( void )
2220 {
2221 	CBlock			block;
2222 
2223 	block.Create( ID_SIGNAL );
2224 
2225 	if (!Match( TK_OPEN_PARENTHESIS ))
2226 		return Error("syntax error : '(' not found");
2227 
2228 	if ( GetString( &block ) == false )
2229 		return false;
2230 
2231 	if (!Match( TK_CLOSED_PARENTHESIS ))
2232 		return Error("signal : too many parameters");
2233 
2234 	m_blockStream->WriteBlock( &block );
2235 
2236 	return true;
2237 }
2238 
2239 /*
2240 -------------------------
2241 GetSignal
2242 -------------------------
2243 */
2244 
GetWaitSignal(void)2245 int CInterpreter::GetWaitSignal( void )
2246 {
2247 	CBlock			block;
2248 
2249 	block.Create( ID_WAITSIGNAL );
2250 
2251 	if (!Match( TK_OPEN_PARENTHESIS ))
2252 		return Error("syntax error : '(' not found");
2253 
2254 	if ( GetString( &block ) == false )
2255 		return false;
2256 
2257 	if (!Match( TK_CLOSED_PARENTHESIS ))
2258 		return Error("waitsignal : too many parameters");
2259 
2260 	m_blockStream->WriteBlock( &block );
2261 
2262 	return true;
2263 }
2264 
2265 /*
2266 -------------------------
2267 GetPlay
2268 -------------------------
2269 */
2270 
GetPlay(void)2271 int CInterpreter::GetPlay( void )
2272 {
2273 	CBlock			block;
2274 
2275 	block.Create( ID_PLAY );
2276 
2277 	if (!Match( TK_OPEN_PARENTHESIS ))
2278 		return Error("syntax error : '(' not found");
2279 
2280 	if ( GetString( &block ) == false )
2281 		return false;
2282 
2283 	if ( GetString( &block ) == false )
2284 		return false;
2285 
2286 	if (!Match( TK_CLOSED_PARENTHESIS ))
2287 		return Error("waitsignal : too many parameters");
2288 
2289 	m_blockStream->WriteBlock( &block );
2290 
2291 	return true;
2292 }
2293 
2294 /*
2295 ===================================================================================================
2296 
2297   GetTag()
2298 
2299   Handles the tag() identifier.
2300 
2301 ===================================================================================================
2302 */
2303 
2304 //NOTENOTE: The tag's information is included as block members, not as a separate block.
2305 
GetTag(CBlock * block)2306 int CInterpreter::GetTag( CBlock *block )
2307 {
2308 	char	typeName[MAX_STRING_SIZE];
2309 	int		typeID;
2310 
2311 	//Mark as a tag
2312 	block->Write( ID_TAG, (float) ID_TAG );
2313 
2314 	if (!Match( TK_OPEN_PARENTHESIS ))
2315 		return Error("syntax error : '(' not found");
2316 
2317 	//Get the tag name
2318 	if ( GetString( block ) == false )
2319 		return false;
2320 
2321 	//Get the lookup ID
2322 	GetType( (char *) typeName );
2323 
2324 	typeID = FindSymbol( (char *) typeName, m_typeKeywords);
2325 
2326 	//Tags only contain origin and angles lookups
2327 	if ( (typeID != TYPE_ORIGIN) && (typeID != TYPE_ANGLES) )
2328 	{
2329 		return Error("syntax error : 'tag' : %s is not a valid look up identifier", typeName );
2330 	}
2331 
2332 	block->Write( TK_FLOAT, (float) typeID );
2333 
2334 	if (!Match( TK_CLOSED_PARENTHESIS ))
2335 		return Error("tag : too many parameters");
2336 
2337 	return true;
2338 }
2339 
2340 /*
2341 ===================================================================================================
2342 
2343 	Interpret function
2344 
2345 ===================================================================================================
2346 */
2347 
2348 // note new return type, this now returns the bad block number, else 0 for success.
2349 //
2350 //  I also return -ve block numbers for errors between blocks. Eg if you read 3 good blocks, then find an unexpected
2351 //		float in the script between blocks 3 & 4 then I return -3 to indicate the error is after that, but not block 4
2352 //
Interpret(CTokenizer * Tokenizer,CBlockStream * BlockStream,char * filename)2353 int	CInterpreter::Interpret( CTokenizer *Tokenizer, CBlockStream *BlockStream, char *filename )
2354 {
2355 	CBlock		block;
2356 	CToken		*token;
2357 	int			type, blockLevel = 0, parenthesisLevel = 0;
2358 
2359 	m_sCurrentFile	= filename;		// used during error reporting because you can't ask tokenizer for pushed streams
2360 
2361 	m_tokenizer		= Tokenizer;
2362 	m_blockStream	= BlockStream;
2363 
2364 	m_iCurrentLine = m_tokenizer->GetCurLine();
2365 	token = m_tokenizer->GetToEndOfLine(TK_STRING);
2366 	m_sCurrentLine = token->GetStringValue();
2367 	m_tokenizer->PutBackToken(token, false, NULL, true);
2368 
2369 	m_iBadCBlockNumber = 0;
2370 
2371 	while (m_tokenizer->GetRemainingSize() > 0)
2372 	{
2373 		token = m_tokenizer->GetToken( TKF_USES_EOL, 0 );
2374 		type = token->GetType();
2375 
2376 		switch ( type )
2377 		{
2378 		case TK_UNDEFINED:
2379 			token->Delete();
2380 			m_iBadCBlockNumber = -m_iBadCBlockNumber;
2381 			Error("%d : undefined token", type);
2382 			return m_iBadCBlockNumber;
2383 			break;
2384 
2385 		case TK_EOF:
2386 			break;
2387 
2388 		case TK_EOL:
2389 			// read the next line, then put it back
2390 			token->Delete();
2391 			m_iCurrentLine = m_tokenizer->GetCurLine();
2392 			token = m_tokenizer->GetToEndOfLine(TK_STRING);
2393 			m_sCurrentLine = token->GetStringValue();
2394 			m_tokenizer->PutBackToken(token, false, NULL, true);
2395 			break;
2396 
2397 		case TK_CHAR:
2398 		case TK_STRING:
2399 			token->Delete();
2400 			m_iBadCBlockNumber = -m_iBadCBlockNumber;
2401 			Error("syntax error : unexpected string");
2402 			return m_iBadCBlockNumber;
2403 			break;
2404 
2405 		case TK_INT:
2406 			token->Delete();
2407 			m_iBadCBlockNumber = -m_iBadCBlockNumber;
2408 			Error("syntax error : unexpected integer");
2409 			return m_iBadCBlockNumber;
2410 			break;
2411 
2412 		case TK_FLOAT:
2413 			token->Delete();
2414 			m_iBadCBlockNumber = -m_iBadCBlockNumber;
2415 			Error("syntax error : unexpected float");
2416 			return m_iBadCBlockNumber;
2417 			break;
2418 
2419 		case TK_IDENTIFIER:
2420 			m_iBadCBlockNumber++;
2421 			if (!GetID( (char *) token->GetStringValue() ))
2422 			{
2423 				token->Delete();
2424 				return m_iBadCBlockNumber;
2425 			}
2426 			token->Delete();
2427 			break;
2428 
2429 		case TK_BLOCK_START:
2430 			token->Delete();
2431 			if (parenthesisLevel)
2432 			{
2433 				m_iBadCBlockNumber = -m_iBadCBlockNumber;
2434 				Error("syntax error : brace inside parenthesis");
2435 				return m_iBadCBlockNumber;
2436 			}
2437 
2438 			blockLevel++;
2439 			break;
2440 
2441 		case TK_BLOCK_END:
2442 			token->Delete();
2443 			if (parenthesisLevel)
2444 			{
2445 				m_iBadCBlockNumber = -m_iBadCBlockNumber;
2446 				Error("syntax error : brace inside parenthesis");
2447 				return m_iBadCBlockNumber;
2448 			}
2449 
2450 			block.Create( ID_BLOCK_END );
2451 			m_blockStream->WriteBlock( &block );
2452 			block.Free();
2453 
2454 			blockLevel--;
2455 			break;
2456 
2457 		case TK_OPEN_PARENTHESIS:
2458 			token->Delete();
2459 			blockLevel++;
2460 			parenthesisLevel++;
2461 			break;
2462 
2463 		case TK_CLOSED_PARENTHESIS:
2464 			token->Delete();
2465 			blockLevel--;
2466 			parenthesisLevel--;
2467 
2468 			if (parenthesisLevel<0)
2469 			{
2470 				m_iBadCBlockNumber = -m_iBadCBlockNumber;
2471 				Error("syntax error : closed parenthesis with no opening match");
2472 				return m_iBadCBlockNumber;
2473 			}
2474 			break;
2475 
2476 		case TK_VECTOR_START:
2477 			token->Delete();
2478 			m_iBadCBlockNumber = -m_iBadCBlockNumber;
2479 			Error("syntax error : unexpected vector");
2480 			return m_iBadCBlockNumber;
2481 			break;
2482 
2483 		case TK_VECTOR_END:
2484 			token->Delete();
2485 			m_iBadCBlockNumber = -m_iBadCBlockNumber;
2486 			Error("syntax error : unexpected vector");
2487 			return m_iBadCBlockNumber;
2488 			break;
2489 		}
2490 	}
2491 
2492 	if ( blockLevel )
2493 	{
2494 		m_iBadCBlockNumber = -m_iBadCBlockNumber;
2495 		Error("error : open brace was not closed");
2496 		return m_iBadCBlockNumber;
2497 	}
2498 
2499 	if ( parenthesisLevel )
2500 	{
2501 		m_iBadCBlockNumber = -m_iBadCBlockNumber;
2502 		Error("error: open parenthesis");
2503 		return m_iBadCBlockNumber;
2504 	}
2505 
2506 	//Release all the variable information, because it's already been written out
2507 	FreeVars();
2508 
2509 	m_iBadCBlockNumber = 0;
2510 	return m_iBadCBlockNumber;	//true;
2511 }
2512 
2513