initial revision
[swftools.git] / lib / action / swf4compiler.flex
1 %{
2
3 #include <math.h>
4 #include <string.h>
5
6 #include "compile.h"
7 #include "action.h"
8 #include "blocks/error.h"
9 #include "swf4compiler.tab.h" /* defines token types */
10
11 static int swf4debug;
12
13 static const char *lexBuffer = NULL;
14 static int lexBufferLen = 0;
15
16 static int  sLineNumber = 0;
17 static char szLine[1024];
18 static char msgbufs[2][1024] = { {0}, {0} }, *msgline = {0};
19 static int  column = 0;
20
21 static void comment();
22 static void comment1();
23 static void count();
24 static void warning(char *msg);
25
26 #define YY_INPUT(buf,result,max_size) result=lexBufferInput(buf, max_size)
27
28 /* thanks to the prolific and brilliant Raff: */
29 static int lexBufferInput(char *buf, int max_size)
30 {
31   int l = lexBufferLen > max_size ? max_size : lexBufferLen;
32   
33   if (lexBufferLen <= 0)
34     return YY_NULL;
35
36   memcpy(buf, lexBuffer, l);
37   lexBuffer += l;
38   lexBufferLen -= l;
39   return l;
40 }
41
42         /* very inefficient method of unescaping strings */
43 static void unescape(char *buf)
44 {
45   char *p, *p1;
46
47   for (p1=buf; (p=strchr(p1, '\\')) != 0; p1 = p+1) {
48     switch(p[1])
49     {
50     case 'b' : p[1] = '\b'; break;
51     case 'f' : p[1] = '\f'; break;
52     case 'n' : p[1] = '\n'; break;
53     case 'r' : p[1] = '\r'; break;
54     case 't' : p[1] = '\t'; break;
55     case 'x' :
56     case 'u' : warning("unsupported escape sequence");
57     }
58     strcpy(p, p+1);
59   }
60 }
61
62 void swf4ParseInit(const char *script, int debug)
63 {
64   checkByteOrder();
65   yyrestart(NULL);
66
67   swf4debug = debug;
68
69   lexBuffer = script;
70   lexBufferLen = strlen(script);
71   sLineNumber = 0;
72   column = 0;
73   msgline = msgbufs[0];
74 }
75
76 %}
77
78 %{
79  // forward declaration needed by the following function
80 #ifndef YY_PROTO
81 #ifdef YY_USE_PROTOS
82 #define YY_PROTO(proto) proto
83 #else
84 #define YY_PROTO(proto) ()
85 #endif
86 #endif
87  static void yyunput YY_PROTO(( int c, char *buf_ptr ));
88
89  void do_unput4(const char c) { unput(c); }
90 %}
91
92 DIGIT    [0-9]
93 ID       [a-zA-Z_][a-zA-Z0-9_]*
94 LEVEL    \.\.?
95
96 %%
97
98 {DIGIT}+                { count();      swf4lval.str = strdup(yytext);
99                                         return NUMBER;          }
100 {DIGIT}+"."{DIGIT}*     { count();      swf4lval.str = strdup(yytext);
101                                         return NUMBER;          }
102 true                    { count();      swf4lval.str = strdup("1");
103                                         return NUMBER;          }
104 false                   { count();      swf4lval.str = strdup("0");
105                                         return NUMBER;          }
106 break                   { count();      return BREAK;           }
107 continue                { count();      return CONTINUE;        }
108 else                    { count();      return ELSE;            }
109 for                     { count();      return FOR;             }
110 if                      { count();      return IF;              }
111 while                   { count();      return WHILE;           }
112 do                      { count();      return DO;              }
113 valueOf                 { count();      return EVAL;            }
114
115   /* functions */
116 random          { count();      return RANDOM;  }
117 time            { count();      return TIME;    }
118 length          { count();      return LENGTH;  }
119 int             { count();      return INT;     }
120 concat          { count();      return CONCAT;  }
121 duplicateClip   { count();      return DUPLICATECLIP;   }
122 removeClip      { count();      return REMOVECLIP;      }
123 trace           { count();      return TRACE;   }
124 startDrag       { count();      return STARTDRAG;       }
125 stopDrag        { count();      return STOPDRAG;        }
126 ord             { count();      return ORD;     }
127 chr             { count();      return CHR;     }
128 callFrame       { count();      return CALLFRAME;       }
129 getURL          { count();      return GETURL;  }
130 getURL1         { count();      return GETURL1; }
131 loadMovie       { count();      return LOADMOVIE;       }
132 loadVariables   { count();      return LOADVARIABLES;   }
133 substr          { count();      return SUBSTR;  }
134
135 getProperty     { count();      return GETPROPERTY;     }
136
137   /* getURL2 methods */
138 post            { count();      swf4lval.getURLMethod = GETURL_METHOD_POST;
139                                 return GETURL_METHOD;   }
140 get             { count();      swf4lval.getURLMethod = GETURL_METHOD_GET;
141                                 return GETURL_METHOD;   }
142 nosend          { count();      swf4lval.getURLMethod = GETURL_METHOD_NOSEND;
143                                 return GETURL_METHOD;   }
144
145
146   /* v3 functions */
147 nextFrame       { count();      return NEXTFRAME;       }
148 prevFrame       { count();      return PREVFRAME;       }
149 play            { count();      return PLAY;            }
150 stop            { count();      return STOP;            }
151 toggleQuality   { count();      return TOGGLEQUALITY;   }
152 stopSounds      { count();      return STOPSOUNDS;      }
153 gotoFrame       { count();      return GOTOFRAME;       }
154 gotoAndPlay     { count();      return GOTOANDPLAY;     }
155 frameLoaded     { count();      return FRAMELOADED;     }
156 setTarget       { count();      return SETTARGET;       }
157
158   /* high level functions */
159 tellTarget      { count();      return TELLTARGET;      }
160
161
162 this                    { count();      return THIS;    }
163
164 {ID}                    { count();      swf4lval.str = strdup(yytext);
165                                         return IDENTIFIER;      }
166
167 {LEVEL}?("/"({ID}|{LEVEL}))+ { count(); swf4lval.str = strdup(yytext);
168                                         return PATH;    }
169                     
170 {ID}("/"({ID}|{LEVEL}))+ { count();     swf4lval.str = strdup(yytext);
171                                         return PATH;    }
172
173 \"(\\.|[^\\"])*\"       { count();      swf4lval.str = strdup(yytext+1);
174                                         swf4lval.str[strlen(swf4lval.str)-1]=0;
175                                         unescape(swf4lval.str);
176                                         return STRING;          }
177
178 \'(\\.|[^\\'])*\'       { count();      swf4lval.str = strdup(yytext+1);
179                                         swf4lval.str[strlen(swf4lval.str)-1]=0;
180                                         unescape(swf4lval.str);
181                                         return STRING;          }
182
183 \"(\\.|[^\\"])*$        { count();      swf4lval.str = strdup("");
184                                         warning("Unterminated string!");
185                                         return STRING;          }
186
187 \'(\\.|[^\\'])*$        { count();      swf4lval.str = strdup("");
188                                         warning("Unterminated string!");
189                                         return STRING;          }
190
191 "/*"                    { count();      comment();              }
192 "//"                    { count();      comment1();             }
193 [ \t\v\f]               { count(); }
194
195 "++"                    { count();      return INC; }
196 "--"                    { count();      return DEC; }
197 "<"                     { count();      return '<'; }
198 ">"                     { count();      return '>'; }
199 "<="                    { count();      return LE; }
200 ">="                    { count();      return GE; }
201 "=="                    { count();      return EQ; }
202 "!="                    { count();      return NE; }
203 "&&"                    { count();      return LAN; }
204 "||"                    { count();      return LOR; }
205 "*="                    { count();      return MEQ; }
206 "/="                    { count();      return DEQ; }
207 "+="                    { count();      return IEQ; }
208 "-="                    { count();      return SEQ; }
209 "==="                   { count();      return STREQ; }
210 "!=="                   { count();      return STRNE; }
211 "<=>"                   { count();      return STRCMP; }
212 ".."                    { count();      return PARENT; }
213
214 ";"                     { count();      return ';'; }
215 "="                     { count();      return '='; }
216 "+"                     { count();      return '+'; }
217 "-"                     { count();      return '-'; }
218 "&"                     { count();      return '&'; }
219 "*"                     { count();      return '*'; }
220 "/"                     { count();      return '/'; }
221 "!"                     { count();      return '!'; }
222 "("                     { count();      return '('; }
223 ")"                     { count();      return ')'; }
224 "["                     { count();      return '['; }
225 "]"                     { count();      return ']'; }
226 "{"                     { count();      return '{'; }
227 "}"                     { count();      return '}'; }
228 ","                     { count();      return ','; }
229 "."                     { count();      return '.'; }
230 "?"                     { count();      return '?'; }
231 ":"                     { count();      return ':'; }
232
233 \r?\n                   { count();      column = 0;
234                                         strcpy(szLine, yytext + 1);
235                                         ++sLineNumber;  yyless(1);      }
236
237 .                       printf( "Unrecognized character: %s\n", yytext );
238
239 %%
240 static int getinput() {
241 #ifdef __cplusplus
242                                         return yyinput();
243 #else
244                                         return input();
245 #endif
246 }
247
248 int swf4wrap()
249 {
250   return 1;
251 }
252
253 static void countline()
254 {
255   if(sLineNumber != 0)
256     msgline[column] = 0;
257
258   ++sLineNumber;
259   column = 0;
260   msgline = msgbufs[sLineNumber & 1];
261 }
262
263 static int LineNumber(void)
264 {
265    return (sLineNumber + 1);
266 }
267
268 static int ColumnNumber(void)
269 {
270    return column;
271 }
272
273 static char *LineText(void)
274 {
275   msgline[column] = 0;
276   return msgline;
277 }
278
279 static void comment(void)
280 {
281    // Handle block comments
282
283    int c, c1;
284
285 loop:
286    // We have the start of a comment so look skip everything up to the
287    // end of the comment character
288    while ((c = getinput()) != '*' && c != EOF)
289    {
290       if(column < 1023)
291          msgline[column] = c;
292
293       ++column;
294
295       // keep the line number in synch
296       if (c == '\n')
297       {
298          // start the output (matches the algorithim in the lexx above)
299          countline();
300       }
301
302       if (swf4debug) putchar(c);
303    }
304
305    // is this the end of comment character
306    if ((c1 = getinput()) != '/' && c != EOF)
307    {
308       // false start as this was no end of comment
309       do_unput4(c1);
310       goto loop;
311    }
312
313    // write out the start of the end of comment
314    if (c != EOF)
315       if (swf4debug) putchar(c);
316
317    // write out the end of the end of comment
318    if (c1 != EOF) 
319       if (swf4debug) putchar(c1);
320 }
321
322 static void comment1(void)
323 {
324    // Handle comment of type 1 (ie '//')
325
326    int c;
327
328    // this is a line comment
329    while ((c = getinput()) != '\n' && c != EOF)
330    {
331       if (swf4debug) putchar(c);
332
333       if(column < 1023)
334          msgline[column] = c;
335
336       ++column;
337    };
338
339    // keep the line number in synch
340    if (c == '\n')
341    {
342       if (swf4debug) putchar(c);
343
344       countline();
345    }
346 }
347
348 static void count(void)
349 {
350    int n;
351
352    // Count the characters to maintain the current column position
353    if (yytext[0] == '\n')
354    {
355       if (swf4debug) printf("\n");
356    }
357    else
358    {
359       if (swf4debug) printf("%s", yytext);
360
361       for(n=0; n<yyleng; ++n, ++column)
362       {
363         if(column < 1023)
364           msgline[column] = yytext[n];
365       }
366
367       //-- keep writing the stuff to standard output
368       //column += yyleng;
369    }
370 }
371
372 static void printprog()
373 {
374   if(sLineNumber)
375     SWF_warn("\n%s", msgbufs[(sLineNumber-1)&1]);
376
377   if(column < 1023)
378     msgline[column] = 0;
379
380   SWF_warn("\n%s", msgline);
381 }
382
383 static void warning(char *msg)
384 {
385    // print a warning message
386    printprog();
387    SWF_warn("\n%*s", ColumnNumber(), "^");
388    SWF_warn("\nLine %4.4d:  Reason: '%s' \n", LineNumber(), msg);
389 }
390
391 void swf4error(char *msg)
392 {
393   // report a error
394   if(strlen(yytext))
395   {
396     SWF_error("\n%s\n%*s\nLine %i:  Reason: '%s'\n",
397               LineText(), ColumnNumber(), "^", LineNumber(), msg);
398   }
399   else
400   {
401     SWF_error("\nLine %d: Reason: 'Unexpected EOF found while looking for input.'\n", LineNumber());
402   }
403 }