%{ #include #include #include #include #include #include #ifndef yylval #define yylval tmpl_yylval #endif extern char* fileToParse; static int yyerror(char *s, int line); static int getIdent(char *word); static char *strbuf = NULL; static int length; static int total; static void addstring(char *s, int l); static void addchar(char s); static MemoryContext *lexContext; %} %option 8bit %option never-interactive %option nodefault %option noyywrap %option nounput %option prefix="tmpl_yy" %option yylineno %x xVAR %x xEXPR %x xINCLUDE %x xQUOTED %x xCOMMENT LEXEMCHARSTART [a-zA-Z_] LEXEMCHAR [a-zA-Z0-9_] PATH [a-zA-Z0-9_/\.] DIGIT [0-9] %% \<\% { BEGIN xVAR; return VAR_OPEN; } \<\@ { BEGIN xEXPR; return EXPR_OPEN; } \<\& { BEGIN xINCLUDE; return INCLUDE_OPEN; } \<\# { BEGIN xCOMMENT; } [,\|#] { yylval.punct = *yytext; return yylval.punct; } \%\> { BEGIN INITIAL; return VAR_CLOSE; } \" { total = 1024; strbuf = mcalloc(lexContext, total); length=0; BEGIN xQUOTED; } \\(.|\n) { addchar(yytext[1]); } \" { yylval.str = strbuf; BEGIN xVAR; strbuf = NULL; return STRING; } [^\"\\]+ { addstring(yytext, yyleng); } \\ { /* This is only needed for \ just before EOF */ addchar(*yytext); } {DIGIT}+ { yylval.intval = strtoll(yytext, NULL, 0); return INTEGER; } {LEXEMCHARSTART}{LEXEMCHAR}* { yylval.str = strlower(mcnstrdup(lexContext, yytext, yyleng)); return getIdent(yylval.str); } \|\| { return OR_P; } \&\& { return AND_P; } \! { return NOT_P; } [\^\%\+\*\/\-\(\)\?\:] { yylval.punct = *yytext; return yylval.punct; } (\<|\<=|\>=|\>|==|\!=|\<\>) { yylval.str = mcnstrdup(lexContext, yytext, yyleng); return CMP_P; } {DIGIT}+"."{DIGIT}+ { yylval.floatval = atof(yytext); return DOUBLE; } {DIGIT}+[eE]["+""-"]?{DIGIT}+ { yylval.floatval = atof(yytext); return DOUBLE; } {DIGIT}+"."{DIGIT}+[eE]["+""-"]?{DIGIT}+ { yylval.floatval = atof(yytext); return DOUBLE; } \@\> { BEGIN INITIAL; return EXPR_CLOSE; } {PATH}+ { yylval.str = mcnstrdup(lexContext, yytext, yyleng); return FILENAME; } \&\> { BEGIN INITIAL; return INCLUDE_CLOSE; } \#\> { BEGIN INITIAL; } \n+ ; [\r\t ]+ ; . ; . { return yyerror("Syntax error in template tag", yylineno); } <> { return yyerror("unterminated template tag", yylineno); } [^\<]+ { yylval.str = mcnstrdup(lexContext, yytext, yyleng); return TEXT_P; } ([^\<]*\<[^\&\#\@\%][^\<]*)+ { yylval.str = mcnstrdup(lexContext, yytext, yyleng); return TEXT_P; } \< { /* This is only needed for < just before EOF */ yylval.str = mcnstrdup(lexContext, yytext, yyleng); return TEXT_P; } <> { yyterminate(); } %% typedef struct KeyWord { char *word; int len; int id; } KeyWord; static KeyWord keywords[] = { { "H", 0, HTMLESCAPE }, { "U", 0, URLESCAPE }, { "IF", 0, IF_P }, { "ELSE", 0, ELSE_P }, { "LOOP", 0, LOOP_P }, { "SELF", 0, SELF_P }, { "ELSIF", 0, ELSIF_P }, { "ENDIF", 0, ENDIF_P }, { "ENDLOOP", 0, ENDLOOP_P } }; void startTemplateLex(Template tmpl, FILE *in) { if ( keywords->len == 0 ) { int i; for(i=0; itemplateContext; yylineno=1; yyrestart(in); BEGIN INITIAL; } static int getIdent(char *word) { int len = strlen(word); int i; if ( len > keywords[ sizeof(keywords)/sizeof(KeyWord)-1 ].len ) return LEXEME; for(i=0; i= keywords[i].len; i++) if ( len == keywords[i].len && strcasecmp(word, keywords[i].word) == 0 ) return keywords[i].id; return LEXEME; } static int yyerror(char *s, int line) { strbuf = NULL; tlog(TL_CRIT,"template error at line %d in '%s': %s", line, fileToParse, s); return 0; } static void addstring(char *s, int l) { while( length + l + 1 >= total ) { total*=2; strbuf=mcrealloc(strbuf, total); } memcpy( strbuf+length, s, l); length+=l; strbuf[length] = '\0'; } static void addchar(char s) { if( length + 2 >= total ) { total*=2; strbuf=mcrealloc(strbuf, total); } strbuf[ length++ ] = s; strbuf[length] = '\0'; }