Introduce template instance concept to simplify freeing memory
[tedtools.git] / tmpl_scan.l
1 %{
2 #include <tlog.h>
3 #include <tmalloc.h>
4 #include <template.h>
5 #include <tmpl_gram.h>
6
7 #ifndef yylval
8 #define yylval tmpl_yylval
9 #endif
10
11 extern char* fileToParse;
12
13 static int yyerror(char *s, int line);
14 static int getIdent(char *word);
15
16 static char *strbuf = NULL;
17 static int length;
18 static int total;
19 static void addstring(char *s, int l); 
20 static void addchar(char s); 
21 static MemoryContext *lexContext;       
22
23 %}
24
25 %option 8bit
26 %option never-interactive
27 %option nodefault
28 %option noyywrap
29 %option nounput
30 %option prefix="tmpl_yy"
31 %option yylineno
32
33 %x      xVAR
34 %x      xEXPR
35 %x  xINCLUDE
36 %x  xQUOTED
37 %x  xCOMMENT
38
39 LEXEMCHARSTART  [a-zA-Z_]
40 LEXEMCHAR       [a-zA-Z0-9_]
41 PATH            [a-zA-Z0-9_/\.]
42 DIGIT           [0-9]
43
44 %%
45
46 <INITIAL>\<\%           {
47                                                 BEGIN xVAR;
48                                                 return VAR_OPEN;
49                                         }
50
51 <INITIAL>\<\@           {
52                                                 BEGIN xEXPR;
53                                                 return EXPR_OPEN;
54                                         }
55
56 <INITIAL>\<\&           {
57                                                 BEGIN xINCLUDE;
58                                                 return INCLUDE_OPEN;
59                                         }
60
61 <INITIAL>\<\#           {
62                                                 BEGIN xCOMMENT;
63                                         }
64
65 <xVAR>[,\|#]            {
66                                                 yylval.punct = *yytext;
67                                                 return yylval.punct;
68                                         }
69
70 <xVAR>\%\>                      {
71                                                 BEGIN INITIAL;
72                                                 return VAR_CLOSE;
73                                         }
74
75 <xVAR>\"                        {
76                                                 total = 1024;
77                                                 strbuf = mcalloc(lexContext, total);
78                                                 length=0;
79                                                 BEGIN xQUOTED;
80                                         }
81
82
83 <xQUOTED>\\(.|\n)       { addchar(yytext[1]); }
84
85 <xQUOTED>\"                     {
86                                                 yylval.str = strbuf;
87                                                 BEGIN xVAR;
88                                                 strbuf = NULL;
89                                                 return STRING;
90                                         }
91                                                 
92 <xQUOTED>[^\"\\]+       { addstring(yytext, yyleng); }
93
94 <xQUOTED>\\                     { 
95                                                 /* This is only needed for \ just before EOF */
96                                                 addchar(*yytext); 
97                                         }
98
99 <xEXPR,xVAR>{DIGIT}+    {
100                                         yylval.intval = atoi(yytext);
101                                                 return INTEGER;
102                                         }
103
104 <xEXPR,xVAR>{LEXEMCHARSTART}{LEXEMCHAR}* {
105                                                 yylval.str  = strlower(mcnstrdup(lexContext, yytext, yyleng));
106                                                 return  getIdent(yylval.str);
107                                         }
108
109 <xEXPR,xVAR>\|\|                        { return OR_P; }
110
111 <xEXPR,xVAR>\&\&                        { return AND_P; }
112
113 <xEXPR,xVAR>\!                  { return NOT_P; }
114
115 <xEXPR,xVAR>[\^\%\+\*\/\-\(\)\?\:]              {
116                                                 yylval.punct = *yytext;
117                                                 return yylval.punct;
118                                         }
119
120 <xEXPR,xVAR>(\<|\<=|\>=|\>|==|\!=|\<\>) {
121                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
122                                                 return CMP_P;
123                                         }
124
125 <xEXPR,xVAR>{DIGIT}+"."{DIGIT}+ {
126                                         yylval.floatval = atof(yytext);
127                                                 return DOUBLE;
128                                         }
129
130 <xEXPR,xVAR>{DIGIT}+[eE]["+""-"]?{DIGIT}+    {
131                                         yylval.floatval = atof(yytext);
132                                                 return DOUBLE;
133                                         }
134
135 <xEXPR,xVAR>{DIGIT}+"."{DIGIT}+[eE]["+""-"]?{DIGIT}+   {
136                                                 yylval.floatval = atof(yytext);
137                                                 return DOUBLE;
138                                         }
139
140 <xEXPR>\@\>                     {
141                                                 BEGIN INITIAL;
142                                                 return  EXPR_CLOSE;
143                                         }
144
145 <xINCLUDE>{PATH}+       {
146                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
147                                                 return FILENAME;
148                                         }
149
150 <xINCLUDE>\&\>          {
151                                                 BEGIN INITIAL;
152                                                 return INCLUDE_CLOSE;
153                                         }
154
155 <xCOMMENT>\#\>          {
156                                                 BEGIN INITIAL;
157                                         }
158
159 <xVAR,xINCLUDE,xEXPR,xCOMMENT>\n+       ;
160
161 <xVAR,xINCLUDE,xEXPR,xCOMMENT>[\r\t ]+  ;
162
163 <xCOMMENT>.             ;
164
165 <xVAR,xINCLUDE,xEXPR>.  { 
166                                                 return yyerror("Syntax error in template tag", yylineno); 
167                                         }
168
169 <xVAR,xQUOTED,xINCLUDE,xEXPR,xCOMMENT><<EOF>> { 
170                                                 return yyerror("unterminated template tag", yylineno); 
171                                         }
172
173 <INITIAL>[^\<]+         {
174                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
175                                                 return TEXT_P;
176                                         }
177
178 <INITIAL>([^\<]*\<[^\&\#\@\%][^\<]*)+   {
179                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
180                                                 return TEXT_P;
181                                         }
182                                 
183
184 <INITIAL>\<             {
185                                                 /* This is only needed for < just before EOF */
186                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
187                                                 return TEXT_P;
188                                         }
189
190 <INITIAL><<EOF>>        {
191                                         yyterminate();
192                         }
193
194 %%
195
196 typedef struct KeyWord {
197         char    *word;
198         int             len;
199         int             id;
200 } KeyWord;
201
202 static KeyWord keywords[] = {
203         { "H",                  0,      HTMLESCAPE      },
204         { "U",                  0,      URLESCAPE       },
205         { "IF",                 0,      IF_P            },
206         { "ELSE",               0,      ELSE_P          },
207         { "LOOP",               0,      LOOP_P          },
208         { "SELF",               0,      SELF_P          },
209         { "ENDIF",              0,      ENDIF_P         },
210         { "ENDLOOP",    0,      ENDLOOP_P       } 
211 };
212
213 void
214 startTemplateLex(Template tmpl, FILE *in) {
215         if ( keywords->len == 0 ) {
216                 int i;
217                 for(i=0; i<sizeof(keywords)/sizeof(KeyWord);i++)
218                         keywords[i].len = strlen(keywords[i].word);
219         }
220
221         lexContext = tmpl->templateContext;
222
223         yyrestart(in);
224         BEGIN INITIAL;
225 }
226
227 static int
228 getIdent(char *word) {
229         int len = strlen(word);
230         int i;
231
232         if ( len > keywords[ sizeof(keywords)/sizeof(KeyWord)-1 ].len )
233                 return LEXEME;
234
235         for(i=0; i<sizeof(keywords)/sizeof(KeyWord) && len >= keywords[i].len; i++)
236                 if ( len == keywords[i].len && strcasecmp(word, keywords[i].word) == 0 )
237                         return keywords[i].id;
238
239         return LEXEME;
240 }
241
242 static int 
243 yyerror(char *s, int line) {
244         strbuf = NULL;
245         tlog(TL_CRIT,"template error at line %d in '%s': %s", line, fileToParse, s);
246
247         return 0;
248 }
249
250 static void
251 addstring(char *s, int l) {
252         while( length + l + 1 >= total ) {
253                 total*=2;
254                 strbuf=mcrealloc(strbuf, total);
255         }
256
257         memcpy( strbuf+length, s, l);
258         length+=l;
259         strbuf[length] = '\0';
260 }
261
262 static void
263 addchar(char s) {
264         if(  length + 2 >= total ) {
265                 total*=2;
266                 strbuf=mcrealloc(strbuf, total);
267         }
268
269         strbuf[ length++ ] = s;
270         strbuf[length] = '\0';
271 }
272
273