1 /****************************************************************************
2  *
3  *  makeswf - a command line actionscript compiler
4  *
5  *  Copyright (C) 2003-2009 "Sandro Santilli" <strk@keybit.net>
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  ****************************************************************************
22  *
23  *  Intro
24  *  -----
25  *
26  *  This is a simple Flash actionscript compiler that
27  *  uses libming to do its job. You'll find it useful
28  *  only when coding in pure actionscript, thus probably
29  *  only when using the Flash 6 drawing API.
30  *
31  *  Input files are preprocessed
32  *  -D can be used to set macros and -I to add dirs to include search paths.
33  *  You can skip the preprocessing step using the -p switch, but this
34  *  is undocumented/deprecated.
35  *
36  *  If you need another kind of preprocessing change the CPP define in
37  *  makeswf_utils.c.
38  *
39  *  Build
40  *  -----
41  *
42  *  This binary will link dinamically to libming, so you should
43  *  install ming somewhere, or let the linker know where to find
44  *  the ming library.
45  *
46  *  TODO
47  *  ----
48  *
49  *  - Write preprocessor output to <output>.as.pp rather then <source>.as.pp
50  *    to have more chances at succeeding (source dir can be unwriteable)
51  *
52  ***************************************************************************/
53 
54 /* This is needed to get vasprintf definition */
55 #define _GNU_SOURCE 1
56 
57 #include <stdio.h>
58 #include <string.h>
59 #include <strings.h>
60 #include <stdarg.h>
61 #include <errno.h>
62 #include <unistd.h>
63 #include <stdlib.h>
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include <limits.h>
67 #include <ming.h>
68 #include <ming_config.h>
69 #include "makeswf.h"
70 #ifdef HAVE_GETOPT_H
71 #include <getopt.h>
72 #endif
73 
74 // Cheating, but it works (not sure why the above ifdef for getopt isn't)
75 #ifdef _WIN32
76 #include <getopt.h>
77 #endif
78 
79 #define DEFSWFVERSION 6
80 #define DEFSWFCOMPRESSION 9
81 
82 #define MAXERRORMSG 1024
83 
84 /* prototypes */
85 static void add_import_spec(char *spec);
86 static void add_init_action(char *file, int frameno);
87 static void add_init_action_spec(char *spec);
88 static void compile_init_actions(int frameno, int debug);
89 static int add_imports(void);
90 static void embed_image(SWFMovie movie, char *f);
91 static void embed_swf(SWFMovie movie, char *f);
92 static void print_init_actions(int frameno, FILE* stream);
93 // return pointer to allocated memory (free it)
94 static char* base_name(char* filename);
95 /* data */
96 static char **import_specs;
97 static int numimport_specs = 0;
98 static int swfversion = DEFSWFVERSION;
99 static const char *RCSID = "$Id$";
100 static SWFMovie mo;
101 static int useBgColor=0;
102 static long int bgcolor=0;
103 char *outputfile="out.swf";
104 
105 typedef struct {
106 	char* file;
107 	int frameno;
108 } init_action;
109 static init_action* init_actions = NULL;
110 static int num_init_actions = 0;
111 static int max_init_action_frame = 0;
112 
113 void
usage(char * me,int ex)114 usage (char *me, int ex)
115 {
116 	fprintf(stderr, "Usage: %s [OPTIONS] <frame_content> ...\n",
117 		me);
118 	fprintf(stderr, "<frame_content> can be: swf, png, jpg, actionscript code.\n");
119 	fprintf(stderr, "Options:\n");
120 	fprintf(stderr, " -o <output>\n");
121 	fprintf(stderr, " -s <width>x<height>\n");
122 	fprintf(stderr, " -r <frame_rate>\n");
123 	fprintf(stderr, " -v <output_version>\n");
124 	fprintf(stderr, " -c <compression_level>\n");
125 	fprintf(stderr, " -b <background_color>\n");
126 	fprintf(stderr, " -I <includedir>\n");
127 	fprintf(stderr, " -D <macro>[=<def>]>\n");
128 	fprintf(stderr, " -i <library.swf>:<sym>[,<sym>]>\n");
129 	fprintf(stderr, " -h  Print this help screen\n");
130 	fprintf(stderr, " -V  Print version and copyright info\n");
131 	fprintf(stderr, " -d  debug parser\n");
132 	fprintf(stderr, " -a  <AS_file>[:<frameno>] - add init action for frame <frameno> (0-based, 0 if omitted)\n");
133 	fprintf(stderr, " -n  network|file - restrict sandbox access from locally-loaded movies (automatically restricted to file for SWF>=8)\n");
134 	exit(ex);
135 }
136 
137 static void
warningHandler(const char * fmt,...)138 warningHandler(const char *fmt, ...)
139 {
140 	va_list ap;
141 
142 	va_start (ap, fmt);
143 
144 	vfprintf(stderr, fmt, ap);
145 	putc('\n', stderr);
146 
147 	va_end(ap);
148 }
149 
150 
151 char *cppargs;
152 size_t cppargsize = 256;
153 typedef enum {
154 
155 	// A prebuilt clip
156 	SWF,
157 
158 	// Any bitmap that can be feed to embed_image
159 	BITMAP,
160 
161 	// ActionScript code
162 	AS
163 } FileType;
164 
getFileType(char * filename)165 FileType getFileType(char* filename)
166 {
167 	// TODO: use magic number
168 
169 	char *ext = strrchr(filename, '.');
170 	if ( ! ext ) return AS;
171 
172 	if ( ! strcasecmp(ext, ".swf") ) return SWF;
173 	if ( ! strcasecmp(ext, ".png") ) return BITMAP;
174 	if ( ! strcasecmp(ext, ".dbl") ) return BITMAP;
175 	if ( ! strcasecmp(ext, ".jpg") ) return BITMAP;
176 	if ( ! strcasecmp(ext, ".jpeg") ) return BITMAP;
177 
178 	return AS;
179 }
180 
181 int
main(int argc,char ** argv)182 main (int argc, char **argv)
183 {
184 	int width=640, height=480;    /* default stage size */
185 	int i;
186 	int swfcompression = DEFSWFCOMPRESSION;
187 	float framerate = 12.0;
188 	/*
189 	 * Allow network access from locally-loaded movies.
190 	 *
191 	 *   0 = file access
192 	 *   1 = network access
193 	 *  -1 = unspecified (omit the tag if SWF < 8, file access otherwise)
194 	 *
195 	 *  By default is unspecified.
196 	 */
197 	int networkAccess = -1;
198 	int usedfiles = 0;
199 	struct stat statbuf;
200 	int debug_parser = 0;
201 #ifdef HAVE_GETOPT_LONG
202 	struct option opts[] =
203 	{
204 		{"dont-preprocess", 0, 0, 'p'},
205 		{"frame-rate", 1, 0, 'r'},
206 		{"swfversion", 1, 0, 'v'},
207 		{"bgcolor", 1, 0, 'b'},
208 		{"compression", 1, 0, 'c'},
209 		{"includepath", 1, 0, 'I'},
210 		{"define", 1, 0, 'D'},
211 		{"size", 1, 0, 's'},
212 		{"network-access", 1, 0, 'n'},
213 		{"output", 1, 0, 'o'},
214 		{"import", 1, 0, 'i'},
215 		{"version", 0, 0, 'V'},
216 		{"help", 0, 0, 'h'},
217 		{"debug", 0, 0, 'd'},
218 		{"init-action", 1, 0, 'a'},
219 		{0, 0, 0, 0}
220 	};
221 	int opts_idx;
222 #endif
223 	int c;
224 	char *me;
225 
226 	cppargs = malloc(cppargsize);
227 	sprintf(cppargs, "%s", DEFAULT_FLAGS);
228 	//cppargs[0] = '\0';
229 
230 
231 	me = argv[0];
232 
233 	while (1)
234 	{
235 #define BUFSIZE 1024
236 		char buf [BUFSIZE];
237 
238 		const char *optstring = "Vhpds:r:D:I:v:c:b:i:o:a:n:";
239 #ifdef HAVE_GETOPT_LONG
240 		c = getopt_long (argc, argv, optstring, opts, &opts_idx);
241 #else
242 		c = getopt (argc, argv, optstring);
243 #endif
244 		if (c == -1) break;
245 
246 		switch (c)
247 		{
248 			case 'p':
249 				makeswf_set_dopreprocess(0);
250 				break;
251 			case 's':
252 				if ( sscanf(optarg, "%dx%d", &width, &height) != 2 )
253 				{
254 					usage(argv[0], EXIT_FAILURE);
255 				}
256 				break;
257 			case 'n':
258 			{
259 				if ( ! strcasecmp(optarg, "network") )
260 				{
261 					networkAccess = 1;
262 				}
263 				else if ( ! strcasecmp(optarg, "file") )
264 				{
265 					networkAccess = 0;
266 				}
267 				else
268 				{
269 					fprintf(stderr, "Network access must be 'network' or 'file'\n");
270 					exit(1);
271 				}
272 				break;
273 			}
274 			case 'v':
275 				if ( sscanf(optarg, "%d", &swfversion) != 1 )
276 				{
277 					usage(argv[0], EXIT_FAILURE);
278 				}
279 				makeswf_set_swfversion(swfversion);
280 				break;
281 			case 'b':
282 				if ( sscanf(optarg, "%lx", &bgcolor) != 1 )
283 				{
284 					usage(argv[0], EXIT_FAILURE);
285 				}
286 				useBgColor=1;
287 				break;
288 			case 'c':
289 				if ( sscanf(optarg, "%d", &swfcompression) != 1 )
290 				{
291 					usage(argv[0], EXIT_FAILURE);
292 				}
293 				if ( swfcompression < -1 || swfcompression > 9 )
294 				{
295 					fprintf(stderr, "Compression level must be in the range -1..9\n");
296 					exit(1);
297 				}
298 				break;
299 			case 'r':
300 				if ( sscanf(optarg, "%f", &framerate) != 1 )
301 				{
302 					usage(argv[0], EXIT_FAILURE);
303 				}
304 				break;
305 			case 'I':
306 				snprintf(buf, BUFSIZE-1, " -I%s", optarg);
307 				buf[BUFSIZE-1]='\0';
308 				makeswf_append_cpparg(buf);
309 				break;
310 			case 'i':
311 				add_import_spec(optarg);
312 				break;
313 			case 'o':
314 				outputfile = optarg;
315 				break;
316 			case 'D':
317 				// yes, you can smash the stack ...
318 				snprintf(buf, BUFSIZE-1, " -D%s", optarg);
319 				buf[BUFSIZE-1]='\0';
320 				makeswf_append_cpparg(buf);
321 				break;
322 			case 'd':
323 				debug_parser = 1;
324 				break;
325 			case 'a':
326 				add_init_action_spec(optarg);
327 				break;
328 			case 'V':
329 				printf("%s\n", RCSID);
330 				printf("Copyright (C) 2001-2006 \"Sandro Santilli\" <strk@keybit.net>.\n");
331 				printf("Released under the GNU General Public License.\n");
332 				exit(EXIT_SUCCESS);
333 			case 'h':
334 				usage(argv[0], EXIT_SUCCESS);
335 			default:
336 				usage(argv[0], EXIT_FAILURE);
337 				break;
338 		}
339 	}
340 	argv+=optind;
341 	argc-=optind;
342 
343 	if ( argc < 1 ) usage(me, EXIT_FAILURE);
344 
345 	if ( stat(outputfile, &statbuf) )
346 	{
347 		// should warn about overriding (-f ?)
348 	}
349 
350 	if ( swfversion < 6 && swfcompression > -1 )
351 	{
352 		fprintf(stderr, "WARNING: SWF compression was unsupported until version 6, use -c -1 to disable.\n");
353 	}
354 
355 	if ( Ming_init() )
356 	{
357 		fprintf(stderr, "Ming initialization error\n");
358 		exit(EXIT_FAILURE);
359 	}
360 	Ming_setWarnFunction(warningHandler);
361 	//Ming_setErrorFunction(compileError);
362 	Ming_useSWFVersion(swfversion);
363 	Ming_setSWFCompression(swfcompression);
364 
365 	mo = newSWFMovie();
366 	if ( networkAccess >= 0 ) SWFMovie_setNetworkAccess(mo, networkAccess);
367 	SWFMovie_setDimension(mo, (float)width, (float)height);
368 	SWFMovie_setRate(mo, framerate);
369 
370 	if ( useBgColor )
371 	{
372 		SWFMovie_setBackground(mo,
373 			bgcolor >> 16,
374 			(bgcolor&0x00FF00) >> 8,
375 			(bgcolor&0x0000FF));
376 	}
377 
378 	printf("Output file name: %s\n", outputfile);
379 	printf("Output compression level: %d\n", swfcompression);
380 	printf("Output SWF version: %d\n", swfversion);
381 
382 	 /*
383 	 * Add imports
384 	 */
385 	if ( numimport_specs ) add_imports();
386 
387 	for ( i=0; i<argc; i++ )
388 	{
389 		SWFAction ac;
390 		char *filename = argv[i];
391 		char ppfile[PATH_MAX];
392 
393 		FileType type = getFileType(filename);
394 
395 		compile_init_actions(i, debug_parser);
396 
397 		if ( type == SWF )
398 		{
399 			printf("Adding prebuilt clip %s to frame %d... ",
400 					filename, i);
401 			embed_swf(mo, filename);
402 		}
403 		else if ( type == BITMAP )
404 		{
405 			printf("Adding bitmap %s to frame %d... ",
406 					filename, i);
407 			embed_image(mo, filename);
408 		}
409 		else
410 		{
411 			sprintf(ppfile, "%s.frame%d.pp", outputfile, i);
412 			ac = makeswf_compile_source(filename, ppfile,
413 				debug_parser);
414 			printf("Adding %s to frame %d... ", filename, i);
415 			SWFMovie_add(mo, (SWFBlock)ac);
416 		}
417 
418 		printf("done.\n");
419 		usedfiles++;
420 		SWFMovie_nextFrame(mo);
421 
422 	}
423 
424 	if ( i <= max_init_action_frame )
425 	{
426 		fprintf(stderr, "WARNING: following init actions for frames > %d have been discarded:\n", i-1);
427 		for (;i<=max_init_action_frame; ++i)
428 		{
429 			print_init_actions(i, stderr);
430 		}
431 	}
432 
433 	if ( ! usedfiles )
434 	{
435 		printf("No valid input files\n");
436 		return 1;
437 	}
438 
439 	printf("Saving output to %s... ", outputfile);
440 	fflush(stdout);
441 	SWFMovie_save(mo, outputfile);
442 	printf("done.\n");
443 
444 	return 0;
445 }
446 
447 
448 static void
add_import_spec(char * spec)449 add_import_spec(char *spec)
450 {
451 	if ( numimport_specs == 0 )
452 	{
453 		import_specs = (char **)malloc(sizeof(char*));
454 	}
455 	else
456 	{
457 		import_specs = (char **)realloc(import_specs,
458 				(numimport_specs+1)*sizeof(char*));
459 	}
460 	import_specs[numimport_specs] = spec;
461 	numimport_specs++;
462 }
463 
464 static void
add_init_action(char * file,int frameno)465 add_init_action(char* file, int frameno)
466 {
467 	printf("Init action for frame %d in file %s\n", frameno, file);
468 
469 	++num_init_actions;
470 	init_actions = (init_action*)realloc(init_actions, num_init_actions*sizeof(init_action));
471 	init_action* ac = &(init_actions[num_init_actions-1]);
472 
473 	ac->file = file;
474 	ac->frameno = frameno;
475 
476 	if ( frameno > max_init_action_frame ) max_init_action_frame = frameno;
477 }
478 
479 static void
print_init_actions(int frameno,FILE * stream)480 print_init_actions(int frameno, FILE* stream)
481 {
482 	int i;
483 
484 	for (i=0; i<num_init_actions; ++i)
485 	{
486 		init_action* ia = &(init_actions[i]);
487 		if ( ia->frameno != frameno ) continue;
488 		fprintf(stream, " %s:%d\n", ia->file, ia->frameno);
489 	}
490 
491 }
492 
493 static void
compile_init_actions(int frameno,int debug)494 compile_init_actions(int frameno, int debug)
495 {
496 	int i;
497 	int found=0;
498 	SWFAction action;
499 	char ppfile[PATH_MAX];
500 
501 	for (i=0; i<num_init_actions; ++i)
502 	{
503 		init_action* ia = &(init_actions[i]);
504 		char* file;
505 
506 		if ( ia->frameno != frameno ) continue;
507 		file = ia->file;
508 
509 		sprintf(ppfile, "%s.frame%d.init%d.pp", outputfile, frameno, found);
510 		action = makeswf_compile_source(file, ppfile, debug);
511 
512 
513 		printf("Adding %s to frame %d init actions... ",
514 					file, frameno);
515 	 	SWFMovie_add(mo, newSWFInitAction(action));
516 		printf("done.\n");
517 
518 		++found;
519 	}
520 
521 }
522 
523 static void
add_init_action_spec(char * spec)524 add_init_action_spec(char *spec)
525 {
526 	struct stat statbuf;
527 	int frameno = 0;
528 	char *file = strtok(spec, ":");
529 	char *framespec = strtok(NULL, ",");
530 
531 	if ( framespec ) frameno = atoi(framespec);
532 
533 	if ( -1 == stat(file, &statbuf) )
534 	{
535 		perror(file);
536 		exit(EXIT_FAILURE);
537 	}
538 
539 	if ( ! S_ISREG(statbuf.st_mode) )
540 	{
541 		fprintf(stderr, "ERROR: %s: is not a regular file\n", file);
542 		exit(EXIT_FAILURE);
543 	}
544 
545 	/* check valid frame spec here */
546 	if ( frameno < 0 )
547 	{
548 		fprintf(stderr, "ERROR: invalid frame number %d for init actions\n", frameno);
549 		exit(EXIT_FAILURE);
550 	}
551 
552 	add_init_action(file, frameno);
553 }
554 
555 static int
add_imports()556 add_imports()
557 {
558 	int i;
559 	SWFMovieClip mc;
560 	SWFDisplayItem di;
561 	SWFAction ac;
562 	struct stat statbuf;
563 
564 	mc = newSWFMovieClip();
565 
566 	for (i=0; i<numimport_specs; i++)
567 	{
568 		char *spec = import_specs[i];
569 		char *file = strtok(spec, ":");
570 		char *sym;
571 		char unchecked = 0;
572 
573    		if ( -1 == stat(file, &statbuf) )
574 		{
575 			unchecked = 1;
576 		}
577 
578 		printf("Importing symbols from ");
579 		if ( unchecked ) printf("[UNAVAILABLE] ");
580 		printf("%s:", file);
581 		fflush(stdout);
582 		while ((sym=strtok(NULL, ",")))
583 		{
584 			SWFCharacter ch;
585 
586 			printf(" %s", sym);
587 			fflush(stdout);
588 			ch = SWFMovie_importCharacter(mo, file, sym);
589 			SWFMovieClip_add(mc, (SWFBlock)ch);
590 		}
591 		printf("\n");
592 	}
593 
594 	SWFMovieClip_nextFrame(mc);
595 	di = SWFMovie_add(mo, (SWFBlock)mc);
596 	SWFDisplayItem_setName(di, "__shared_assets");
597 	ac = newSWFAction("__shared_assets._visible=false;");
598 	SWFMovie_add(mo, (SWFBlock)ac);
599 
600 	return 1;
601 }
602 
603 static char*
base_name(char * filename)604 base_name(char* filename)
605 {
606 	char *name, *ptr;
607 
608 	ptr = strrchr(filename, '/');
609 
610 	if ( ! ptr ) ptr = filename;
611 	else if ( ! *++ptr ) ptr = filename;
612 	name = strdup(ptr);
613 	ptr = strrchr(name, '.');
614 	if ( ptr ) *ptr = '\0';
615 	return name;
616 }
617 
618 static void
embed_image(SWFMovie movie,char * f)619 embed_image(SWFMovie movie, char *f)
620 {
621 	SWFFill fill;
622 	SWFBitmap bm;
623 	SWFShape shape;
624 	SWFMovieClip clip;
625 	SWFDisplayItem it;
626 	FILE *raster;
627 	SWFInput in;
628 	int height, width;
629 	char *name;
630 
631         if (!(raster = fopen (f, "rb")))
632         {
633                 fprintf (stdout, "%s: %s\n", f, strerror (errno));
634 		exit(1);
635         }
636 
637         if (!(in = newSWFInput_file(raster)))
638         {
639                 fprintf (stdout, "Can't create SWFInput from file\n");
640 		exit(1);
641         }
642 
643         if (!(bm = newSWFBitmap_fromInput (in)))
644         {
645                 fprintf (stdout, "Error creating bitmap");
646 		exit(1);
647         }
648 
649 	height = SWFBitmap_getHeight(bm);
650 	width = SWFBitmap_getWidth(bm);
651 
652 
653 	shape = newSWFShape();
654 
655 	SWFShape_movePenTo(shape, 0, 0);
656 
657 	fill = SWFShape_addBitmapFill(shape, bm, SWFFILL_CLIPPED_BITMAP);
658 	SWFShape_setRightFill(shape, fill);
659 	SWFShape_drawLineTo(shape, width, 0);
660 	SWFShape_drawLineTo(shape, width, height);
661 	SWFShape_drawLineTo(shape, 0, height);
662 	SWFShape_drawLineTo(shape, 0, 0);
663 
664 	clip = newSWFMovieClip();
665 	it = SWFMovieClip_add(clip, (SWFBlock)shape);
666 	SWFMovieClip_nextFrame(clip);
667 
668 	it = SWFMovie_add(mo, (SWFBlock)clip);
669 
670 	name = base_name(f);
671 
672 	SWFDisplayItem_setName(it, name);
673 
674 	free(name);
675 
676 }
677 
678 static void
embed_swf(SWFMovie movie,char * filename)679 embed_swf(SWFMovie movie, char* filename)
680 {
681 	SWFPrebuiltClip builtclip;
682 	SWFDisplayItem it;
683 	char *name;
684 	SWFInput in;
685 	FILE *swf;
686 
687         if (!(swf = fopen (filename, "rb")))
688         {
689                 fprintf (stdout, "%s: %s\n", filename, strerror (errno));
690 		exit(1);
691         }
692 
693         if (!(in = newSWFInput_file(swf)))
694         {
695                 fprintf (stdout, "Can't create SWFInput from file\n");
696 		exit(1);
697         }
698 
699 	builtclip = newSWFPrebuiltClip_fromInput(in);
700 	if ( ! builtclip ) {
701                 fprintf (stdout, "Error creating prebuilt clip\n");
702 		exit(1);
703 	}
704 
705 	it = SWFMovie_add(mo, (SWFBlock)builtclip);
706 
707 	name = base_name(filename);
708 	SWFDisplayItem_setName(it, name);
709 	free(name);
710 }
711 
712 /**************************************************************
713  *
714  * $Log$
715  * Revision 1.50  2009/09/08 22:26:16  strk
716  * Update copyright notice (and FSF address)
717  *
718  * Revision 1.49  2009/03/15 21:38:10  strk
719  * Allow using .dbl files as frame content
720  *
721  * Revision 1.48  2009/03/14 09:45:10  strk
722  * Add -b --bgcolor switch to makeswf
723  *
724  * Revision 1.47  2008/06/26 19:36:12  krechert
725  * fix linker error and make enabling SWFAction's debug mode generic
726  *
727  * Revision 1.46  2008/02/08 09:19:57  strk
728  * Add -n switch to force NetworkAccess flag in a file attribute tag.
729  * See http://bugs.libming.org/show_bug.cgi?id=37
730  *
731  * Revision 1.45  2008/01/15 08:11:24  strk
732  * Fix bitmap embedding code to respect size of image (rather then swap dimensions)
733  *
734  * Revision 1.44  2007/10/30 12:17:08  krechert
735  * set framerate as float
736  *
737  * Revision 1.43  2007/10/25 17:26:12  krechert
738  * use new InitAction api
739  *
740  * Revision 1.42  2007/10/24 08:38:47  strk
741  * Use a separate character definition for each init action block
742  *
743  * Revision 1.41  2007/10/24 08:30:43  strk
744  * Add support for multiple init actions in same and/or different frames.
745  * Still unsupported adding init actions for frames for which we specify no content.
746  *
747  * Revision 1.40  2007/10/24 07:49:55  strk
748  * Exit with an error if multiple init actions are attempted to be added (still unsupported)
749  *
750  * Revision 1.39  2007/10/24 07:46:30  strk
751  * Change -C flag to -a (--init-action) and support specifying a target frame number.
752  * Only frame0 is currently supported.
753  *
754  * Revision 1.38  2007/10/18 09:17:59  krechert
755  * add class definition support.
756  * Class definitions are initialized by InitAction tags. These tags need a dummy movieclip they depend on.
757  *
758  * Revision 1.37  2007/10/15 12:37:28  krechert
759  * add bison debugging support in makeswf
760  *
761  * Revision 1.36  2007/07/06 17:53:14  krechert
762  * fixed declaration after statement (C90)
763  * makes ming compile on MSVC again
764  *
765  * Revision 1.35  2007/04/30 09:58:32  strk
766  * Don't include getopt.h if it's not found. Patch by Nils Goroll <nils.goroll@mcs.de>.
767  *
768  * Revision 1.34  2007/04/14 16:58:46  strk
769  * Removed unused CPP define from makeswf.c, fix the *used* one in makeswf_utils.
770  * Thanks to Bastiaan Jacques for finding this out.
771  *
772  * Revision 1.33  2007/04/01 10:01:16  strk
773  * Add -xc++ in CPP define  - patch by Deanna Phillips.
774  *
775  * Revision 1.32  2007/03/22 10:59:17  strk
776  * Updated to use newSWFAction() instead of compileSWFActionCode()
777  *
778  * Revision 1.31  2006/12/12 23:36:10  strk
779  * Implement a separate function for detecting the type of frame content.
780  * Take files anding in .jpeg as bitmaps.
781  * (to be improved to use magic number)
782  *
783  * Revision 1.30  2006/12/11 22:01:29  strk
784  * Use a name for prebuilt clips as well. I can't belive how powerful this tool is getting ;)
785  *
786  * Revision 1.29  2006/12/11 20:01:44  strk
787  * Allow png or jpg frame contents
788  *
789  * Revision 1.28  2006/11/22 23:24:26  strk
790  * Experimental support for use of prebuilt clips.
791  * Example: makeswf frame1.as frame2.swf frame3.as ...
792  *
793  * Revision 1.27  2006/11/15 16:34:48  strk
794  * Fixed import feature to properly set __shared_assets sprite frame count
795  *
796  * Revision 1.26  2006/09/19 08:50:16  strk
797  * Fixed handling of -D flag
798  *
799  * Revision 1.25  2006/07/10 16:11:26  strk
800  * Changed makeswf_compile_source signature to accept path to preprocessor output file. Changed preprocessed file paths to (<output>.frame#.pp) to reduce probability of filesystem permission problems.
801  *
802  * Revision 1.24  2006/07/10 15:30:41  strk
803  * Fixed --help and --version to not require an argument, added TODO item
804  * for non-writeable source dir case.
805  *
806  * Revision 1.23  2006/07/08 13:47:18  strk
807  * Split makeswf general functionalities in a separate file, for use by unit testers
808  *
809  * Revision 1.22  2006/06/20 22:16:13  strk
810  * makeswf:
811  *   - Added __SWF_VERSION__ macro definition for use in source files
812  *
813  * Revision 1.21  2006/05/06 10:38:37  strk
814  * Fixed support for builds w/out zlib in SWF_output and listswf.
815  * Added handler for Ming's warning in command line compiler
816  *
817  * Revision 1.20  2006/05/04 22:28:40  strk
818  * fixed read past end of allocated memory in error handler
819  *
820  * Revision 1.19  2006/04/21 13:55:42  vapour
821  * Added vasprintf() function from http://unixpapa.com/incnote/stdio.html, for those platforms missing it.
822  *
823  * Revision 1.18  2006/04/19 13:16:56  vapour
824  * + Forced use of getopt on Windows.
825  * + Changed to use memset rather than bzero.  bzero not on MinGW.
826  *
827  * Revision 1.17  2006/04/19 11:38:01  vapour
828  * Added liberal use of ifdefs to avoid vasprintf on the platforms that don't have it.  I make no guarantees of the functional integrity on them now. ;(
829  *
830  * Revision 1.16  2005/03/28 08:08:52  strk
831  * Added frame layout printing.
832  *
833  * Revision 1.15  2005/03/22 13:41:30  strk
834  * Changed calling interface:
835  * 	- all arguments are source files
836  * 	- each source file will be stored in a separate
837  * 	  frame, in the order they appear
838  * 	- output will be "out.swf" unless -o <output> is used
839  *
840  * Revision 1.14  2004/11/10 14:00:46  strk
841  * Added support for specifying output compression level
842  *
843  * Revision 1.13  2004/11/09 12:48:12  strk
844  * Added -v flag in usage string (already supported but not documented)
845  *
846  * Revision 1.12  2004/11/03 07:52:08  strk
847  * Introduced a default include path to easy code sharing.
848  *
849  * Revision 1.11  2004/11/02 17:53:05  strk
850  * Fixed a bug in -I and -D handling.
851  *
852  * Revision 1.10  2004/09/29 10:07:29  strk
853  * ImportAssets executed even if import file is not found on filesystem.
854  * A warning is issued in that case.
855  *
856  * Revision 1.9  2004/09/28 14:39:50  strk
857  * Forced imported assets inclusion by mean of instantiation.
858  * Symbols are instantiated inside a __shared_assets clip, which in turn
859  * is made invisible.
860  *
861  * Revision 1.8  2004/09/28 14:09:07  strk
862  * Added assets import support.
863  *
864  * Revision 1.7  2004/09/28 06:59:29  strk
865  * Added -v switch to set output version.
866  * Added notice about output configuration.
867  *
868  * Revision 1.6  2004/09/25 08:23:05  strk
869  * Added -C to cpp call
870  *
871  * Revision 1.5  2004/09/25 08:17:11  strk
872  * Post-processed files are kept and their name is shown to the user to
873  * allow for error Line finding.
874  *
875  * Revision 1.4  2004/07/19 08:22:56  strk
876  * GNU_SOURCE define in makeswf.c, makeswf.h dependency in Makefile
877  *
878  * Revision 1.3  2004/07/15 12:45:54  strk
879  * Added -D and -I switched for preprocessor control
880  *
881  *
882  **************************************************************/
883