new parameter addspacechars
[swftools.git] / src / as3compile.c
1 /* as3compile.c
2    Compiles ActionScript 3.0 (.as) files into .swf files.
3
4    Part of the swftools package.
5
6    Copyright (c) 2008/2009 Matthias Kramm <kramm@quiss.org>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include "../lib/rfxswf.h"
28 #include "../lib/args.h"
29 #include "../lib/q.h"
30 #include "../lib/os.h"
31
32 static char * filename = 0;
33 static char * outputname = 0;
34 static int override_outputname = 0;
35 static int do_cgi = 0;
36 static double framerate = 25.0;
37 static double width = 400;
38 static double height = 300;
39 static int flashversion = 9;
40 static int verbose = 1;
41 static char local_with_networking = 0;
42 static char local_with_filesystem = 0;
43 static char*mainclass = 0;
44
45 static struct options_t options[] = {
46 {"h", "help"},
47 {"V", "version"},
48 {"v", "verbose"},
49 {"q", "quiet"},
50 {"C", "cgi"},
51 {"R", "resolve"},
52 {"D", "define"},
53 {"X", "width"},
54 {"Y", "height"},
55 {"r", "rate"},
56 {"M", "mainclass"},
57 {"l", "library"},
58 {"I", "include"},
59 {"N", "local-with-network"},
60 {"L", "local-with-filesystem"},
61 {"T", "flashversion"},
62 {"o", "output"},
63 {0,0}
64 };
65
66 int args_callback_option(char*name,char*val)
67 {
68     if(!strcmp(name, "V")) {
69         printf("swfc - part of %s %s\n", PACKAGE, VERSION);
70         exit(0);
71     }
72     else if(!strcmp(name, "o")) {
73         outputname = val;
74         override_outputname = 1;
75         return 1;
76     }
77     else if(!strcmp(name, "r")) {
78         framerate = atof(val);
79         return 1;
80     }
81     else if(!strcmp(name, "M")) {
82         mainclass = val;
83         return 1;
84     }
85     else if(!strcmp(name, "v")) {
86         verbose++;
87         return 0;
88     }
89     else if(!strcmp(name, "q")) {
90         verbose--;
91         return 0;
92     }
93     else if(!strcmp(name, "X")) {
94         width = atof(val);
95         return 1;
96     }
97     else if(!strcmp(name, "Y")) {
98         height = atof(val);
99         return 1;
100     }
101     else if(!strcmp(name, "T")) {
102         flashversion = atoi(val);
103         return 1;
104     }
105     else if(!strcmp(name, "C")) {
106         do_cgi = 1;
107         return 0;
108     }
109     else if(!strcmp(name, "l")) {
110         as3_import_file(val);
111         return 1;
112     }
113     else if(!strcmp(name, "I")) {
114         as3_add_include_dir(val);
115         return 1;
116     }
117     else if(!strcmp(name, "R")) {
118         as3_set_option("recurse","1");
119         return 0;
120     }
121     else if(!strcmp(name, "D")) {
122         if(!strstr(val, "::")) {
123             fprintf(stderr, "Error: compile definition must contain \"::\"\n");
124             exit(1);
125         }
126         as3_set_define(val);
127         return 1;
128     }
129     else if (!strcmp(name, "N"))
130     {
131         local_with_networking = 1;
132         return 0;
133     }
134     else if (!strcmp(name, "L"))
135     {
136         local_with_filesystem = 1;
137         return 0;
138     }
139     else {
140         printf("Unknown option: -%s\n", name);
141         exit(1);
142     }
143     return 0;
144 }
145 int args_callback_longoption(char*name,char*val)
146 {
147     return args_long2shortoption(options, name, val);
148 }
149 void args_callback_usage(char *name)
150 {
151     printf("\n");
152     printf("Usage: %s file.as [-o file.swf] \n", name);
153     printf("\n");
154     printf("-h , --help                    Print short help message and exit\n");
155     printf("-V , --version                 Print version info and exit\n");
156     printf("-v , --verbose                 Increase verbosity\n");
157     printf("-q , --quiet                   Decrease verbosity\n");
158     printf("-C , --cgi                     Output to stdout (for use in CGI environments)\n");
159     printf("-R , --resolve                 Try to resolve undefined classes automatically.\n");
160     printf("-D , --define <namespace::variable>    Set a compile time variable (for doing conditional compilation)\n");
161     printf("-X , --width                   Set target SWF width\n");
162     printf("-Y , --height                  Set target SWF width\n");
163     printf("-r , --rate                    Set target SWF framerate\n");
164     printf("-M , --mainclass               Set the name of the main class (extending flash.display.MovieClip or .Sprite)\n");
165     printf("-l , --library <file>          Include library file <file>. <file> can be an .abc or .swf file.\n");
166     printf("-I , --include <dir>           Add additional include dir <dir>.\n");
167     printf("-N , --local-with-network      Make output file \"local with networking\"\n");
168     printf("-L , --local-with-filesystem     Make output file \"local with filesystem\"\n");
169     printf("-T , --flashversion <num>      Set target SWF flash version to <num>.\n");
170     printf("-o , --output <filename>       Set output file to <filename>.\n");
171     printf("\n");
172 }
173 int args_callback_command(char*name,char*val)
174 {
175     if(filename) {
176         fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
177                  filename, name);
178     }
179     filename = name;
180     return 0;
181 }
182
183 void writeSWF(SWF*swf)
184 {
185     int fi = -1;
186     if(do_cgi || !strcmp(filename, "-"))
187         fi = fileno(stdout);
188     else
189         fi = open(outputname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644);
190     if(fi<0) {
191         fprintf(stderr, "couldn't create output file %s\n", filename);
192         exit(1);
193     }
194     if(do_cgi) {
195         if(swf_WriteCGI(swf)<0) {
196             fprintf(stderr, "WriteCGI failed.\n");
197             exit(1);
198         }
199     } else {
200         if(swf_WriteSWF(fi, swf)<0) {
201             fprintf(stderr, "WriteSWF() failed.\n");
202             exit(1);
203         }
204     }
205 }
206
207 int main (int argc,char ** argv)
208 {
209     char buf[512];
210     char*currentdir = getcwd(buf, 512);
211     if(!currentdir) {
212         as3_warning("Could not determine the current directory");
213     } else {
214         as3_add_include_dir(currentdir);
215     }
216
217     int t;
218     processargs(argc, argv);
219     as3_setverbosity(verbose);
220
221     if(!filename) {
222         args_callback_usage(argv[0]);
223         exit(1);
224     }
225     if(!outputname) {
226         outputname = stripFilename(filename, ".swf");
227         //as3_warning("output name not given, writing to %s", outputname);
228     }
229
230     if(!strcmp(filename, ".")) {
231         as3_parse_directory(".");
232     } else {
233         as3_parse_file(filename);
234     }
235
236     void*code = as3_getcode();
237
238     SWF swf;
239     memset(&swf, 0, sizeof(swf));
240     swf.fileVersion = flashversion;
241     swf.frameRate = framerate*0x100;
242     swf.movieSize.xmin = 0;
243     swf.movieSize.ymin = 0;
244     swf.movieSize.xmax = width*20;
245     swf.movieSize.ymax = height*20;
246     TAG*tag = swf.firstTag = swf_InsertTag(0, ST_DOABC);
247     swf_WriteABC(tag, code);
248
249     if(!mainclass)
250         mainclass = as3_getglobalclass();
251     if(mainclass) {
252         tag = swf_InsertTag(tag, ST_SYMBOLCLASS);
253         swf_SetU16(tag, 1);
254         swf_SetU16(tag, 0);
255         swf_SetString(tag, mainclass);
256     } else {
257         as3_warning("no global public MovieClip subclass");
258     }
259     
260     as3_destroy();
261
262     tag = swf_InsertTag(tag, ST_SHOWFRAME);
263     tag = swf_InsertTag(tag, ST_END);
264
265     swf_FreeABC(code);
266     
267     if(local_with_filesystem)
268         swf.fileAttributes &= ~FILEATTRIBUTE_USENETWORK;
269     if(local_with_networking)
270         swf.fileAttributes |= FILEATTRIBUTE_USENETWORK;
271
272     writeSWF(&swf);
273     swf_FreeTags(&swf);
274
275     return 0;
276 }
277