fixed off-by-one bug
[swftools.git] / lib / action / swf4compiler.flex
blob6a6dddde7b43527ee70eea6126b459e587d7b247
1 %{
3 #include <math.h>
4 #include <string.h>
6 #include "compile.h"
7 #include "action.h"
8 #include "blocks/error.h"
9 #include "swf4compiler.tab.h" /* defines token types */
11 static int swf4debug;
13 static const char *lexBuffer = NULL;
14 static int lexBufferLen = 0;
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;
21 static void comment();
22 static void comment1();
23 static void count();
24 static void warning(char *msg);
26 #define YY_INPUT(buf,result,max_size) result=lexBufferInput(buf, max_size)
28 /* thanks to the prolific and brilliant Raff: */
29 static int lexBufferInput(char *buf, int max_size)
31   int l = lexBufferLen > max_size ? max_size : lexBufferLen;
32   
33   if (lexBufferLen <= 0)
34     return YY_NULL;
36   memcpy(buf, lexBuffer, l);
37   lexBuffer += l;
38   lexBufferLen -= l;
39   return l;
42         /* very inefficient method of unescaping strings */
43 static void unescape(char *buf)
45   char *p, *p1;
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   }
62 void swf4ParseInit(const char *script, int debug)
64   checkByteOrder();
65   yyrestart(NULL);
67   swf4debug = debug;
69   lexBuffer = script;
70   lexBufferLen = strlen(script);
71   sLineNumber = 0;
72   column = 0;
73   msgline = msgbufs[0];
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 ));
89  void do_unput4(const char c) { unput(c); }
92 DIGIT    [0-9]
93 ID       [a-zA-Z_][a-zA-Z0-9_]*
94 LEVEL    \.\.?
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;            }
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;  }
135 getProperty     { count();      return GETPROPERTY;     }
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;   }
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;       }
158   /* high level functions */
159 tellTarget      { count();      return TELLTARGET;      }
162 this                    { count();      return THIS;    }
164 {ID}                    { count();      swf4lval.str = strdup(yytext);
165                                         return IDENTIFIER;      }
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;    }
173 \"(\\.|[^\\"])*\"       { count();      swf4lval.str = strdup(yytext+1);
174                                         swf4lval.str[strlen(swf4lval.str)-1]=0;
175                                         unescape(swf4lval.str);
176                                         return STRING;          }
178 \'(\\.|[^\\'])*\'       { count();      swf4lval.str = strdup(yytext+1);
179                                         swf4lval.str[strlen(swf4lval.str)-1]=0;
180                                         unescape(swf4lval.str);
181                                         return STRING;          }
183 \"(\\.|[^\\"])*$        { count();      swf4lval.str = strdup("");
184                                         warning("Unterminated string!");
185                                         return STRING;          }
187 \'(\\.|[^\\'])*$        { count();      swf4lval.str = strdup("");
188                                         warning("Unterminated string!");
189                                         return STRING;          }
191 "/*"                    { count();      comment();              }
192 "//"                    { count();      comment1();             }
193 [ \t\v\f]               { count(); }
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; }
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 ':'; }
233 \r?\n                   { count();      column = 0;
234                                         strcpy(szLine, yytext + 1);
235                                         ++sLineNumber;  yyless(1);      }
237 .                       printf( "Unrecognized character: %s\n", yytext );
240 static int getinput() {
241 #ifdef __cplusplus
242                                         return yyinput();
243 #else
244                                         return input();
245 #endif
248 int swf4wrap()
250   return 1;
253 static void countline()
255   if(sLineNumber != 0)
256     msgline[column] = 0;
258   ++sLineNumber;
259   column = 0;
260   msgline = msgbufs[sLineNumber & 1];
263 static int LineNumber(void)
265    return (sLineNumber + 1);
268 static int ColumnNumber(void)
270    return column;
273 static char *LineText(void)
275   msgline[column] = 0;
276   return msgline;
279 static void comment(void)
281    // Handle block comments
283    int c, c1;
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;
293       ++column;
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       }
302       if (swf4debug) putchar(c);
303    }
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    }
313    // write out the start of the end of comment
314    if (c != EOF)
315       if (swf4debug) putchar(c);
317    // write out the end of the end of comment
318    if (c1 != EOF) 
319       if (swf4debug) putchar(c1);
322 static void comment1(void)
324    // Handle comment of type 1 (ie '//')
326    int c;
328    // this is a line comment
329    while ((c = getinput()) != '\n' && c != EOF)
330    {
331       if (swf4debug) putchar(c);
333       if(column < 1023)
334          msgline[column] = c;
336       ++column;
337    };
339    // keep the line number in synch
340    if (c == '\n')
341    {
342       if (swf4debug) putchar(c);
344       countline();
345    }
348 static void count(void)
350    int n;
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);
361       for(n=0; n<yyleng; ++n, ++column)
362       {
363         if(column < 1023)
364           msgline[column] = yytext[n];
365       }
367       //-- keep writing the stuff to standard output
368       //column += yyleng;
369    }
372 static void printprog()
374   if(sLineNumber)
375     SWF_warn("\n%s", msgbufs[(sLineNumber-1)&1]);
377   if(column < 1023)
378     msgline[column] = 0;
380   SWF_warn("\n%s", msgline);
383 static void warning(char *msg)
385    // print a warning message
386    printprog();
387    SWF_warn("\n%*s", ColumnNumber(), "^");
388    SWF_warn("\nLine %4.4d:  Reason: '%s' \n", LineNumber(), msg);
391 void swf4error(char *msg)
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   }