| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #include | 
| 2 |  |  |  |  |  |  | #include | 
| 3 |  |  |  |  |  |  | #include | 
| 4 |  |  |  |  |  |  | #include | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | #include "tmplpro.h" | 
| 7 |  |  |  |  |  |  | #include "pconst.h" | 
| 8 |  |  |  |  |  |  | #include "procore.h" | 
| 9 |  |  |  |  |  |  | #include "prostate.h" | 
| 10 |  |  |  |  |  |  | #include "provalue.h" | 
| 11 |  |  |  |  |  |  | #include "tagstack.h" | 
| 12 |  |  |  |  |  |  | #include "pbuffer.h" | 
| 13 |  |  |  |  |  |  | #include "parse_expr.h" | 
| 14 |  |  |  |  |  |  | #include "pparam.h" | 
| 15 |  |  |  |  |  |  | #include "optint.h" | 
| 16 |  |  |  |  |  |  | #include "proscope.h" | 
| 17 |  |  |  |  |  |  | #include "proscope.inc" | 
| 18 |  |  |  |  |  |  | #include "pstrutils.inc" | 
| 19 |  |  |  |  |  |  | #include "pmiscdef.h" /*for snprintf */ | 
| 20 |  |  |  |  |  |  | /* for mmap_load_file & mmap_unload_file */ | 
| 21 |  |  |  |  |  |  | #include "loadfile.inc" | 
| 22 |  |  |  |  |  |  | #include "loopvar.inc" | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | #define HTML_TEMPLATE_NO_TAG     -1 | 
| 25 |  |  |  |  |  |  | #define HTML_TEMPLATE_BAD_TAG     0 | 
| 26 |  |  |  |  |  |  | #define HTML_TEMPLATE_FIRST_TAG_USED 1 | 
| 27 |  |  |  |  |  |  | #define HTML_TEMPLATE_TAG_VAR     1 | 
| 28 |  |  |  |  |  |  | #define HTML_TEMPLATE_TAG_INCLUDE 2 | 
| 29 |  |  |  |  |  |  | #define HTML_TEMPLATE_TAG_LOOP    3 | 
| 30 |  |  |  |  |  |  | #define HTML_TEMPLATE_TAG_IF      4 | 
| 31 |  |  |  |  |  |  | #define HTML_TEMPLATE_TAG_ELSE    5 | 
| 32 |  |  |  |  |  |  | #define HTML_TEMPLATE_TAG_UNLESS  6 | 
| 33 |  |  |  |  |  |  | #define HTML_TEMPLATE_TAG_ELSIF   7 | 
| 34 |  |  |  |  |  |  | #define HTML_TEMPLATE_LAST_TAG_USED  7 | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | static | 
| 37 |  |  |  |  |  |  | const char* const tagname[]={ | 
| 38 |  |  |  |  |  |  | "Bad or unsupported tag", /* 0 */ | 
| 39 |  |  |  |  |  |  | "var", "include", "loop", "if", "else", "unless", "elsif" | 
| 40 |  |  |  |  |  |  | }; | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | static | 
| 43 |  |  |  |  |  |  | const char* const TAGNAME[]={ | 
| 44 |  |  |  |  |  |  | "Bad or unsupported tag", /* 0 */ | 
| 45 |  |  |  |  |  |  | "VAR", "INCLUDE", "LOOP", "IF", "ELSE", "UNLESS", "ELSIF" | 
| 46 |  |  |  |  |  |  | }; | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | static int debuglevel=0; | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | #define TAG_OPT_NAME 0 | 
| 51 |  |  |  |  |  |  | #define TAG_OPT_EXPR 1 | 
| 52 |  |  |  |  |  |  | #define TAG_OPT_ESCAPE 2 | 
| 53 |  |  |  |  |  |  | #define TAG_OPT_DEFAULT 3 | 
| 54 |  |  |  |  |  |  | #define MIN_TAG_OPT 0 | 
| 55 |  |  |  |  |  |  | #define MAX_TAG_OPT 3 | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | static const char* const tagopt[]={"name", "expr", "escape", "default" }; | 
| 58 |  |  |  |  |  |  | static const char* const TAGOPT[]={"NAME", "EXPR", "ESCAPE", "DEFAULT" }; | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | #include "prostate.inc" | 
| 61 |  |  |  |  |  |  | #include "tags.inc" | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | static const char tag_can_be_closed[]={ | 
| 64 |  |  |  |  |  |  | 1 /*Bad or unsupported tag*/, | 
| 65 |  |  |  |  |  |  | 0 /*VAR*/, | 
| 66 |  |  |  |  |  |  | 0 /*INCLUDE*/, | 
| 67 |  |  |  |  |  |  | 1 /*LOOP*/, | 
| 68 |  |  |  |  |  |  | 1 /*IF*/, | 
| 69 |  |  |  |  |  |  | 0 /*ELSE*/, | 
| 70 |  |  |  |  |  |  | 1 /*UNLESS*/, | 
| 71 |  |  |  |  |  |  | 1 /*ELSIF*/, | 
| 72 |  |  |  |  |  |  | 0 /**/, | 
| 73 |  |  |  |  |  |  | }; | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | static const char tag_has_opt[][6]={ | 
| 76 |  |  |  |  |  |  | /* "name", "expr", "escape", "default", todo, todo */ | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | { 0, 0, 0, 0, 0, 0 }, /*Bad or unsupported tag*/ | 
| 79 |  |  |  |  |  |  | { 1, 1, 1, 1, 0, 0 }, /*VAR*/ | 
| 80 |  |  |  |  |  |  | { 1, 1, 0, 1, 0, 0 }, /*INCLUDE*/ | 
| 81 |  |  |  |  |  |  | { 1, 0, 0, 0, 0, 0 }, /*LOOP*/ | 
| 82 |  |  |  |  |  |  | { 1, 1, 0, 0, 0, 0 }, /*IF*/ | 
| 83 |  |  |  |  |  |  | { 0, 0, 0, 0, 0, 0 }, /*ELSE*/ | 
| 84 |  |  |  |  |  |  | { 1, 1, 0, 0, 0, 0 }, /*UNLESS*/ | 
| 85 |  |  |  |  |  |  | { 1, 1, 0, 0, 0, 0 }, /*ELSIF*/ | 
| 86 |  |  |  |  |  |  | { 0, 0, 0, 0, 0, 0 }, /**/ | 
| 87 |  |  |  |  |  |  | }; | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | typedef void (*tag_handler_func)(struct tmplpro_state *state, const PSTRING* const TagOptVal); | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | static const tag_handler_func output_closetag_handler[]={ | 
| 92 |  |  |  |  |  |  | tag_handler_unknown,	/*Bad or unsupported tag*/ | 
| 93 |  |  |  |  |  |  | tag_handler_unknown,	/*VAR*/ | 
| 94 |  |  |  |  |  |  | tag_handler_unknown,	/*INCLUDE*/ | 
| 95 |  |  |  |  |  |  | tag_handler_closeloop,	/*LOOP*/ | 
| 96 |  |  |  |  |  |  | tag_handler_closeif,	/*IF*/ | 
| 97 |  |  |  |  |  |  | tag_handler_unknown,	/*ELSE*/ | 
| 98 |  |  |  |  |  |  | tag_handler_closeunless,	/*UNLESS*/ | 
| 99 |  |  |  |  |  |  | tag_handler_unknown,	/*ELSIF*/ | 
| 100 |  |  |  |  |  |  | tag_handler_unknown,	/**/ | 
| 101 |  |  |  |  |  |  | }; | 
| 102 |  |  |  |  |  |  | static const tag_handler_func output_opentag_handler[]={ | 
| 103 |  |  |  |  |  |  | tag_handler_unknown,	/*Bad or unsupported tag*/ | 
| 104 |  |  |  |  |  |  | tag_handler_var,	/*VAR*/ | 
| 105 |  |  |  |  |  |  | tag_handler_include,	/*INCLUDE*/ | 
| 106 |  |  |  |  |  |  | tag_handler_loop,	/*LOOP*/ | 
| 107 |  |  |  |  |  |  | tag_handler_if,	/*IF*/ | 
| 108 |  |  |  |  |  |  | tag_handler_else,	/*ELSE*/ | 
| 109 |  |  |  |  |  |  | tag_handler_unless,	/*UNLESS*/ | 
| 110 |  |  |  |  |  |  | tag_handler_elsif,	/*ELSIF*/ | 
| 111 |  |  |  |  |  |  | tag_handler_unknown,	/**/ | 
| 112 |  |  |  |  |  |  | }; | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | static | 
| 115 |  |  |  |  |  |  | int | 
| 116 | 33109 |  |  |  |  |  | is_string(struct tmplpro_state *state, const char* pattern,const char* PATTERN) | 
| 117 |  |  |  |  |  |  | { | 
| 118 | 33109 |  |  |  |  |  | const char* cur_pos=state->cur_pos; | 
| 119 | 33109 |  |  |  |  |  | register const char* const next_to_end = state->next_to_end; | 
| 120 | 70443 | 100 |  |  |  |  | while (*pattern && cur_pos | 
|  |  | 50 |  |  |  |  |  | 
| 121 | 61915 | 100 |  |  |  |  | if (*pattern == *cur_pos || *PATTERN == *cur_pos) { | 
|  |  | 100 |  |  |  |  |  | 
| 122 | 37334 |  |  |  |  |  | pattern++; | 
| 123 | 37334 |  |  |  |  |  | PATTERN++; | 
| 124 | 37334 |  |  |  |  |  | cur_pos++; | 
| 125 |  |  |  |  |  |  | } else { | 
| 126 | 24581 |  |  |  |  |  | return 0; | 
| 127 |  |  |  |  |  |  | } | 
| 128 |  |  |  |  |  |  | } | 
| 129 | 8528 | 50 |  |  |  |  | if (cur_pos>=next_to_end) return 0; | 
| 130 | 8528 |  |  |  |  |  | state->cur_pos=cur_pos; | 
| 131 | 8528 |  |  |  |  |  | return 1; | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | static | 
| 135 |  |  |  |  |  |  | INLINE | 
| 136 |  |  |  |  |  |  | void | 
| 137 | 26246 |  |  |  |  |  | jump_over_space(struct tmplpro_state *state) | 
| 138 |  |  |  |  |  |  | { | 
| 139 | 26246 |  |  |  |  |  | register const char* const next_to_end = state->next_to_end; | 
| 140 | 32397 | 100 |  |  |  |  | while (isspace(*(state->cur_pos)) && state->cur_poscur_pos++;}; | 
|  |  | 50 |  |  |  |  |  | 
| 141 | 26246 |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | static | 
| 144 |  |  |  |  |  |  | INLINE | 
| 145 |  |  |  |  |  |  | void | 
| 146 |  |  |  |  |  |  | jump_to_char(struct tmplpro_state *state, char c) | 
| 147 |  |  |  |  |  |  | { | 
| 148 |  |  |  |  |  |  | register const char* const next_to_end = state->next_to_end; | 
| 149 |  |  |  |  |  |  | while (c!=*(state->cur_pos) && state->cur_poscur_pos++;}; | 
| 150 |  |  |  |  |  |  | } | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | static | 
| 153 |  |  |  |  |  |  | PSTRING | 
| 154 | 2411 |  |  |  |  |  | read_tag_parameter_value (struct tmplpro_state *state) | 
| 155 |  |  |  |  |  |  | { | 
| 156 |  |  |  |  |  |  | PSTRING modifier_value; | 
| 157 |  |  |  |  |  |  | char cur_char; | 
| 158 | 2411 |  |  |  |  |  | char quote_char=0; | 
| 159 |  |  |  |  |  |  | register const char* cur_pos; | 
| 160 | 2411 |  |  |  |  |  | const char* const next_to_end=state->next_to_end; | 
| 161 | 2411 |  |  |  |  |  | jump_over_space(state); | 
| 162 | 2411 |  |  |  |  |  | cur_pos=state->cur_pos; | 
| 163 | 2411 |  |  |  |  |  | cur_char=*cur_pos; | 
| 164 | 2411 | 100 |  |  |  |  | if (('"'==cur_char) || ('\''==cur_char)) { | 
|  |  | 100 |  |  |  |  |  | 
| 165 | 1518 |  |  |  |  |  | quote_char=*cur_pos; | 
| 166 | 1518 |  |  |  |  |  | cur_pos++; | 
| 167 |  |  |  |  |  |  | } | 
| 168 | 2411 |  |  |  |  |  | modifier_value.begin=cur_pos; | 
| 169 | 2411 |  |  |  |  |  | cur_char=*cur_pos; | 
| 170 | 2411 | 100 |  |  |  |  | if (quote_char) { | 
| 171 | 14298 | 100 |  |  |  |  | while (quote_char!=cur_char | 
| 172 |  |  |  |  |  |  | #ifdef COMPAT_ON_BROKEN_QUOTE | 
| 173 |  |  |  |  |  |  | /* compatibility mode; HTML::Template doesn't allow '>' inside quotes */ | 
| 174 |  |  |  |  |  |  | && ('>' != quote_char) | 
| 175 |  |  |  |  |  |  | #endif | 
| 176 | 12782 | 100 |  |  |  |  | && cur_pos | 
| 177 | 12780 |  |  |  |  |  | cur_pos++; | 
| 178 | 12780 |  |  |  |  |  | cur_char=*cur_pos; | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  | } else { | 
| 181 | 5132 | 100 |  |  |  |  | while ('>'!=cur_char && ! isspace(cur_char) && cur_pos | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 182 | 4239 |  |  |  |  |  | cur_pos++; | 
| 183 | 4239 |  |  |  |  |  | cur_char=*cur_pos; | 
| 184 |  |  |  |  |  |  | } | 
| 185 |  |  |  |  |  |  | } | 
| 186 | 2411 | 100 |  |  |  |  | if (cur_pos>=next_to_end) { | 
| 187 | 2 |  |  |  |  |  | log_state(state,TMPL_LOG_ERROR,"quote char %c at pos " MOD_TD " is not terminated\n", | 
| 188 | 4 |  |  |  |  |  | quote_char,TO_PTRDIFF_T(state->cur_pos - state->top)); | 
| 189 | 2 |  |  |  |  |  | modifier_value.endnext=modifier_value.begin; | 
| 190 | 2 |  |  |  |  |  | jump_over_space(state); | 
| 191 | 2 |  |  |  |  |  | return modifier_value; | 
| 192 |  |  |  |  |  |  | } | 
| 193 | 2409 |  |  |  |  |  | modifier_value.endnext=cur_pos; | 
| 194 | 2409 | 100 |  |  |  |  | if (quote_char) { | 
| 195 | 1516 | 50 |  |  |  |  | if (quote_char==*cur_pos) { | 
| 196 | 1516 |  |  |  |  |  | cur_pos++; | 
| 197 |  |  |  |  |  |  | } else { | 
| 198 | 0 |  |  |  |  |  | log_state(state,TMPL_LOG_ERROR,"found %c instead of end quote %c at pos " MOD_TD "\n", | 
| 199 | 0 |  |  |  |  |  | *cur_pos,quote_char,TO_PTRDIFF_T(cur_pos - state->top)); | 
| 200 |  |  |  |  |  |  | } | 
| 201 |  |  |  |  |  |  | } | 
| 202 | 2409 |  |  |  |  |  | state->cur_pos=cur_pos; | 
| 203 |  |  |  |  |  |  | /* if (debuglevel) log_state(state,TMPL_LOG_DEBUG2," at pos " MOD_TD "",TO_PTRDIFF_T(state->cur_pos-state->top)); */ | 
| 204 | 2409 |  |  |  |  |  | jump_over_space(state); | 
| 205 | 2411 |  |  |  |  |  | return modifier_value; | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  | static | 
| 209 |  |  |  |  |  |  | int | 
| 210 | 17904 |  |  |  |  |  | try_tag_parameter (struct tmplpro_state *state,const char *modifier,const char *MODIFIER) | 
| 211 |  |  |  |  |  |  | { | 
| 212 | 17904 |  |  |  |  |  | const char* const initial_pos=state->cur_pos; | 
| 213 | 17904 |  |  |  |  |  | jump_over_space(state); | 
| 214 | 17904 | 100 |  |  |  |  | if (is_string(state, modifier, MODIFIER)) { | 
| 215 | 1738 |  |  |  |  |  | jump_over_space(state); | 
| 216 | 1738 | 100 |  |  |  |  | if ('='==*(state->cur_pos)) { | 
| 217 | 1736 |  |  |  |  |  | state->cur_pos++; | 
| 218 | 1736 |  |  |  |  |  | jump_over_space(state); | 
| 219 | 1736 |  |  |  |  |  | return 1; | 
| 220 |  |  |  |  |  |  | } | 
| 221 |  |  |  |  |  |  | } | 
| 222 | 16168 |  |  |  |  |  | state->cur_pos=initial_pos; | 
| 223 | 16168 |  |  |  |  |  | return 0; | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | static | 
| 227 |  |  |  |  |  |  | void | 
| 228 | 2866 |  |  |  |  |  | try_tmpl_var_options (struct tmplpro_state *state, int tag_type, PSTRING* TagOptVal) | 
| 229 |  |  |  |  |  |  | { | 
| 230 |  |  |  |  |  |  | int i; | 
| 231 | 2866 |  |  |  |  |  | int opt_found = 1; | 
| 232 |  |  |  |  |  |  | /* reading parameter */ | 
| 233 | 7342 | 100 |  |  |  |  | while (opt_found) { | 
| 234 | 4476 |  |  |  |  |  | int found_in_loop=0; | 
| 235 | 22380 | 100 |  |  |  |  | for (i=MIN_TAG_OPT; i<=MAX_TAG_OPT; i++) { | 
| 236 | 17904 | 100 |  |  |  |  | if ( | 
| 237 |  |  |  |  |  |  | /* we will complain about syntax errors later; | 
| 238 |  |  |  |  |  |  | tag_has_opt[tag_type][i] && */ | 
| 239 | 17904 |  |  |  |  |  | try_tag_parameter(state, tagopt[i], TAGOPT[i])) { | 
| 240 | 1736 |  |  |  |  |  | TagOptVal[i] = read_tag_parameter_value(state); | 
| 241 | 1736 |  |  |  |  |  | found_in_loop=1; | 
| 242 | 1736 | 100 |  |  |  |  | if (debuglevel) log_state(state,TMPL_LOG_DEBUG,"in tag %s: found option %s=%.*s\n", TAGNAME[tag_type], TAGOPT[i],(int)(TagOptVal[i].endnext-TagOptVal[i].begin),TagOptVal[i].begin); | 
| 243 |  |  |  |  |  |  | } | 
| 244 |  |  |  |  |  |  | } | 
| 245 | 4476 | 100 |  |  |  |  | if (!found_in_loop) opt_found = 0; | 
| 246 |  |  |  |  |  |  | } | 
| 247 | 2866 |  |  |  |  |  | } | 
| 248 |  |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | static | 
| 250 |  |  |  |  |  |  | void | 
| 251 | 3395 |  |  |  |  |  | process_tmpl_tag(struct tmplpro_state *state) | 
| 252 |  |  |  |  |  |  | { | 
| 253 | 3395 |  |  |  |  |  | const int is_tag_closed=state->is_tag_closed; | 
| 254 |  |  |  |  |  |  |  | 
| 255 | 3395 |  |  |  |  |  | int tag_type=HTML_TEMPLATE_BAD_TAG; | 
| 256 |  |  |  |  |  |  | PSTRING TagOptVal[MAX_TAG_OPT+1]; | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | int i; | 
| 259 | 16975 | 100 |  |  |  |  | for (i=MIN_TAG_OPT; i<=MAX_TAG_OPT; i++) { | 
| 260 | 13580 |  |  |  |  |  | TagOptVal[i].begin = NULL; | 
| 261 | 13580 |  |  |  |  |  | TagOptVal[i].endnext = NULL; | 
| 262 |  |  |  |  |  |  | } | 
| 263 |  |  |  |  |  |  |  | 
| 264 | 9398 | 50 |  |  |  |  | for (i=HTML_TEMPLATE_FIRST_TAG_USED; i<=HTML_TEMPLATE_LAST_TAG_USED; i++) { | 
| 265 | 9398 | 100 |  |  |  |  | if (is_string(state, tagname[i], TAGNAME[i])) { | 
| 266 | 3395 |  |  |  |  |  | tag_type=i; | 
| 267 | 3395 |  |  |  |  |  | state->tag=tag_type; | 
| 268 | 3395 | 100 |  |  |  |  | if (debuglevel) { | 
| 269 | 5 | 100 |  |  |  |  | if (is_tag_closed) { | 
| 270 | 1 |  |  |  |  |  | tmpl_log(TMPL_LOG_DEBUG, "found  at pos " MOD_TD "\n",TAGNAME[i], TO_PTRDIFF_T(state->cur_pos-state->top)); | 
| 271 |  |  |  |  |  |  | } else { | 
| 272 | 4 |  |  |  |  |  | tmpl_log(TMPL_LOG_DEBUG, "found  at pos " MOD_TD "\n",TAGNAME[i], TO_PTRDIFF_T(state->cur_pos-state->top)); | 
| 273 |  |  |  |  |  |  | } | 
| 274 |  |  |  |  |  |  | } | 
| 275 | 3395 |  |  |  |  |  | break; | 
| 276 |  |  |  |  |  |  | } | 
| 277 |  |  |  |  |  |  | } | 
| 278 | 3395 | 50 |  |  |  |  | if (HTML_TEMPLATE_BAD_TAG==tag_type) { | 
| 279 | 0 |  |  |  |  |  | state->param->found_syntax_error=1; | 
| 280 | 0 |  |  |  |  |  | log_state(state,TMPL_LOG_ERROR, "found bad/unsupported tag at pos " MOD_TD "\n", TO_PTRDIFF_T(state->cur_pos-state->top)); | 
| 281 |  |  |  |  |  |  | /* TODO: flush its data ---  */ | 
| 282 | 0 |  |  |  |  |  | state->cur_pos++; | 
| 283 | 0 |  |  |  |  |  | return; | 
| 284 |  |  |  |  |  |  | } | 
| 285 |  |  |  |  |  |  |  | 
| 286 | 3395 | 100 |  |  |  |  | if (is_tag_closed && !tag_can_be_closed[tag_type]) { | 
|  |  | 50 |  |  |  |  |  | 
| 287 | 0 |  |  |  |  |  | state->param->found_syntax_error=1; | 
| 288 | 0 |  |  |  |  |  | log_state(state,TMPL_LOG_ERROR, "incorrect closed tag  at pos " MOD_TD "\n", | 
| 289 | 0 |  |  |  |  |  | TAGNAME[tag_type], TO_PTRDIFF_T(state->cur_pos-state->top)); | 
| 290 |  |  |  |  |  |  | } | 
| 291 |  |  |  |  |  |  |  | 
| 292 | 3395 | 100 |  |  |  |  | if (is_tag_closed || ! tag_has_opt[tag_type][TAG_OPT_NAME]) { | 
|  |  | 100 |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | /* tag has no parameter */ | 
| 294 |  |  |  |  |  |  | #ifdef COMPAT_ALLOW_NAME_IN_CLOSING_TAG | 
| 295 |  |  |  |  |  |  | /* requested compatibility mode | 
| 296 |  |  |  |  |  |  | to try reading NAME inside | 
| 297 |  |  |  |  |  |  | (useful for comments?) */ | 
| 298 |  |  |  |  |  |  | try_tag_parameter(state, tagopt[TAG_OPT_NAME], TAGOPT[TAG_OPT_NAME]); | 
| 299 |  |  |  |  |  |  | read_tag_parameter_value(state); | 
| 300 |  |  |  |  |  |  | #endif | 
| 301 |  |  |  |  |  |  | } else { | 
| 302 | 2191 |  |  |  |  |  | try_tmpl_var_options(state, tag_type, TagOptVal); | 
| 303 |  |  |  |  |  |  | /* suport for short syntax */ | 
| 304 | 2191 | 100 |  |  |  |  | if (TagOptVal[TAG_OPT_NAME].begin == NULL && | 
|  |  | 50 |  |  |  |  |  | 
| 305 | 1234 | 100 |  |  |  |  | tag_has_opt[tag_type][TAG_OPT_NAME] && | 
| 306 | 1201 | 100 |  |  |  |  | (!tag_has_opt[tag_type][TAG_OPT_EXPR] || TagOptVal[TAG_OPT_EXPR].begin == NULL )) { | 
| 307 | 675 |  |  |  |  |  | TagOptVal[TAG_OPT_NAME]=read_tag_parameter_value(state); | 
| 308 | 675 |  |  |  |  |  | try_tmpl_var_options(state, tag_type, TagOptVal); | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  |  | 
| 311 | 2191 | 100 |  |  |  |  | if (TagOptVal[TAG_OPT_NAME].begin == NULL && | 
|  |  | 50 |  |  |  |  |  | 
| 312 | 559 | 50 |  |  |  |  | tag_has_opt[tag_type][TAG_OPT_NAME] && | 
| 313 | 559 | 50 |  |  |  |  | (!tag_has_opt[tag_type][TAG_OPT_EXPR] || TagOptVal[TAG_OPT_EXPR].begin == NULL )) { | 
| 314 | 0 |  |  |  |  |  | state->param->found_syntax_error=1; | 
| 315 | 0 |  |  |  |  |  | log_state(state,TMPL_LOG_ERROR,"NAME or EXPR is required for TMPL_%s\n", TAGNAME[tag_type]); | 
| 316 |  |  |  |  |  |  | } | 
| 317 | 10955 | 100 |  |  |  |  | for (i=MIN_TAG_OPT; i<=MAX_TAG_OPT; i++) { | 
| 318 | 8764 | 100 |  |  |  |  | if (TagOptVal[i].begin!=NULL && ! tag_has_opt[tag_type][i]) { | 
|  |  | 50 |  |  |  |  |  | 
| 319 | 0 |  |  |  |  |  | state->param->found_syntax_error=1; | 
| 320 | 0 |  |  |  |  |  | log_state(state,TMPL_LOG_ERROR,"TMPL_%s does not support %s= option\n", TAGNAME[tag_type], TAGOPT[i]); | 
| 321 |  |  |  |  |  |  | } | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 3395 | 100 |  |  |  |  | if (state->is_tag_commented) { | 
| 326 |  |  |  |  |  |  | /* try read comment end */ | 
| 327 |  |  |  |  |  |  | /* jump_over_space(state); it should be already done :( */ | 
| 328 | 18 |  |  |  |  |  | jump_over_space(state); | 
| 329 | 18 | 50 |  |  |  |  | if (state->cur_posnext_to_end-2 && '-'==*(state->cur_pos) && '-'==*(state->cur_pos+1)) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 330 | 18 |  |  |  |  |  | state->cur_pos+=2; | 
| 331 |  |  |  |  |  |  | } | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  | /* template tags could also be decorated as xml  */ | 
| 334 | 3395 | 100 |  |  |  |  | if (!is_tag_closed && '/'==*(state->cur_pos)) state->cur_pos++; | 
|  |  | 100 |  |  |  |  |  | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 3395 | 100 |  |  |  |  | if ('>'==*(state->cur_pos)) { | 
| 337 | 3392 |  |  |  |  |  | state->cur_pos++; | 
| 338 |  |  |  |  |  |  | } else { | 
| 339 | 3 |  |  |  |  |  | state->param->found_syntax_error=1; | 
| 340 | 3 |  |  |  |  |  | log_state(state,TMPL_LOG_ERROR,"end tag:found %c instead of > at pos " MOD_TD "\n", | 
| 341 | 9 |  |  |  |  |  | *state->cur_pos, TO_PTRDIFF_T(state->cur_pos-state->top)); | 
| 342 |  |  |  |  |  |  | } | 
| 343 |  |  |  |  |  |  | /* flush run chars (if in SHOW mode) */ | 
| 344 | 3395 | 100 |  |  |  |  | if (state->is_visible) { | 
| 345 | 2486 |  |  |  |  |  | (state->param->WriterFuncPtr)(state->param->ext_writer_state,state->last_processed_pos,state->tag_start); | 
| 346 | 2486 |  |  |  |  |  | state->last_processed_pos=state->cur_pos; | 
| 347 |  |  |  |  |  |  | } | 
| 348 | 3395 | 100 |  |  |  |  | if (is_tag_closed) { | 
| 349 | 798 |  |  |  |  |  | output_closetag_handler[tag_type](state,TagOptVal); | 
| 350 |  |  |  |  |  |  | } else { | 
| 351 | 3395 |  |  |  |  |  | output_opentag_handler[tag_type](state,TagOptVal); | 
| 352 |  |  |  |  |  |  | } | 
| 353 |  |  |  |  |  |  | } | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | /* max offset to ensure we are not out of file when try |