/* sswf.h V1.0 -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2009 */
#ifndef SSWF_H
#define	SSWF_H

/*

Copyright (c) 2002-2009 Made to Order Software Corp.

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/


#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<stdarg.h>
#include	<stddef.h>
#include	<limits.h>
#include	<ctype.h>
#include	<math.h>
#include	<errno.h>

#ifndef __MINGW32__
#ifndef _MSVC
#include	<sys/time.h>
#include	<sys/resource.h>
#endif
#endif


#include	"sswf/libsswf-config.h"


#ifdef __cplusplus
extern "C" {
#endif



#ifndef	M_PI
#define	M_PI		3.14159265358979323846
#endif

extern	int		yylex(void);
extern	FILE *		yyin;
extern	int		yyparse(void *result);



#if DEBUG
extern	void	assert(int cond, const char *format, ...)
#ifdef __GNUC__
	__attribute__ ((format (printf, 2, 3)))
#endif
			;
#else
#ifdef SSWF_NEED_ASSERT
static	void	assert(int cond, const char *format, ...) {}
#endif
#endif


#ifdef _MSVC
#ifndef	strcasecmp
#define	strcasecmp	stricmp
#endif
#ifndef	strncasecmp
#define	strncasecmp	strnicmp
#endif
#ifndef	rint
#define	rint(x)		((double) (long) floor(x + 0.5))
#endif
#ifndef	snprintf
#define	snprintf	_snprintf
#endif
#endif



#define	ADJUST_STRINGS		1



enum node_type_t {
	NODE_TYPE_UNKNOWN = 0,
		NODE_SUBTYPE_UNKNOWN,
	NODE_TYPE_IDENTIFIER,
	NODE_TYPE_INTEGER,
	NODE_TYPE_FLOAT,
	NODE_TYPE_RANGE_INTEGER,
	NODE_TYPE_RANGE_FLOAT,
	NODE_TYPE_STRING,
	NODE_TYPE_DATA,			/* an object data structure - uses object sub-types */
		NODE_SUBTYPE_DEFINITION,		/* to seperate multiple definitions within the same list */
	NODE_TYPE_DEFINITION,
	NODE_TYPE_OPERATOR,
		NODE_SUBTYPE_ADD,
		NODE_SUBTYPE_AND,
		NODE_SUBTYPE_DIVIDE,
		NODE_SUBTYPE_EQUAL,
		NODE_SUBTYPE_EXPAND,
		NODE_SUBTYPE_FIELD,
		NODE_SUBTYPE_FUNCTION,
		NODE_SUBTYPE_GREATER,
		NODE_SUBTYPE_GREATER_EQUAL,
		NODE_SUBTYPE_GROUP,
		NODE_SUBTYPE_IDENTITY,
		NODE_SUBTYPE_LESS,
		NODE_SUBTYPE_LESS_EQUAL,
		NODE_SUBTYPE_LET,
		NODE_SUBTYPE_LOGICAL_AND,
		NODE_SUBTYPE_LOGICAL_NOT,
		NODE_SUBTYPE_LOGICAL_OR,
		NODE_SUBTYPE_LOGICAL_XOR,
		NODE_SUBTYPE_MAXIMUM,
		NODE_SUBTYPE_MINIMUM,
		NODE_SUBTYPE_MODULO,
		NODE_SUBTYPE_MULTIPLY,
		NODE_SUBTYPE_NEGATE,
		NODE_SUBTYPE_NOT,
		NODE_SUBTYPE_NOT_EQUAL,
		NODE_SUBTYPE_OR,
		NODE_SUBTYPE_POWER,
		NODE_SUBTYPE_RANGE,
		NODE_SUBTYPE_ROTATE_LEFT,
		NODE_SUBTYPE_ROTATE_RIGHT,
		NODE_SUBTYPE_SELECT,
		NODE_SUBTYPE_SHIFT_LEFT,
		NODE_SUBTYPE_SHIFT_RIGHT,
		NODE_SUBTYPE_SHIFT_RIGHT_UNSIGNED,
		NODE_SUBTYPE_SUBSCRIPT,
		NODE_SUBTYPE_SUBTRACT,
		NODE_SUBTYPE_XOR,
	NODE_TYPE_UNIT,
		NODE_SUBTYPE_BC,		/* byte 0 to 255 (color) */
		NODE_SUBTYPE_CM,		/* centimeter (size) */
		NODE_SUBTYPE_DEG,		/* degree 0 to 360 (angle) */
		NODE_SUBTYPE_FC,		/* float 0.0 to 1.0 (color) */
		NODE_SUBTYPE_FPF,		/* frames per field?! (speed) */
		NODE_SUBTYPE_FPS,		/* frame per seconds (speed) */
		NODE_SUBTYPE_FRM,		/* frame per minute (speed) */
		NODE_SUBTYPE_GRAD,		/* grade 0 to 400 (angle) */
		NODE_SUBTYPE_IN,		/* inch (size) */
		NODE_SUBTYPE_MIN,		/* minute (time) */
		NODE_SUBTYPE_PR,		/* percent 0 to 100 (ratio) */
		NODE_SUBTYPE_PX,		/* pixels (size) */
		NODE_SUBTYPE_RAD,		/* radian (angle) */
		NODE_SUBTYPE_RT,		/* scale 0.0 to 1.0 (ratio) */
		NODE_SUBTYPE_SEC,		/* second (time) */
		NODE_SUBTYPE_TW,		/* twips (size) */
		NODE_SUBTYPE_OTHER,		/* boolean, version #, etc. */
	NODE_TYPE_OBJECT,
		NODE_SUBTYPE_ACTION,
		NODE_SUBTYPE_ACTION_SCRIPT,
		NODE_SUBTYPE_BLOCK,
		NODE_SUBTYPE_BUTTON,
		NODE_SUBTYPE_CATCH,
		NODE_SUBTYPE_COLOR,
		NODE_SUBTYPE_COLOR_TRANSFORM,
		NODE_SUBTYPE_DO_ACTION,
		NODE_SUBTYPE_EDGES,
		NODE_SUBTYPE_EDIT_TEXT,
		NODE_SUBTYPE_END,
		NODE_SUBTYPE_ENVELOPE,
		NODE_SUBTYPE_EXPORT,
		NODE_SUBTYPE_FILL_STYLE,
		NODE_SUBTYPE_FINALLY,
		NODE_SUBTYPE_FONT,
		NODE_SUBTYPE_FOR,
		NODE_SUBTYPE_FRAME_LABEL,
		/* NODE_SUBTYPE_FUNCTION -- already defined in the operators, we can still reuse it for objects! */
		NODE_SUBTYPE_GLYPH,
		NODE_SUBTYPE_GRADIENT,
		NODE_SUBTYPE_IF,
		NODE_SUBTYPE_IMAGE,
		NODE_SUBTYPE_IMPORT,
		NODE_SUBTYPE_LABEL,
		NODE_SUBTYPE_LINE_STYLE,
		NODE_SUBTYPE_LIST,
		NODE_SUBTYPE_MATRIX,
		NODE_SUBTYPE_METADATA,
		NODE_SUBTYPE_ON_EVENT,
		NODE_SUBTYPE_PLACE_OBJECT,
		NODE_SUBTYPE_POINTS,
		NODE_SUBTYPE_RECT,
		NODE_SUBTYPE_REFERENCE,
		NODE_SUBTYPE_REMOVE,
		NODE_SUBTYPE_REMOVE_ALL,
		NODE_SUBTYPE_REPLACE_OBJECT,
		NODE_SUBTYPE_SCENE_FRAME_DATA,
		NODE_SUBTYPE_SCRIPT_LIMITS,
		NODE_SUBTYPE_SEQUENCE,
		NODE_SUBTYPE_SET_BACKGROUND_COLOR,
		NODE_SUBTYPE_SET_TAB_INDEX,
		NODE_SUBTYPE_SHAPE,
		NODE_SUBTYPE_SHOW_FRAME,
		NODE_SUBTYPE_SOUND,
		NODE_SUBTYPE_SOUND_INFO,
		NODE_SUBTYPE_SPRITE,
		NODE_SUBTYPE_STATE,
		NODE_SUBTYPE_TEXT,
		NODE_SUBTYPE_TEXT_SETUP,
		NODE_SUBTYPE_TRY,
		NODE_SUBTYPE_VARIABLE,
		NODE_SUBTYPE_WITH,

	NODE_TYPE_max
};
struct node_type_names_t {
#if DEBUG
	enum node_type_t	type;
#endif
	const char *		name;
};
extern	const struct node_type_names_t	node_type_names[NODE_TYPE_max];



/* different types of units */
enum node_unit_t {
	NODE_UNIT_UNKNOWN = -1,
	NODE_UNIT_ANGLE = 0,
	NODE_UNIT_BOOLEAN,
	NODE_UNIT_COLOR,
	NODE_UNIT_RATIO,
	NODE_UNIT_SIZE,
	NODE_UNIT_SPEED,
	NODE_UNIT_TIME,

	NODE_UNIT_MAX
};



/*
 * The data structures are specific to each object
 * some objects, like the LIST, SEQUENCE, etc. will
 * keep information about each included object.
 *
 * A referenced object is not considered a child object
 * and therefore it can't be referenced as the child of
 * another object later.
 */
#define	SSWF_MEM_ALIGN_SIZE	sizeof(double)		/* must be a power of 2 -- minimum memory alignment for any structure */
#define	SSWF_MEM_ALIGN(size)	(((size) + SSWF_MEM_ALIGN_SIZE - 1) & (- (long) SSWF_MEM_ALIGN_SIZE))

/* VARIABLE SIZE */
#ifdef _MSVC
#pragma	warning(disable: 4200)
#endif
struct data_common_t {
	size_t			length;		/* total length of this data block (to ease duplication) */
	enum node_type_t	type;		/* the object sub_type or NODE_TYPE_STRING */
	const char *		label;		/* at times an object is named using the label {} instruction */
	struct node_t *		node;		/* the node which generated this object */
	long			pad;		/* unused at this time - ensures that the sizeof(data_common_t) is a multiple of 8 */
	size_t			name_len;	/* length of the name rounded up to 8 bytes to be able to skip it at once */
	char			name[0];	/* variable size null terminated string representing the name of this object */
};
#ifdef _MSVC
#pragma	warning(default: 4200)
#endif

/* to avoid typing all the cast each time... */
#define	dc_color(d)		((struct data_color_t *) dc_data(d))
#define	dc_color_transform(d)	((struct data_color_transform_t *) dc_data(d))
#define	dc_common(d)		((struct data_common_t *) dc_data(d))
#define	dc_data(d)		((char *) ((d) + 1) + (d)->name_len)
#define	dc_edges(d)		((struct data_edges_t *) dc_data(d))
#define	dc_gradient(d)		((struct data_gradient_t *) dc_data(d))
#define	dc_image(d)		((struct data_image_t *) dc_data(d))
#define	dc_item(l, i)		((struct data_common_t *) ((char *) (l) + labs((l)->offset[i])))
#define	dc_item_color(l, i)	((struct data_color_t *) ((char *) (l) + labs((l)->offset[i])))
#define	dc_item_edges(l, i)	((struct data_edges_t *) ((char *) (l) + labs((l)->offset[i])))
#define	dc_item_points(l, i)	((struct data_points_t *) ((char *) (l) + labs((l)->offset[i])))
#define	dc_line_style(d)	((struct data_line_style_t *) dc_data(d))
#define	dc_list(d)		((struct data_list_t *) dc_data(d))
#define	dc_matrix(d)		((struct data_matrix_t *) dc_data(d))
#define	dc_place_object(d)	((struct data_place_object_t *) dc_data(d))
#define	dc_points(d)		((struct data_points_t *) dc_data(d))
#define	dc_rect(d)		((struct data_rect_t *) dc_data(d))
#define	dc_remove(d)		((struct data_remove_t *) dc_data(d))
#define	dc_move(d)		((struct data_move_t *) dc_data(d))
#define	dc_script_limits(d)	((struct data_script_limits_t *) dc_data(d))
#define	dc_show_frame(d)	((struct data_show_frame_t *) dc_data(d))
#define	dc_set_tab_index(d)	((struct data_set_tab_index_t *) dc_data(d))
#define	dc_text_setup(d)	((struct data_text_setup_t *) dc_data(d))



/* VARIABLE SIZE -- structure used for BLOCK, EDGES, FILL STYLE, GRADIENT, LIST, SEQUENCE, SHAPE, SPRITE */
#ifdef _MSVC
#pragma	warning(disable: 4200)
#endif
struct data_list_t {
	size_t			count;		/* number of items in this list */
	long			offset[0];	/* an array of offsets to access any object quickly (especially to search a named object) */
						/* NOTE: the offset can be negative! */
	/* char data[count][length]; -- an array of data entries each with a variable length */
};
#ifdef _MSVC
#pragma	warning(default: 4200)
#endif

/*
 * Shapes use the same structure as the LIST.
 * The MOVE is defined with a MATRIX (only the tx and ty fields are used)
 * The other objects are inserted as objects of their own type (as expected in other words!).
 */





/* structure used for BUTTON, BUTTON2 */
struct data_button_flag_t {		// button menu flag
	double			menu;
};

struct data_button_t {			// button states
	double			state;
	double			layer;
};


/* structure used for COLOR, SET BACKGROUND COLOR */
struct data_color_t {
	double			red;
	double			green;
	double			blue;
	double			alpha;
};


/* structure used for COLOR TRANSFORM */
struct data_color_transform_t {
	double			add_red;
	double			add_green;
	double			add_blue;
	double			add_alpha;
	double			mult_red;
	double			mult_green;
	double			mult_blue;
	double			mult_alpha;
};

/* VARIABLE SIZE -- structure used for EDGES (can be repeated, starts with a data_list_t) */
struct data_edges_t {
	long			type;		/* closure or not */
	double			delta_x1;
	double			delta_y1;
	double			delta_x2;	/* if NAN, only (x, y) defined thus we have a LINE edge */
	double			delta_y2;	/* if NAN, only (x, y) defined thus we have a LINE edge */
};

#define	EDGE_TYPE_INTERMEDIATE		0
#define	EDGE_TYPE_CLOSE			1	/* back to the starting point */
#define	EDGE_TYPE_ROTATE		2



/* FIXED SIZE -- structure used for IMPORT */
struct data_import_t {
	long			type;
};

#define	IMPORT_TYPE_NAME	0		/* name of the object to import */
#define	IMPORT_TYPE_URL		1		/* URL of the source movie */
#define	IMPORT_TYPE_FILENAME	2		/* name of the file including the exported items */


/* FIXED SIZE -- structure used for METADATA */
struct data_metadata_t {
	long			type;
};

#define	METADATA_TYPE_FILENAME		0	/* name of the XML file containing the metadata */
#define	METADATA_TYPE_METADATA		1	/* the XML metadata itself */
/* for auto-generated XML */
#define	METADATA_TYPE_TITLE		2	/* title */
#define	METADATA_TYPE_DESCRIPTION	3	/* description */
#define	METADATA_TYPE_AUTHOR		4	/* author/creator/investor... */
#define	METADATA_TYPE_PUBLISHER		5	/* publisher */
#define	METADATA_TYPE_COPYRIGHT		6	/* copyright or license information */
#define	METADATA_TYPE_URL		7	/* a URL in link with this animation */


/* VARIABLE SIZE -- structure used for POINTS (can be repeated, starts with a data_list_t) */
struct data_points_t {
	long			type;		/* closure or not */
	double			x1;
	double			y1;
	double			x2;	/* if NAN, only (x, y) defined thus we have a LINE edge */
	double			y2;	/* if NAN, only (x, y) defined thus we have a LINE edge */
};

/* whether we are defining the FILL0 or FILL1 */
struct data_fill_style_t {
	long			select;		/* 0 - fill0, 1 - fill1 */
};

/* VARIABLE SIZE -- structure used for GRADIENT (is repeated 2 to 15 times with a data_list_t) */
struct data_gradient_t {
	long			type;		/* POSITION or FOCAL */
	double			position;	/* 0.0 to 1.0 */
	double			to_pos;		/* for morph only; NAN otherwise */
};

#define	GRADIENT_TYPE_POSITION	1
#define	GRADIENT_TYPE_FOCAL	2

/* the ascent, descent and leading height font definition */
struct data_font_t {
	long			type;		/* LAYOUT */
	double			ascent;
	double			descent;
	double			leading_height;
	double			advance;
	double			space;
};

struct data_font_advance_t {
	long			type;		/* ADVANCE (only) */
	double			x;		/* advance of that many pixels to next char */
};

struct data_font_kerning_t {
	long			type;		/* KERNING */
	double			x;		/* specific kerning advance */
};

struct data_font_name_t {
	long			type;		/* NAME/DISPLAY NAME/COPYRIGHT/TYPE/LANGUAGE -- used to distinguish different types */
};

#define	FONT_TYPE_LAYOUT	0
#define	FONT_TYPE_ADVANCE	1
#define	FONT_TYPE_KERNING	2
#define	FONT_TYPE_NAME		3
#define	FONT_TYPE_TYPE		4
#define	FONT_TYPE_LANGUAGE	5
#define	FONT_TYPE_DISPLAY_NAME	6
#define	FONT_TYPE_COPYRIGHT	7


/* VARIABLE SIZE -- structure used for IMAGE (followed by one string) */
enum image_format_t {
	IMAGE_FORMAT_LOSSLESS = 0,
	IMAGE_FORMAT_LOSSLESS_8,
	IMAGE_FORMAT_LOSSLESS_16,
	IMAGE_FORMAT_LOSSLESS_32,
	IMAGE_FORMAT_JPEG
};
struct data_image_t {
	/* enum image_format_t	format; -- does not work in big endian 64bit */
	long			format;		/* 0 - LOSSLESS, 1 - JPEG */
	double			quality;	/* 0.0 to 1.0 */
};


/* structure used for STORE REGISTER */
struct data_register_t {
	double			reg;
};


/* structure used for SOUND */
struct data_sound_t {
	long			type;
	double			mono;
	double			set_8bits;
};

#define	SOUND_TYPE_SETUP	0
#define	SOUND_TYPE_FILENAME	1
#define	SOUND_TYPE_FORMAT	2

/* structure used for SOUND INFO */
struct data_sound_info_t {
	double			stop;
	double			no_multiple;
	double			start;
	double			end;
	double			loop;
};

struct data_envelope_t {
	double			position;
	double			left;
	double			right;
};


/* structure used for SHOW FRAME */
struct data_show_frame_t {
	double			wait;
};

/* structure used for PUSH DATA actions */
enum push_data_t {
	PUSHDATA_INTEGER = 20,
	PUSHDATA_STRING,
	PUSHDATA_DOUBLE,
	PUSHDATA_FLOAT,
	PUSHDATA_BOOLEAN,
	PUSHDATA_LOOKUP,
	PUSHDATA_REGISTER,
	PUSHDATA_NULL,
	PUSHDATA_UNDEFINED,
	PUSHDATA_PROPERTY
};
struct data_push_data_t {
	/* enum push_data_t	type; -- does not work in big endian 64bit */
	long			type;
	double			value;
};

/* structure used for GOTO actions */
struct data_goto_play_t {
	double			play;
};

/* VARIABLE SIZE -- structure used for LINE STYLE */
struct data_line_style_t {
	double			width;
	double			to_width;	/* for morph only; -1.0 otherwise */
	double			cap_start;
	double			cap_end;
	double			join;
	double			miter;
	double			hscale;
	double			vscale;
	double			pixel_hinting;
	double			no_close;
	/* followed by one or two colors */
};



/* structure used for MATRIX */
struct data_matrix_t {
	double			sx;		/* scale - 1.0 = default */
	double			sy;
	double			tx;		/* translate - 0.0 = default */
	double			ty;
	double			skew0;		/* skew - 0.0 = default; use only if angle + scale not defined */
	double			skew1;
	double			angle;		/* rotate - 0.0 = default */
};

/* VARIABLE SIZE -- structure used for PLACE OBJECT (followed by color transform, matrix, name, etc.) */
enum {
	PLACE_OBJECT_TYPE_VALUE = 0,		/* default value */
	PLACE_OBJECT_TYPE_NAME,			/* default value */
	PLACE_OBJECT_TYPE_BLEND_MODE		/* blend mode name */
};
struct data_place_object_t {
	long			type;		/* we now need to support multiple strings! */
	double			position;	/* when used for a MorphShape object, NAN otherwise */
	double			depth;		/* depth at which object is placed, if -1, last object depth + 1 */
	double			clip;		/* depth + clip to which object clips */
	double			tab_index;	/* the tab order for the object at this depth */
	double			bitmap_caching;	/* whether to cache the bitmap */
};

/* structure used for ON EVENT */
struct data_on_event_t {
	long			type;
};

#define	ON_EVENT_TYPE_EVENT		1
#define	ON_EVENT_TYPE_KEY		2


/* structure used for RECT */
struct data_rect_t {
	double			min_x;
	double			min_y;
	double			max_x;
	double			max_y;
};

/* VARIABLE SIZE -- structure used for REMOVE, REMOVE ALL */
struct data_remove_t {
	double			depth;		/* if -1, use name instead */
};
	/* if depth == -1 && there isn't a name, then we have a REMOVE ALL */


/* the script limits */
struct data_script_limits_t {
	double			max_recursion_depth;	/* if 0, use default */
	double			timeout_seconds;	/* if 0, use default */
};

/* the set tab index */
struct data_set_tab_index_t {
	double			depth;		/* the depth of an object */
	double			index;		/* the tab order for that object */
};

/* structure used for the shape MOVE */
struct data_move_t {
	long			type;		/* 3 */
	double			tx;
	double			ty;
};


/* structure used for the shape MORPH */
struct data_morph_t {
	long			type;		/* 5 */
	double			mode;		/* 0 - shape0, 1 - shape1, 2 - both shapes */
};


/* structure used for the shape SHOWBOUNDS */
struct data_shape_t {
	long			type;		/* 2 - show bounds, 3 - show origin */
	double			show;
};

/* structure used for the advance between characters in a text object */
enum {
	TEXT_TYPE_INFO = 0,			/* default value */
	TEXT_TYPE_ADVANCE
};
struct data_text_t {
	long			type;
	double			advance;		/* defined when EDIT_TEXT_TYPE_ADVANCE */
	double			thickness;
	double			sharpness;
	double			renderer;
	double			grid_fit;
};

/* structure used for the edit text entries */
enum {
	EDIT_TEXT_TYPE_LAYOUT = 0,		/* default value */
	EDIT_TEXT_TYPE_VARIABLE,
	EDIT_TEXT_TYPE_ALIGNMENT,
	EDIT_TEXT_TYPE_INITIAL_TEXT,
	EDIT_TEXT_TYPE_USED_GLYPHS,
	EDIT_TEXT_TYPE_USED_STRING,
	EDIT_TEXT_TYPE_RENDERER,
	EDIT_TEXT_TYPE_GRID_FIT
};
struct data_edit_text_t {
	long			type;
	double			margin_left;
	double			margin_right;
	double			indent;
	double			leading;
	double			max_length;
	double			word_wrap;
	double			multiline;
	double			password;
	double			readonly;
	double			no_select;
	double			border;
	double			outline;
	double			html;
	double			auto_size;
	double			thickness;
	double			sharpness;
	double			renderer;
	double			grid_fit;
};

/* structure used when the text setup is changed */
struct data_text_setup_t {
	double			x;
	double			y;
	double			height;
};


#define	PIXEL_TO_TWIPS(x)	((long) ((x) * 20.0))
#define	CLAMPED_BYTE_COLOR(c)	((unsigned char) ((c) >= 1.0 ? 255.0 : ((c) <= 0.0 ? 0.0 : rint((c) * 255.0))))





struct node_t {
	enum node_type_t	type;
	enum node_type_t	sub_type;
	enum node_type_t	unit[NODE_UNIT_MAX];
	unsigned long		flags;
	struct node_t *		head;
	struct node_t *		tail;
	struct node_t *		parent;
	struct node_t *		parent2;
	struct node_t *		next;
	struct node_t *		previous;
	struct node_t *		left;
	struct node_t *		right;
	struct node_t *		select;
	struct node_t **	list;		/* list of nodes such as objects or variables */
	long			cnt;		/* valid number of pointers in list */
	long			max;		/* max. number of pointers in list before to reallocate */
	char *			string;		/* identifiers and strings */
	struct data_common_t *	data;		/* a pointer to some object data (see the data_..._t structs) */
	long			integer;
	long			integer2;	/* in case of a range */
	double			floating_point;
	double			floating_point2;
	unsigned long		line;		/* line # when this node was created */
	const char *		filename;	/* filename where the node was read */
#if DEBUG
	unsigned long		serial;		/* used in the node_print() function so the same node isn't printed more than once */
#endif
}; 

#define	NODE_FLAG_SOFTLINK	0x00000001	/* if set, then left, right, select and list can't be cleaned up */



struct node_exec_status_t {
	struct node_exec_status_t *	parent;
	struct node_t *			obj;	/* the object being executed */
	enum node_unit_t		unit;
	int				ref;
};



struct global_t {
	unsigned long		f_flags;
	unsigned long		f_show_steps;
	double			f_frame_rate;
	const char *		f_output_filename;
	const char *		f_output_encoding;
	int			f_version;
	int			f_minimum_version;
	int			f_maximum_version;
};

#define	GLOBAL_FLAG_PROTECT		0x00000001
#define	GLOBAL_FLAG_COMPRESS		0x00000002
#define	GLOBAL_FLAG_USE_NETWORK		0x00000004





#define	node_link(n, l, where)		((n)->where = (l), node_link_parent(n, l))
#define	node_link_left(n, l)		node_link(n, l, left)
#define	node_link_right(n, l)		node_link(n, l, right)
#define	node_link_select(n, l)		node_link(n, l, select)


extern	int			errcnt;
extern	int			warning_off;
extern	const char *		lex_filename;
extern	int			show_input_filenames;
extern	int			show_input_search;
extern	int			show_bounds;
extern	int			show_origin;
#if DEBUG
extern	int			debug_memory;
#endif


extern	struct node_t *		node_alloc(enum node_type_t type, enum node_type_t sub_type, unsigned long line);
extern	void			node_clean(struct node_t *n, const char *spaces);
extern	void			node_done_object(void);
extern	int			node_eval(struct node_t *expr, struct node_t *result, struct node_exec_status_t *status);
extern	int			node_execute(struct node_t *expr, struct node_t *result, struct node_exec_status_t *status);
extern	struct node_t *		node_find_block(struct node_t *expr);
extern	struct node_t *		node_find_object(struct node_t *n, const char *name);
extern	void			node_free(struct node_t *n);
extern	void			node_free_list(struct node_t *n);
extern	struct node_t *		node_init(struct node_t *n, enum node_type_t type, enum node_type_t sub_type);
extern	void			node_link_list(struct node_t *list, struct node_t *item);
extern	void			node_link_object(struct node_t *object);
extern	void			node_link_parent(struct node_t *parent, struct node_t *child);
extern	void			node_link_tail(struct node_t *p, struct node_t *q);
extern	char *			node_path(struct node_t *n, int include_empty);
extern	void			node_print_data(const struct data_common_t *data);
extern	struct node_t *		node_search_list(struct node_t *obj, const char *name);
extern	int			node_setup_objects(void);



#if DEBUG
extern	void			node_print(struct node_t *n);

extern	void *			sswf_alloc(size_t size, const char *name);
extern	void *			sswf_realloc(void *p, size_t size, const char *name);
extern	void			sswf_info(void);
extern	void			sswf_info_serial(void);


#define	sswf_malloc(size, name)		sswf_alloc(size, name)
#define	sswf_remalloc(p, size, name)	sswf_realloc(p, size, name)

#else
/* #if !DEBUG */
extern	void *			sswf_alloc(size_t size);
extern	void *			sswf_realloc(void *p, size_t size);

#define	sswf_malloc(size, name)		sswf_alloc(size)
#define	sswf_remalloc(p, size, name)	sswf_realloc(p, size)
#define	sswf_info()

#endif

extern	void			sswf_free(void *p);
extern	void			sswf_clean(void *p);
extern	char *			sswf_strcat(const char *a, const char *b);
extern	char *			sswf_strcat3(const char *a, const char *b, const char *c);
extern	char *			sswf_strchild(const char *a, const char *b);
extern	char *			sswf_strdup(const char *string);


extern	void			sswf_read_actionscript(int yes);
extern	void			sswf_add_include(const char *path);
extern	void			sswf_set_default_include(int def);
extern	int			sswf_open_script(const char *filename);
extern	void			sswf_close_script(void);

extern	int			strcmp_action(const char *name, const char *pattern);
extern	int			save_data(const struct data_common_t *data, struct global_t *g);
extern	int			parse(void);
extern	void			set_var(const char *name, const char *value);


#ifdef __cplusplus
}
#endif
#endif
