1 /* libsswf_as.h -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2009 */
2 #ifndef LIBSSWF_AS_H
3 #define	LIBSSWF_AS_H
4 
5 /*
6 
7 Copyright (c) 2005-2009 Made to Order Software Corp.
8 
9 Permission is hereby granted, free of charge, to any
10 person obtaining a copy of this software and
11 associated documentation files (the "Software"), to
12 deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify,
14 merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom
16 the Software is furnished to do so, subject to the
17 following conditions:
18 
19 The above copyright notice and this permission notice
20 shall be included in all copies or substantial
21 portions of the Software.
22 
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
24 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
25 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
26 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
27 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
29 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
31 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 SOFTWARE.
33 
34 */
35 
36 
37 
38 #include	<stdarg.h>
39 #include	<stdio.h>
40 #include	<stdlib.h>
41 #include	<time.h>
42 #ifdef _MSVC
43 #include	<io.h>
44 #include	<float.h>
45 #include	<direct.h>
46 #include	<limits.h>
47 #define	snprintf		_snprintf
48 #define	vsnprintf		_vsnprintf
mkdir(const char * filename)49 inline int			mkdir(const char *filename) { return _mkdir(filename); }
isnan(double nan)50 inline int			isnan(double nan) { return _isnan(nan); }
isinf(double d)51 inline int			isinf(double d)
52 				{
53 					int c;
54 					c = _fpclass(d);
55 					if(c == _FPCLASS_PINF) {
56 						return 1;
57 					}
58 					else if(c == _FPCLASS_NINF) {
59 						return -1;
60 					}
61 					return 0;
62 				}
63 typedef __int64			int64_t;
64 typedef unsigned __int64	uint64_t;
65 typedef __int32			int32_t;
66 typedef unsigned __int32	uint32_t;
strtoll(const char * str,char * end,int base)67 inline int64_t			strtoll(const char *str, char *end, int base)
68 				{
69 					return _atoi64(str);
70 				}
71 #else
72 #include	<inttypes.h>
73 #include	<unistd.h>
74 #include	<dirent.h>
75 #endif
76 #include	<string.h>
77 #include	<math.h>
78 #include	<limits.h>
79 #include	<sys/stat.h>
80 
81 #include	"sswf/libsswf-config.h"
82 
83 
84 #ifdef NEED_FP_NAN
85 #ifndef FP_NAN
86 static union __nan_value { uint32_t __l; float __d; } __nan_union = { 0x7fc00000UL };
87 #define FP_NAN    (__nan_union.__d)
88 #endif
89 #endif
90 #ifdef NEED_ISINF
91 #if IRIX
92 // my old version (6.5.7) doesn't have a correct isinf() function
93 // if you have a newer version and you are sure you have a proper
94 // version of isinf(), then feel free to remove this declaration
95 #include	<fp_class.h>
isinf(double d)96 static int isinf(double d)
97 {
98 	int c;
99 	c = fp_class_d(d);
100 	if(c == FP_POS_INF) {
101 		return 1;
102 	}
103 	else if(c == FP_NEG_INF) {
104 		return -1;
105 	}
106 	return 0;
107 }
108 #endif
109 #endif
110 
111 
112 
113 
114 namespace sswf
115 {
116 namespace as
117 {
118 
119 
120 
121 #if defined(_DEBUG) || defined(DEBUG)
122 #define	AS_ASSERT(test)	{ if(!(test)) printf("FATAL ERROR: AS_ASSERT(" #test ") is false in " __FILE__ " at line %d.\n", __LINE__), abort(); }
123 #else
124 #define	AS_ASSERT(test)
125 #endif
126 
127 
128 enum err_code_t
129 {
130 	AS_ERR_NONE = 0,
131 
132 	AS_ERR_ABSTRACT,
133 	AS_ERR_BAD_PRAGMA,
134 	AS_ERR_CANNOT_MATCH,
135 	AS_ERR_CANNOT_OVERLOAD,
136 	AS_ERR_CANNOT_OVERWRITE_CONST,
137 	AS_ERR_CASE_LABEL,
138 	AS_ERR_COLON_EXPECTED,
139 	AS_ERR_CURVLY_BRAKETS_EXPECTED,
140 	AS_ERR_DEFAULT_LABEL,
141 	AS_ERR_DIVIDE_BY_ZERO,
142 	AS_ERR_DUPLICATES,
143 	AS_ERR_DYNAMIC,
144 	AS_ERR_FINAL,
145 	AS_ERR_IMPORPER_STATEMENT,
146 	AS_ERR_INACCESSIBLE_STATEMENT,
147 	AS_ERR_INCOMPATIBLE,
148 	AS_ERR_INCOMPATIBLE_PRAGMA_ARGUMENT,
149 	AS_ERR_INSTANCE_EXPECTED,
150 	AS_ERR_INTERNAL_ERROR,
151 	AS_ERR_INTRINSIC,
152 	AS_ERR_INVALID_ARRAY_FUNCTION,
153 	AS_ERR_INVALID_ATTRIBUTES,
154 	AS_ERR_INVALID_CATCH,
155 	AS_ERR_INVALID_CLASS,
156 	AS_ERR_INVALID_CONDITIONAL,
157 	AS_ERR_INVALID_DEFINITION,
158 	AS_ERR_INVALID_DO,
159 	AS_ERR_INVALID_ENUM,
160 	AS_ERR_INVALID_EXPRESSION,
161 	AS_ERR_INVALID_FIELD,
162 	AS_ERR_INVALID_FIELD_NAME,
163 	AS_ERR_INVALID_FRAME,
164 	AS_ERR_INVALID_FUNCTION,
165 	AS_ERR_INVALID_GOTO,
166 	AS_ERR_INVALID_KEYWORD,
167 	AS_ERR_INVALID_LABEL,
168 	AS_ERR_INVALID_NAMESPACE,
169 	AS_ERR_INVALID_NODE,
170 	AS_ERR_INVALID_OPERATOR,
171 	AS_ERR_INVALID_PACKAGE_NAME,
172 	AS_ERR_INVALID_PARAMETERS,
173 	AS_ERR_INVALID_REST,
174 	AS_ERR_INVALID_RETURN_TYPE,
175 	AS_ERR_INVALID_SCOPE,
176 	AS_ERR_INVALID_TRY,
177 	AS_ERR_INVALID_TYPE,
178 	AS_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE,
179 	AS_ERR_INVALID_VARIABLE,
180 	AS_ERR_LABEL_NOT_FOUND,
181 	AS_ERR_LOOPING_REFERENCE,
182 	AS_ERR_MISMATCH_FUNC_VAR,
183 	AS_ERR_NEED_CONST,
184 	AS_ERR_NOT_FOUND,
185 	AS_ERR_NOT_SUPPORTED,
186 	AS_ERR_PARENTHESIS_EXPECTED,
187 	AS_ERR_PRAGMA_FAILED,
188 	AS_ERR_SEMICOLON_EXPECTED,
189 	AS_ERR_SQUARE_BRAKETS_EXPECTED,
190 	AS_ERR_STATIC,
191 	AS_ERR_UNKNOWN_ESCAPE_SEQUENCE,
192 	AS_ERR_UNKNOWN_OPERATOR,
193 	AS_ERR_UNTERMINTED_STRING,
194 	AS_ERR_UNEXPECTED_PUNCTUATION,
195 
196 	AS_ERR_max
197 };
198 
199 
200 
201 class Node;
202 
203 // the node type is often referenced as a token
204 enum node_t
205 {
206 	NODE_EOF = -1,		// when reading after the end of the file
207 	NODE_UNKNOWN = 0,	// node still uninitialized
208 
209 	// here are all the punctuation as themselves
210 	// (i.e. '<', '>', '=', '+', '-', etc.)
211 	NODE_ADD = '+',
212 	NODE_BITWISE_AND = '&',
213 	NODE_BITWISE_NOT = '~',
214 	NODE_ASSIGNMENT = '=',
215 	NODE_BITWISE_OR = '|',
216 	NODE_BITWISE_XOR = '^',
217 	NODE_CLOSE_CURVLY_BRACKET = '}',
218 	NODE_CLOSE_PARENTHESIS = ')',
219 	NODE_CLOSE_SQUARE_BRACKET = ']',
220 	NODE_COLON = ':',
221 	NODE_COMMA = ',',
222 	NODE_CONDITIONAL = '?',
223 	NODE_DIVIDE = '/',
224 	NODE_GREATER = '>',
225 	NODE_LESS = '<',
226 	NODE_LOGICAL_NOT = '!',
227 	NODE_MODULO = '%',
228 	NODE_MULTIPLY = '*',
229 	NODE_OPEN_CURVLY_BRACKET = '{',
230 	NODE_OPEN_PARENTHESIS = '(',
231 	NODE_OPEN_SQUARE_BRACKET = '[',
232 	NODE_MEMBER = '.',
233 	NODE_SEMICOLON = ';',
234 	NODE_SUBTRACT = '-',
235 
236 	// The following are composed tokens
237 	// (operators, keywords, strings, numbers...)
238 	NODE_other = 1000,
239 
240 	NODE_ARRAY,
241 	NODE_ARRAY_LITERAL,
242 	NODE_AS,
243 	NODE_ASSIGNMENT_ADD,
244 	NODE_ASSIGNMENT_BITWISE_AND,
245 	NODE_ASSIGNMENT_BITWISE_OR,
246 	NODE_ASSIGNMENT_BITWISE_XOR,
247 	NODE_ASSIGNMENT_DIVIDE,
248 	NODE_ASSIGNMENT_LOGICAL_AND,
249 	NODE_ASSIGNMENT_LOGICAL_OR,
250 	NODE_ASSIGNMENT_LOGICAL_XOR,
251 	NODE_ASSIGNMENT_MAXIMUM,
252 	NODE_ASSIGNMENT_MINIMUM,
253 	NODE_ASSIGNMENT_MODULO,
254 	NODE_ASSIGNMENT_MULTIPLY,
255 	NODE_ASSIGNMENT_POWER,
256 	NODE_ASSIGNMENT_ROTATE_LEFT,
257 	NODE_ASSIGNMENT_ROTATE_RIGHT,
258 	NODE_ASSIGNMENT_SHIFT_LEFT,
259 	NODE_ASSIGNMENT_SHIFT_RIGHT,
260 	NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED,
261 	NODE_ASSIGNMENT_SUBTRACT,
262 	NODE_ATTRIBUTES,
263 	NODE_AUTO,
264 	NODE_BREAK,
265 	NODE_CALL,
266 	NODE_CASE,
267 	NODE_CATCH,
268 	NODE_CLASS,
269 	NODE_CONST,
270 	NODE_CONTINUE,
271 	NODE_DEBUGGER,
272 	NODE_DECREMENT,
273 	NODE_DEFAULT,
274 	NODE_DELETE,
275 	NODE_DIRECTIVE_LIST,
276 	NODE_DO,
277 	NODE_ELSE,
278 	NODE_EMPTY,
279 	NODE_ENTRY,
280 	NODE_ENUM,
281 	NODE_EQUAL,
282 	NODE_EXCLUDE,
283 	NODE_EXTENDS,
284 	NODE_FALSE,
285 	NODE_FINALLY,
286 	NODE_FLOAT64,
287 	NODE_FOR,
288 	NODE_FOR_IN,
289 	NODE_FUNCTION,
290 	NODE_GOTO,
291 	NODE_GREATER_EQUAL,
292 	NODE_IDENTIFIER,
293 	NODE_IF,
294 	NODE_IMPLEMENTS,
295 	NODE_IMPORT,
296 	NODE_IN,
297 	NODE_INCLUDE,
298 	NODE_INCREMENT,
299 	NODE_INSTANCEOF,
300 	NODE_INT64,
301 	NODE_INTERFACE,
302 	NODE_IS,
303 	NODE_LABEL,
304 	NODE_LESS_EQUAL,
305 	NODE_LIST,
306 	NODE_LOGICAL_AND,
307 	NODE_LOGICAL_OR,
308 	NODE_LOGICAL_XOR,
309 	NODE_MATCH,
310 	NODE_MAXIMUM,
311 	NODE_MINIMUM,
312 	NODE_NAME,
313 	NODE_NAMESPACE,
314 	NODE_NEW,
315 	NODE_NOT_EQUAL,
316 	NODE_NULL,
317 	NODE_OBJECT_LITERAL,
318 	NODE_PACKAGE,
319 	NODE_PARAM,
320 	NODE_PARAMETERS,
321 	NODE_PARAM_MATCH,
322 	NODE_POST_DECREMENT,
323 	NODE_POST_INCREMENT,
324 	NODE_POWER,
325 	NODE_PRIVATE,
326 	NODE_PROGRAM,
327 	NODE_PUBLIC,
328 	NODE_RANGE,
329 	NODE_REGULAR_EXPRESSION,
330 	NODE_REST,
331 	NODE_RETURN,
332 	NODE_ROOT,
333 	NODE_ROTATE_LEFT,
334 	NODE_ROTATE_RIGHT,
335 	NODE_SCOPE,
336 	NODE_SET,
337 	NODE_SHIFT_LEFT,
338 	NODE_SHIFT_RIGHT,
339 	NODE_SHIFT_RIGHT_UNSIGNED,
340 	NODE_STRICTLY_EQUAL,
341 	NODE_STRICTLY_NOT_EQUAL,
342 	NODE_STRING,
343 	NODE_SUPER,
344 	NODE_SWITCH,
345 	NODE_THIS,
346 	NODE_THROW,
347 	NODE_TRUE,
348 	NODE_TRY,
349 	NODE_TYPE,
350 	NODE_TYPEOF,
351 	NODE_UNDEFINED,
352 	NODE_USE,
353 	NODE_VAR,
354 	NODE_VARIABLE,
355 	NODE_VAR_ATTRIBUTES,
356 	NODE_VIDENTIFIER,
357 	NODE_VOID,
358 	NODE_WHILE,
359 	NODE_WITH,
360 
361 	NODE_max,	// mark the limit
362 
363 	// used to extract the node type from some integers
364 	// (used by the SWITCH statement at time of writing)
365 	NODE_MASK = 0x0FFFF
366 };
367 
368 
369 
370 
371 
372 // some nodes use flags as defined below:
373 enum flags_t
374 {
375 	// NODE_CATCH
376 	NODE_CATCH_FLAG_TYPED = 0x01,
377 
378 	// NODE_DIRECTIVE_LIST
379 	NODE_DIRECTIVE_LIST_FLAG_NEW_VARIABLES = 0x01,
380 
381 	// NODE_FOR
382 	NODE_FOR_FLAG_FOREACH = 0x01,
383 
384 	// NODE_FUNCTION
385 	NODE_FUNCTION_FLAG_GETTER   = 0x01,
386 	NODE_FUNCTION_FLAG_SETTER   = 0x02,
387 	NODE_FUNCTION_FLAG_OUT      = 0x04,
388 	NODE_FUNCTION_FLAG_VOID     = 0x08,
389 	NODE_FUNCTION_FLAG_NEVER    = 0x10,
390 	NODE_FUNCTION_FLAG_NOPARAMS = 0x20,
391 	NODE_FUNCTION_FLAG_OPERATOR = 0x40,
392 
393 	// NODE_IDENTIFIER, NODE_VIDENTIFIER, NODE_STRING
394 	NODE_IDENTIFIER_FLAG_WITH  = 0x01,
395 	NODE_IDENTIFIER_FLAG_TYPED = 0x02,
396 
397 	// NODE_IMPORT
398 	NODE_IMPORT_FLAG_IMPLEMENTS = 0x01,
399 
400 	// NODE_PACKAGE
401 	NODE_PACKAGE_FLAG_FOUND_LABELS = 0x01,
402 	NODE_PACKAGE_FLAG_REFERENCED   = 0x02,
403 
404 	// NODE_PARAM_MATCH
405 	NODE_PARAM_MATCH_FLAG_UNPROTOTYPED = 0x01,
406 
407 	// NODE_PARAMETERS
408 	NODE_PARAMETERS_FLAG_CONST        = 0x001,
409 	NODE_PARAMETERS_FLAG_IN           = 0x002,
410 	NODE_PARAMETERS_FLAG_OUT          = 0x004,
411 	NODE_PARAMETERS_FLAG_NAMED        = 0x008,
412 	NODE_PARAMETERS_FLAG_REST         = 0x010,
413 	NODE_PARAMETERS_FLAG_UNCHECKED    = 0x020,
414 	NODE_PARAMETERS_FLAG_UNPROTOTYPED = 0x040,
415 	NODE_PARAMETERS_FLAG_REFERENCED   = 0x080,	// referenced from a parameter or a variable
416 	NODE_PARAMETERS_FLAG_PARAMREF     = 0x100,	// referenced from another parameter
417 	NODE_PARAMETERS_FLAG_CATCH        = 0x200,	// a parameter defined in a catch()
418 
419 	// NODE_SWITCH
420 	// WARNING: the switch() integer is also used for the operator node type
421 	NODE_SWITCH_FLAG_DEFAULT = 0x80000000,	// we found a 'default:' label in that switch
422 
423 	// NODE_VARIABLE (and NODE_VAR, NODE_PARAM)
424 	NODE_VAR_FLAG_CONST      = 0x01,
425 	NODE_VAR_FLAG_LOCAL      = 0x02,
426 	NODE_VAR_FLAG_MEMBER     = 0x04,
427 	NODE_VAR_FLAG_ATTRIBUTES = 0x08,
428 	NODE_VAR_FLAG_ENUM       = 0x02000000,	// there is a NODE_SET and it somehow needs to be copied
429 	NODE_VAR_FLAG_COMPILED   = 0x04000000,	// Expression() was called on the NODE_SET
430 	NODE_VAR_FLAG_INUSE      = 0x08000000,	// this variable was referenced
431 	NODE_VAR_FLAG_ATTRS      = 0x10000000,	// currently being read for attributes (to avoid loops)
432 	NODE_VAR_FLAG_DEFINED    = 0x20000000,	// was already parsed
433 	NODE_VAR_FLAG_DEFINING   = 0x40000000,	// currently defining, can't read
434 	NODE_VAR_FLAG_TOADD      = 0x80000000,	// to be added in the directive list
435 
436 	unused_flag	// enables commas on all flags...
437 };
438 
439 
440 // the following is a list of all the possible attributes in our system
441 // (note that the bits may change in the future)
442 	// member visibility
443 static const unsigned long	NODE_ATTR_PUBLIC	= 0x00000001;
444 static const unsigned long	NODE_ATTR_PRIVATE	= 0x00000002;
445 static const unsigned long	NODE_ATTR_PROTECTED	= 0x00000004;
446 static const unsigned long	NODE_ATTR_INTERNAL	= 0x00000008;
447 
448 	// function member type
449 static const unsigned long	NODE_ATTR_STATIC	= 0x00000010;
450 static const unsigned long	NODE_ATTR_ABSTRACT	= 0x00000020;
451 static const unsigned long	NODE_ATTR_VIRTUAL	= 0x00000040;
452 static const unsigned long	NODE_ATTR_ARRAY		= 0x00000080;
453 
454 	// function/variable is defined in your system (execution env.)
455 	// you won't find a body for these functions; the variables
456 	// will likely be read-only
457 static const unsigned long	NODE_ATTR_INTRINSIC	= 0x00000100;
458 
459 	// operator overload (function member)
460 	// Contructor -> another way to construct this type of objects
461 static const unsigned long	NODE_ATTR_CONSTRUCTOR	= 0x00000200;
462 
463 	// function & member constrains
464 // CONST is not currently available as an attribute (see flags instead)
465 //static const unsigned long	NODE_ATTR_CONST		= 0x00001000;
466 static const unsigned long	NODE_ATTR_FINAL		= 0x00002000;
467 static const unsigned long	NODE_ATTR_ENUMERABLE	= 0x00004000;
468 
469 	// conditional compilation
470 static const unsigned long	NODE_ATTR_TRUE		= 0x00010000;
471 static const unsigned long	NODE_ATTR_FALSE		= 0x00020000;
472 static const unsigned long	NODE_ATTR_UNUSED	= 0x00040000;	// if definition is used, error!
473 
474 	// class attribute (whether a class can be enlarged at run time)
475 static const unsigned long	NODE_ATTR_DYNAMIC	= 0x00100000;
476 
477 	// switch attributes
478 static const unsigned long	NODE_ATTR_FOREACH	= 0x01000000;
479 static const unsigned long	NODE_ATTR_NOBREAK	= 0x02000000;
480 static const unsigned long	NODE_ATTR_AUTOBREAK	= 0x04000000;
481 
482 // The following is to make sure we never define the attributes more
483 // than once.
484 static const unsigned long	NODE_ATTR_DEFINED	= 0x80000000;
485 
486 
487 
488 
489 class String
490 {
491 public:
492 			String(void);
493 			String(const String& string);
494 			String(const char *str);
495 			~String();
496 
497 	String&		operator = (const String& string);
498 
499 	// Assume ISO-8859-1 as input
500 	String&		operator = (const char *str);
501 
502 	bool		operator == (const String& string) const;
503 	bool		operator != (const String& string) const;
504 	bool		operator == (const char *str) const;
505 	bool		operator != (const char *str) const;
506 	String&		operator += (const String& string);
507 	// Assume ISO-8859-1 as input
508 	String&		operator += (const char *str);
509 
510 	int		Compare(const String& string) const;
511 	int		Compare(const char *string) const;
512 	bool		IsEmpty(void) const;
513 	void		Empty(void);
514 	long		GetLength(void) const;
515 	const long *	Get(void) const;	// NOT NULL TERMINATED
516 	void		Set(const long *str, long size);
517 	void		AppendChar(long c);
518 	String&		AppendStr(const long *str, long len);
519 	int		GetUTF8Length(void) const;
520 	int		ToUTF8(char *mb, size_t& mb_len) const;		// -1 on error, 0 otherwise
521 	int		FromUTF8(const char *mb, size_t mb_len);	// -1 on error, 0 otherwise
522 
523 	// WARNING: you need to 'delete [] str' of returned pointer
524 	char *		GetUTF8(void) const;
525 
526 private:
527 	long		f_len;
528 	long		f_max;
529 	long *		f_str;
530 };
531 
532 class Int64
533 {
534 public:
Int64(void)535 			Int64(void)
536 			{
537 				f_int = 0;
538 			}
Int64(const Int64 & src_int)539 			Int64(const Int64& src_int)
540 			{
541 				f_int = src_int.f_int;
542 			}
543 
544 	Int64&		operator = (const Int64& src_int)
545 			{
546 				f_int = src_int.f_int;
547 				return *this;
548 			}
549 
Get(void)550 	int64_t		Get(void) const
551 			{
552 				return f_int;
553 			}
Set(int64_t new_int)554 	void		Set(int64_t new_int)
555 			{
556 				f_int = new_int;
557 			}
558 
559 private:
560 	int64_t		f_int;
561 };
562 
563 
564 class Float64
565 {
566 public:
Float64(void)567 			Float64(void)
568 			{
569 				f_float = 0;
570 			}
Float64(const Float64 & src_float)571 			Float64(const Float64& src_float)
572 			{
573 				f_float = src_float.f_float;
574 			}
575 
576 	Float64&	operator = (const Float64& src_float)
577 			{
578 				f_float = src_float.f_float;
579 				return *this;
580 			}
581 
Get(void)582 	double		Get(void) const
583 			{
584 				return f_float;
585 			}
Set(double new_float)586 	void		Set(double new_float)
587 			{
588 				f_float = new_float;
589 			}
590 
591 private:
592 	double		f_float;
593 };
594 
595 
596 class UserData
597 {
598 public:
UserData(void)599 			UserData(void)
600 			{
601 				f_size = 0;
602 				f_data = 0;
603 			}
UserData(const UserData & src)604 			UserData(const UserData& src)
605 			{
606 				if(src.f_size > 0) {
607 					f_data = 0;
608 					New(src.f_size);
609 					memcpy(f_data, src.f_data, sizeof(int) * f_size);
610 				}
611 				else {
612 					f_size = 0;
613 					f_data = 0;
614 				}
615 			}
~UserData()616 			~UserData()
617 			{
618 				delete [] f_data;
619 			}
620 	UserData&	operator = (const UserData& src)
621 			{
622 				delete [] f_data;
623 				if(src.f_size > 0) {
624 					f_data = 0;
625 					New(src.f_size);
626 					memcpy(f_data, src.f_data, sizeof(int) * f_size);
627 				}
628 				else {
629 					f_size = 0;
630 					f_data = 0;
631 				}
632 				return *this;
633 			}
New(int size)634 	void		New(int size)
635 			{
636 				AS_ASSERT(size >= 0);
637 				delete [] f_data;
638 				if(size > 0) {
639 					f_data = new int[size];
640 					// by default we clear it
641 					memset(f_data, 0, sizeof(int) * size);
642 				}
643 				else {
644 					f_data = 0;
645 				}
646 				f_size = size;
647 			}
648 
Size(void)649 	int		Size(void) const
650 			{
651 				return f_size;
652 			}
Buffer(void)653 	int *		Buffer(void)
654 			{
655 				// we want to make sure that each call
656 				// to Buffer doesn't require this test
657 				AS_ASSERT(f_data != 0);
658 				return f_data;
659 			}
Buffer(void)660 	const int *	Buffer(void) const
661 			{
662 				// we want to make sure that each call
663 				// to Buffer doesn't require this test
664 				AS_ASSERT(f_data != 0);
665 				return f_data;
666 			}
667 
668 private:
669 	int		f_size;
670 	int *		f_data;
671 };
672 
673 
674 struct Data
675 {
DataData676 			Data(void)
677 			{
678 				f_type = NODE_UNKNOWN;
679 			}
ClearData680 	void		Clear(void)
681 			{
682 				f_type = NODE_UNKNOWN;
683 				f_int.Set(0);
684 				f_float.Set(0.0);
685 				f_str.Empty();
686 			}
687 	void		Display(FILE *out) const;
688 	const char *	GetTypeName(void) const;
689 
690 	// basic conversions
691 	bool		ToBoolean(void);
692 	bool		ToNumber(void);
693 	bool		ToString(void);
694 
695 	node_t		f_type;
696 	Int64		f_int;
697 	Float64		f_float;
698 	String		f_str;
699 	UserData	f_user_data;
700 };
701 
702 
703 
704 class Input;
705 class NodePtr
706 {
707 public:
708 	enum link_t {
709 		LINK_INSTANCE = 0,
710 		LINK_TYPE,
711 		LINK_ATTRIBUTES,	// this is the list of identifiers
712 
713 		LINK_max,
714 
715 		LINK_GOTO_EXIT = LINK_INSTANCE,
716 		LINK_GOTO_ENTER = LINK_TYPE,
717 
718 		LINK_end
719 	};
720 
NodePtr(void)721 				NodePtr(void)
722 				{
723 					f_node = 0;
724 				}
725 				NodePtr(const NodePtr& node);
726 				~NodePtr();
727 
728 	NodePtr&		operator = (const NodePtr& node);
729 
730 	void			SetInputInfo(const Input *input);
731 	void			CopyInputInfo(const NodePtr& node);
732 	long			GetPage(void) const;
733 	long			GetPageLine(void) const;
734 	long			GetParagraph(void) const;
735 	long			GetLine(void) const;
736 	const String&		GetFilename(void) const;
737 
738 	void			SetNode(const Node *node);
739 	void			SetNode(const NodePtr& node);
740 	void			CreateNode(node_t type = NODE_UNKNOWN);
741 	NodePtr&		Clone(const NodePtr& source);
742 	void			ClearNode(void);
HasNode(void)743 	bool			HasNode(void) const
744 				{
745 					return f_node != 0;
746 				}
SameAs(const NodePtr & node)747 	bool			SameAs(const NodePtr& node) const
748 				{
749 					return f_node == node.f_node;
750 				}
751 
752 	Data&			GetData(void) const;
753 	void			SetData(const Data& data);
754 	unsigned long		GetAttrs(void) const;	// see NODE_ATTR_...
755 	void			SetAttrs(unsigned long attrs);
756 	bool			HasSideEffects(void) const;
757 
758 	bool			IsLocked(void) const;
759 	void			Lock(void);
760 	void			Unlock(void);
761 	void			SetOffset(int offset);
762 	int			GetOffset(void) const;
763 	void			ReplaceWith(NodePtr& new_node);
764 	void			DeleteChild(int index);
765 	void			AddChild(NodePtr& child);
766 	void			InsertChild(int idx, NodePtr& child);
767 	void			SetChild(int index, NodePtr& child);
768 	int			GetChildCount(void) const;
769 	NodePtr&		GetChild(int index) const;
770 	void			SetParent(Node *parent);
771 	NodePtr&		GetParent(void);
772 	void			SetLink(link_t index, NodePtr& link);
773 	NodePtr&		GetLink(link_t index);
774 
775 	void			AddVariable(NodePtr& variable);
776 	int			GetVariableCount(void) const;
777 	NodePtr&		GetVariable(int index) const;
778 
779 	void			AddLabel(NodePtr& label);
780 	int			GetLabelCount(void) const;
781 	NodePtr&		GetLabel(int index) const;
782 	NodePtr&		FindLabel(const String& name) const;
783 
784 	void			Display(FILE *out, int indent = 0, NodePtr *parent = 0, char c = '-') const;
785 	void			DisplayPtr(FILE *out) const;
786 
787 	const char *		OperatorToString(void);
788 	node_t			StringToOperator(void);
789 
790 private:
791 	Node *			f_node;
792 };
793 
794 
795 class NodeLock
796 {
797 public:
NodeLock(NodePtr & node)798 				NodeLock(NodePtr& node)
799 				{
800 					f_node = node;
801 					if(f_node.HasNode()) {
802 						f_node.Lock();
803 					}
804 				}
~NodeLock()805 				~NodeLock()
806 				{
807 					if(f_node.HasNode()) {
808 						f_node.Unlock();
809 					}
810 				}
811 
812 	// premature unlocking
Unlock(void)813 	void			Unlock(void)
814 				{
815 					if(f_node.HasNode()) {
816 						f_node.Unlock();
817 						f_node.ClearNode();
818 					}
819 				}
820 
821 private:
822 	NodePtr			f_node;
823 };
824 
825 
826 
827 // ErrorStream handling object; you can derive from this
828 // class to redirect the errors to a different
829 // output (by default it goes to stderr).
830 // For that purpose, overload the Error() function.
831 // Within your function, use the IntGetFilename()
832 // and IntLine() functions to get the filename
833 // and line where the error occured.
834 //
835 // NOTE: The Input class derives from this class
836 //	 so it can handle the errors at once.
837 class ErrorStream
838 {
839 public:
840 				ErrorStream(void);
841 	virtual			~ErrorStream();
842 
843 	// by default, write in stderr; overload to send errors in
844 	// your console, etc.
845 	virtual void		Error(err_code_t err_code, const char *message);
846 
847 	// We call one of these functions which transform their
848 	// parameters (format + params) in a single easy to use
849 	// string sent to Error().
850 	// You don't overload these functions.
851 	void			ErrMsg(err_code_t err_code, const char *format, ...);
852 	void			ErrMsg(err_code_t err_code, const char *format, va_list ap);
853 
854 	// the following replaces String pointers by their UTF-8 const char *
855 	// whenever the format includes a %S -- this makes it work on all
856 	// systems without jungling with wide characters too much
857 	// also, we support %N for nodes in which case we print out the
858 	// filename and line of the given node
859 	void			ErrStrMsg(err_code_t err_code, const char *format, ...);
860 	void			ErrStrMsg(err_code_t err_code, const char *format, va_list ap);
861 
862 	// errors which should use the node information for the
863 	// filename & line number (instead of GetFilename() and Line())
864 	void			ErrMsg(err_code_t err_code, const NodePtr& node, const char *format, ...);
865 	void			ErrStrMsg(err_code_t err_code, const NodePtr& node, const char *format, ...);
866 
ErrCount(void)867 	long			ErrCount(void) const
868 				{
869 					return f_errcnt;
870 				}
871 
872 	virtual const char *	GetFilename(void) const;
873 	virtual long		Line(void) const;
874 
875 protected:
876 	const String&		IntGetFilename(void) const;
877 	long			IntLine(void) const;
878 
879 private:
880 	long			f_errcnt;
881 	NodePtr			f_node;
882 	mutable String		f_filename;	// IntGetFilename() must return a string...
883 };
884 
885 
886 
887 // I/O interface that YOU have to derive from so the
888 // parser can read the input data from somewhere
889 // You need to implement the GetC() function. You can
890 // also overload the Error() function so it prints
891 // the errors in a console of your choice.
892 // The GetFilename() is used by the default Error()
893 // function. It is used to generate an error like gcc.
894 // That function returns "asc" by default.
895 //
896 // Two examples are available below. One reads a USC-4
897 // formatted file and the other reads a string.
898 class Input : public ErrorStream
899 {
900 public:
901 	enum {
902 		AS_EOF = -1
903 	};
904 
905 				Input(void);
906 	virtual			~Input(void);
907 
908 	virtual long		GetC(void) = 0;
909 
910 	// return the size if known, -1 if unknown
911 	virtual long		GetSize(void) const;
912 
913 	void			ResetCounters(long line = 1)
914 				{
915 					f_page = 1;
916 					f_page_line = 1;
917 					f_paragraph = 1;
918 					f_line = line;
919 				}
920 
NewPage(void)921 	void			NewPage(void)
922 				{
923 					++f_page;
924 					f_page_line = 1;
925 					f_paragraph = 1;
926 				}
NewParagraph(void)927 	void			NewParagraph(void)
928 				{
929 					++f_paragraph;
930 				}
NewLine(void)931 	void			NewLine(void)
932 				{
933 					++f_page_line;
934 					++f_line;
935 				}
936 
Page(void)937 	long			Page(void) const
938 				{
939 					return f_page;
940 				}
PageLine(void)941 	long			PageLine(void) const
942 				{
943 					return f_page_line;
944 				}
Paragraph(void)945 	long			Paragraph(void) const
946 				{
947 					return f_paragraph;
948 				}
Line(void)949 	virtual long		Line(void) const
950 				{
951 					return f_line;
952 				}
953 
954 private:
955 	long			f_page;
956 	long			f_page_line;
957 	long			f_paragraph;
958 	long			f_line;
959 };
960 
961 
962 
963 
964 
965 
966 
967 class FileInput : public Input
968 {
969 public:
970 				FileInput(void);
971 	virtual			~FileInput();
972 	virtual const char *	GetFilename(void) const;
973 	bool			StandardInput(void);
974 	bool			Open(const char *filename);
975 	void			Close(void);
976 	virtual long		GetC(void);
977 	virtual long		GetSize(void) const;
978 	void			SetOriginalFilename(const char *original_filename);
979 
980 protected:
981 	char *			f_filename;
982 	char *			f_original_filename;
983 	FILE *			f_file;
984 	long			f_size;
985 };
986 
987 
988 class FileUCS32Input : public FileInput
989 {
990 public:
991 	virtual long		GetC(void);
992 };
993 
994 
995 
996 class StringInput : public Input
997 {
998 public:
999 				StringInput(const char *filename = 0);
1000 	virtual			~StringInput();
1001 
1002 	void			Set(const long *str, long size, unsigned long line);
1003 	long			GetSize(void) const;
1004 	virtual long		GetC(void);
1005 
1006 	virtual const char *	GetFilename(void) const;
1007 
1008 private:
1009 	int			f_pos;
1010 	String			f_str;
1011 	const char *		f_filename;
1012 };
1013 
1014 
1015 
1016 // In order to support different types of file systems, the
1017 // compiler supports a file retriever. Any time a file is
1018 // opened, it calls the retriever (if defined) and uses
1019 // that file. If no retriever was defined, the default is
1020 // used: attempt to open the file with fopen() or an equivalent.
1021 // In particular, this is used to handle the internal ASC files.
1022 class InputRetriever
1023 {
1024 public:
~InputRetriever()1025 	virtual			~InputRetriever() {}
1026 
1027 	virtual Input *		Retrieve(const char *filename) = 0;
1028 };
1029 
1030 
1031 
1032 // Options you can tweak so the compiler reacts in a different
1033 // manner in different situations (for instance, the \e escape
1034 // sequence can be used to generate the escape character whenever
1035 // the extended escape sequences is set to 1).
1036 enum option_t
1037 {
1038 	AS_OPTION_UNKNOWN = 0,
1039 	AS_OPTION_DEBUG,
1040 	AS_OPTION_DEBUG_LEXER,
1041 	AS_OPTION_EXTENDED_ESCAPE_SEQUENCES,
1042 	AS_OPTION_EXTENDED_OPERATORS,
1043 	AS_OPTION_EXTENDED_STATEMENTS,
1044 	AS_OPTION_OCTAL,
1045 	AS_OPTION_STRICT,
1046 	AS_OPTION_TRACE,
1047 	AS_OPTION_TRACE_TO_OBJECT,
1048 
1049 	AS_OPTION_max
1050 };
1051 
1052 class Options
1053 {
1054 public:
Options(void)1055 				Options(void)
1056 				{
1057 					memset(f_options, 0, sizeof(f_options));
1058 
1059 					// we're always in strict mode
1060 					f_options[AS_OPTION_STRICT] = 1;
1061 				}
1062 
SetOption(option_t option,long value)1063 	void			SetOption(option_t option, long value)
1064 				{
1065 					AS_ASSERT(option < AS_OPTION_max);
1066 
1067 					// we're always in strict mode
1068 					if(option == AS_OPTION_STRICT) {
1069 						value = 1;
1070 					}
1071 					f_options[option] = value;
1072 				}
GetOption(option_t option)1073 	long			GetOption(option_t option)
1074 				{
1075 					AS_ASSERT(option < AS_OPTION_max);
1076 
1077 					return f_options[option];
1078 				}
1079 
1080 private:
1081 	long			f_options[AS_OPTION_max];
1082 };
1083 
1084 
1085 
1086 
1087 // The parser class is mostly hidden to you.
1088 // You can't derive from it. You call the CreateParser() to use it.
1089 // Once you are finished with the parser, delete it.
1090 // Note that deleting the parser doesn't delete the nodes and thus
1091 // you can work with the tree even after you deleted the parser.
1092 //
1093 // You use like this:
1094 //
1095 //	using namespace sswf::as;
1096 //	MyInput input;
1097 //	Parser *parser = Parser::CreateParser();
1098 //	parser->SetInput(input);
1099 //	// it is optional to set the options
1100 //	parser->SetOptions(options);
1101 //	NodePtr root = parser->Parse();
1102 //
1103 // NOTE: the input and options are NOT copied, a pointer to these
1104 // object is saved in the parser. Delete the Parser() before you
1105 // delete them. Also, this means you can change the options as the
1106 // parsing goes on (i.e. usually this happens in Input::Error().).
1107 class Parser
1108 {
1109 public:
~Parser()1110 	virtual			~Parser() {}
1111 
1112 	static Parser *		CreateParser(void);
1113 	static const char *	Version(void);
1114 
1115 	virtual void		SetInput(Input& input) = 0;
1116 	virtual void		SetOptions(Options& options) = 0;
1117 	virtual NodePtr&	Parse(void) = 0;
1118 };
1119 
1120 
1121 // Once a program was parsed, you need to compile it. This
1122 // mainly means resolving the references (i.e. identifiers)
1123 // which may generate the loading of libraries specified in
1124 // import instructions (note that some import instructions
1125 // are automatic for the global and native environments.)
1126 //
1127 // The code, after you ran the parser looks like this:
1128 //
1129 //	Compiler *compiler = Compiler::CreateCompiler();
1130 //	// this is the same options as for the parser
1131 //	compiler->SetOptions(options);
1132 //	error_count = compiler->Compile(root);
1133 //
1134 // The Compile() function returns the number of errors
1135 // encountered while compiling. The root parameter is
1136 // what was returned by the Parse() function of the
1137 // Parser object.
1138 class Compiler
1139 {
1140 public:
~Compiler()1141 	virtual			~Compiler() {}
1142 
1143 	// NOTE: to be thread safe, this call should be
1144 	//	 protected so only one thread can call it at
1145 	//	 a time (or create a compiler before any thread)
1146 	static Compiler *	CreateCompiler(InputRetriever *retriever);
1147 	static const char *	Version(void);
1148 
1149 	virtual InputRetriever *SetInputRetriever(InputRetriever *retriever) = 0;
1150 	virtual void		SetErrorStream(ErrorStream& error_stream) = 0;
1151 	virtual void		SetOptions(Options& options) = 0;
1152 	virtual int		Compile(NodePtr& tree) = 0;
1153 };
1154 
1155 
1156 
1157 
1158 // Finally, once the program was parsed and then compiled
1159 // one usually wants to optimize it. This means removing
1160 // all the possible expressions and statements which can
1161 // be removed to make the code more efficient. The
1162 // optimizations applied can be tweaked using the options.
1163 //
1164 // The code, after you ran the compiler looks like this:
1165 //
1166 //	Optimizer *optimizer = Optimizer::CreateOptimizer();
1167 //	// this is the same options as for the parser
1168 //	optimize->SetOptions(options);
1169 //	optimize->Optimize(root);
1170 //
1171 // The Optimize() function goes through the list of
1172 // nodes defined in the root parameter and it tries to
1173 // remove all possible expressions and functions which
1174 // will have no effect in the final output (certain things,
1175 // such as x + 0, are not removed since it has an effect!).
1176 // The root parameter is what was returned by the Parse()
1177 // function of the Parser object.
1178 //
1179 // Note that it is expected that you first Compile()
1180 // the nodes, but it is possible to call the optimizer
1181 // without first running any compilation.
1182 class Optimizer
1183 {
1184 public:
~Optimizer()1185 	virtual			~Optimizer() {}
1186 
1187 	static Optimizer *	CreateOptimizer(void);
1188 	static const char *	Version(void);
1189 
1190 	virtual void		SetErrorStream(ErrorStream& error_stream) = 0;
1191 	virtual void		SetOptions(Options& options) = 0;
1192 	virtual int		Optimize(NodePtr& tree) = 0;
1193 	virtual	int		GetLastLabel(void) const = 0;
1194 	virtual void		SetFirstLabel(int label) = 0;
1195 };
1196 
1197 
1198 
1199 
1200 // Now you're on your own! You have a perfect tree
1201 // and you can generate valid code from it...
1202 //
1203 // Each node has a Data structure, a set of children
1204 // node and a set of attribute flags (WARNING:
1205 // the attributes are computed by the compiler; you
1206 // need to call Compile() with a compiler to get
1207 // the attributes).
1208 
1209 
1210 
1211 
1212 };	// namespace as
1213 };	// namespace sswf
1214 #endif			/* #ifndef LIBSSWF_AS_H */
1215