diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/template-parser.c | 136 | ||||
-rw-r--r-- | src/template-parser.h | 3 |
2 files changed, 126 insertions, 13 deletions
diff --git a/src/template-parser.c b/src/template-parser.c index d25ea0f..6eb65b6 100644 --- a/src/template-parser.c +++ b/src/template-parser.c @@ -25,8 +25,12 @@ typedef enum { TEMPLATE_BLOCK_TYPE, TEMPLATE_BLOCK_BLOCK_TYPE_START, TEMPLATE_BLOCK_BLOCK_TYPE, - TEMPLATE_BLOCK_IFDEF_START, - TEMPLATE_BLOCK_IFDEF_VARIABLE, + TEMPLATE_BLOCK_IF_START, + TEMPLATE_BLOCK_IF_VARIABLE, + TEMPLATE_BLOCK_IF_OPERATOR_START, + TEMPLATE_BLOCK_IF_OPERATOR, + TEMPLATE_BLOCK_IF_OPERAND_START, + TEMPLATE_BLOCK_IF_OPERAND, TEMPLATE_BLOCK_END, TEMPLATE_VARIABLE_START, TEMPLATE_VARIABLE, @@ -52,6 +56,10 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) size_t current = 0; size_t start = 0; size_t end = 0; + size_t op_start = 0; + size_t op_end = 0; + size_t start2 = 0; + size_t end2 = 0; unsigned int if_count = 0; @@ -73,6 +81,8 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) stmt = b_malloc(sizeof(blogc_template_stmt_t)); stmt->type = type; stmt->value = b_strndup(src + start, src_len - start); + stmt->op = NULL; + stmt->value2 = NULL; stmts = b_slist_append(stmts, stmt); stmt = NULL; } @@ -92,6 +102,8 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) stmt = b_malloc(sizeof(blogc_template_stmt_t)); stmt->type = type; stmt->value = b_strndup(src + start, end - start); + stmt->op = NULL; + stmt->value2 = NULL; stmts = b_slist_append(stmts, stmt); stmt = NULL; } @@ -117,7 +129,9 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) if (c >= 'a' && c <= 'z') break; if (c == ' ') { - if (0 == strncmp("block", src + start, current - start)) { + if ((current - start == 5) && + (0 == strncmp("block", src + start, current - start))) + { if (block_state == BLOCK_CLOSED) { state = TEMPLATE_BLOCK_BLOCK_TYPE_START; type = BLOGC_TEMPLATE_BLOCK_STMT; @@ -128,7 +142,9 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) src, src_len, current, "Blocks can't be nested."); break; } - else if (0 == strncmp("endblock", src + start, current - start)) { + else if ((current - start == 8) && + (0 == strncmp("endblock", src + start, current - start))) + { if (block_state != BLOCK_CLOSED) { state = TEMPLATE_BLOCK_END; type = BLOGC_TEMPLATE_ENDBLOCK_STMT; @@ -140,21 +156,36 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) "'endblock' statement without an open 'block' statement."); break; } - else if (0 == strncmp("ifdef", src + start, current - start)) { - state = TEMPLATE_BLOCK_IFDEF_START; + else if ((current - start == 5) && + (0 == strncmp("ifdef", src + start, current - start))) + { + state = TEMPLATE_BLOCK_IF_START; type = BLOGC_TEMPLATE_IFDEF_STMT; start = current; if_count++; break; } - else if (0 == strncmp("ifndef", src + start, current - start)) { - state = TEMPLATE_BLOCK_IFDEF_START; + else if ((current - start == 6) && + (0 == strncmp("ifndef", src + start, current - start))) + { + state = TEMPLATE_BLOCK_IF_START; type = BLOGC_TEMPLATE_IFNDEF_STMT; start = current; if_count++; break; } - else if (0 == strncmp("endif", src + start, current - start)) { + else if ((current - start == 2) && + (0 == strncmp("if", src + start, current - start))) + { + state = TEMPLATE_BLOCK_IF_START; + type = BLOGC_TEMPLATE_IF_STMT; + start = current; + if_count++; + break; + } + else if ((current - start == 5) && + (0 == strncmp("endif", src + start, current - start))) + { if (if_count > 0) { state = TEMPLATE_BLOCK_END; type = BLOGC_TEMPLATE_ENDIF_STMT; @@ -216,11 +247,11 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) "and 'listing_once'."); break; - case TEMPLATE_BLOCK_IFDEF_START: + case TEMPLATE_BLOCK_IF_START: if (c == ' ') break; if (c >= 'A' && c <= 'Z') { - state = TEMPLATE_BLOCK_IFDEF_VARIABLE; + state = TEMPLATE_BLOCK_IF_VARIABLE; start = current; break; } @@ -229,12 +260,15 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) "Invalid variable name. Must begin with uppercase letter."); break; - case TEMPLATE_BLOCK_IFDEF_VARIABLE: + case TEMPLATE_BLOCK_IF_VARIABLE: if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') break; if (c == ' ') { end = current; - state = TEMPLATE_BLOCK_END; + if (type == BLOGC_TEMPLATE_IF_STMT) + state = TEMPLATE_BLOCK_IF_OPERATOR_START; + else + state = TEMPLATE_BLOCK_END; break; } *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, @@ -243,6 +277,45 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) "or '_'."); break; + case TEMPLATE_BLOCK_IF_OPERATOR_START: + if (c == ' ') { + break; + } + state = TEMPLATE_BLOCK_IF_OPERATOR; + op_start = current; + break; + + case TEMPLATE_BLOCK_IF_OPERATOR: + if (c != ' ') + break; + state = TEMPLATE_BLOCK_IF_OPERAND_START; + op_end = current; + break; + + case TEMPLATE_BLOCK_IF_OPERAND_START: + if (c == ' ') + break; + if (c != '"') { + op_start = 0; + op_end = 0; + *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, + src_len, current, + "Invalid 'if' operand. Must be double-quoted static string."); + break; + } + state = TEMPLATE_BLOCK_IF_OPERAND; + start2 = current + 1; + break; + + case TEMPLATE_BLOCK_IF_OPERAND: + if (c != '"') + break; + if (c == '"' && src[current - 1] == '\\') + break; + state = TEMPLATE_BLOCK_END; + end2 = current; + break; + case TEMPLATE_BLOCK_END: if (c == ' ') break; @@ -302,11 +375,44 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) case TEMPLATE_CLOSE_BRACKET: if (c == '}') { + if (op_end > op_start) { + if ((!((op_end - op_start == 1) && + (0 == strncmp("<", src + op_start, op_end - op_start)))) && + (!((op_end - op_start == 1) && + (0 == strncmp(">", src + op_start, op_end - op_start)))) && + (!((op_end - op_start == 2) && + (0 == strncmp("<=", src + op_start, op_end - op_start)))) && + (!((op_end - op_start == 2) && + (0 == strncmp(">=", src + op_start, op_end - op_start)))) && + (!((op_end - op_start == 2) && + (0 == strncmp("==", src + op_start, op_end - op_start)))) && + (!((op_end - op_start == 2) && + (0 == strncmp("!=", src + op_start, op_end - op_start))))) + { + *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, + src, src_len, op_start, + "Invalid 'if' operator. Must be '<', '>', " + "'<=', '>=', '==' or '!='."); + break; + } + } stmt = b_malloc(sizeof(blogc_template_stmt_t)); stmt->type = type; stmt->value = NULL; + stmt->op = NULL; + stmt->value2 = NULL; + if (op_end > op_start) { + stmt->op = b_strndup(src + op_start, op_end - op_start); + op_start = 0; + op_end = 0; + } if (end > start) stmt->value = b_strndup(src + start, end - start); + if (end2 > start2) { + stmt->value2 = b_strndup(src + start2, end2 - start2); + start2 = 0; + end2 = 0; + } stmts = b_slist_append(stmts, stmt); stmt = NULL; state = TEMPLATE_START; @@ -355,7 +461,11 @@ blogc_template_free_stmts(b_slist_t *stmts) { for (b_slist_t *tmp = stmts; tmp != NULL; tmp = tmp->next) { blogc_template_stmt_t *data = tmp->data; + if (data == NULL) + continue; free(data->value); + free(data->op); + free(data->value2); free(data); } b_slist_free(stmts); diff --git a/src/template-parser.h b/src/template-parser.h index 88c9ccf..b9213e2 100644 --- a/src/template-parser.h +++ b/src/template-parser.h @@ -15,6 +15,7 @@ typedef enum { BLOGC_TEMPLATE_IFDEF_STMT = 1, BLOGC_TEMPLATE_IFNDEF_STMT, + BLOGC_TEMPLATE_IF_STMT, BLOGC_TEMPLATE_ENDIF_STMT, BLOGC_TEMPLATE_BLOCK_STMT, BLOGC_TEMPLATE_ENDBLOCK_STMT, @@ -25,6 +26,8 @@ typedef enum { typedef struct { blogc_template_stmt_type_t type; char *value; + char *value2; + char *op; } blogc_template_stmt_t; b_slist_t* blogc_template_parse(const char *src, size_t src_len, |