moved extern declaration up to prevent compile-time errors.
[swftools.git] / src / parser.lex
index c0513d1..d5d81d6 100644 (file)
@@ -1,7 +1,9 @@
 %{
 
 #include <string.h>
-#include "q.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include "../lib/q.h"
 #include "parser.h"
 
 //RVALUE        {NUMBER}|{PERCENT}|{NAME}|\"{STRING}\"|{DIM}
@@ -32,17 +34,20 @@ static char*prefix = 0;
 static void unescapeString(string_t * tmp)
 {
     char *p, *p1;
+    /* fixme - this routine expects the string to be
+       null-terminated */
 
-    for (p1=tmp->str; (p=strchr(p1, '\\')) != 0; p1 = p+1) 
+    for (p1=tmp->str; (p=strchr(p1, '\\')); p1 = p+1) 
     {
        switch(p[1])
        {
-           case '\\': p[1] = '\\'; break;
-           case 'b': p[1] = '\b'; break;
-           case 'f': p[1] = '\f'; break;
-           case 'n': p[1] = '\n'; break;
-           case 'r': p[1] = '\r'; break;
-           case 't': p[1] = '\t'; break;
+           case '\\': p[1] = '\\'; tmp->len--; break;
+           case '"': p[1] = '"'; tmp->len--; break;
+           case 'b': p[1] = '\b'; tmp->len--; break;
+           case 'f': p[1] = '\f'; tmp->len--; break;
+           case 'n': p[1] = '\n'; tmp->len--; break;
+           case 'r': p[1] = '\r'; tmp->len--; break;
+           case 't': p[1] = '\t'; tmp->len--; break;
            default:
                continue;
        }
@@ -113,6 +118,43 @@ static void store(enum type_t type, int line, int column, char*text, int length)
     prefix = 0;
 }
 
+#define MAX_INCLUDE_DEPTH 16
+YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+int line_stack[MAX_INCLUDE_DEPTH];
+int column_stack[MAX_INCLUDE_DEPTH];
+int include_stack_ptr = 0;
+
+void handleInclude(char*text, int len)
+{
+    text+=9;len-=9;
+    while(len >=1 && (text[0] == ' ' || text[0] == '\t')) {
+       text++;len--;
+    }
+    while(len >= 1 && (text[len-1] == ' ' || text[len-1] == '\n')) {
+       len--;
+    }
+    if(len >= 2 && text[0] == '"' && text[len-1] == '"') {
+       text++; len-=2;
+    }
+    text[len] = 0;
+    if(include_stack_ptr >= MAX_INCLUDE_DEPTH) {
+       fprintf( stderr, "Includes nested too deeply" );
+       exit( 1 );
+    }
+    include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
+    line_stack[include_stack_ptr] = line;
+    column_stack[include_stack_ptr] = column;
+    include_stack_ptr++;
+    yyin = fopen(text, "rb");
+    if (!yyin) {
+       fprintf(stderr, "Couldn't open %s\n", text);
+       exit(1);
+    }
+    yy_switch_to_buffer(
+       yy_create_buffer( yyin, YY_BUF_SIZE ) );
+    BEGIN(INITIAL);
+}
+
 #define c() {count(yytext, yyleng, YY_START);}
 #define s(type) {store(type, line, column, yytext, yyleng);}
 %}
@@ -121,8 +163,8 @@ static void store(enum type_t type, int line, int column, char*text, int length)
 %x BINARY
 
 NAME    [a-zA-Z_./](-*[a-zA-Z0-9_./])*
-TWIP    ([0-9]+(\.([0-9]([05])?)?)?)
-NUMBER  [0-9]+(\.[0-9]*)?
+TWIP    (-?[0-9]+(\.([0-9]([05])?)?)?)
+NUMBER  -?[0-9]+(\.[0-9]*)?
 PERCENT         {NUMBER}%
 STRING   (\\.|[^\\"\n])*
 S       [ \n\r\t]
@@ -145,16 +187,16 @@ RVALUE     \"{STRING}\"|([^ \n\r\t]+)
 <R>{ /* values which appear only on the right-hand side of assignments, like: x=50% */
     [^ \n\t\r]*                    {s(IDENTIFIER);c();BEGIN(0);}
 }
+\.include{S}.*\n                   {handleInclude(yytext, yyleng);}
 \.{NAME}                   {s(COMMAND);c();}
 {NAME}{S}*:                 {s(LABEL);c();}
 {NAME}                      {s(IDENTIFIER);c();}
 "["                        {c();BEGIN(BINARY);}
 {S}                        {c();}
-.                          {char c,c1=0;
+.                          {char c,c1=yytext[0];
                             printf("Syntax error in line %d, %d: %s", line, column, yytext);
                             while(1) {
                                 c=input();
-                                if(!c1) c1=c;
                                 if(c=='\n' || c==EOF) 
                                     break;
                                printf("%c", c);
@@ -165,7 +207,19 @@ RVALUE      \"{STRING}\"|([^ \n\r\t]+)
                             exit(1);
                             yyterminate();
                            }
-<<EOF>>                            {c();s(END);yyterminate();}
+<<EOF>>                            {c();
+                            if ( --include_stack_ptr < 0 ) {
+                               s(END);
+                               yyterminate();
+                            } else {
+                                yy_delete_buffer( YY_CURRENT_BUFFER );
+                                yy_switch_to_buffer(
+                                     include_stack[include_stack_ptr] );
+                                column = column_stack[include_stack_ptr];
+                                line = line_stack[include_stack_ptr];
+                            }
+                           }
+
 %%
 
 int yywrap()