diff options
Diffstat (limited to 'src/renderer.c')
-rw-r--r-- | src/renderer.c | 99 |
1 files changed, 89 insertions, 10 deletions
diff --git a/src/renderer.c b/src/renderer.c index 3061c43..5e07b0c 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -1,6 +1,6 @@ /* * blogc: A blog compiler. - * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * Copyright (C) 2015-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br> * * This program can be distributed under the terms of the BSD License. * See the file LICENSE. @@ -58,8 +58,16 @@ blogc_format_date(const char *date, b_trie_t *global, b_trie_t *local) char* -blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local) +blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local, + b_slist_t *foreach_var) { + if (0 == strcmp(name, "FOREACH_ITEM")) { + if (foreach_var != NULL && foreach_var->data != NULL) { + return b_strdup(foreach_var->data); + } + return NULL; + } + char *var = NULL; bool must_format = false; if (b_str_ends_with(name, "_FORMATTED")) { @@ -88,6 +96,28 @@ blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local) } +b_slist_t* +blogc_split_list_variable(const char *name, b_trie_t *global, b_trie_t *local) +{ + const char *value = blogc_get_variable(name, global, local); + if (value == NULL) + return NULL; + + b_slist_t *rv = NULL; + + char **tmp = b_str_split(value, ' ', 0); + for (unsigned int i = 0; tmp[i] != NULL; i++) { + if (tmp[i][0] != '\0') // ignore empty strings + rv = b_slist_append(rv, tmp[i]); + else + free(tmp[i]); + } + free(tmp); + + return rv; +} + + char* blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing) { @@ -104,7 +134,10 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing char *defined = NULL; unsigned int if_count = 0; - unsigned int if_skip = 0; + + b_slist_t *foreach_var = NULL; + b_slist_t *foreach_var_start = NULL; + b_slist_t *foreach_start = NULL; bool if_not = false; bool inside_block = false; @@ -175,7 +208,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing case BLOGC_TEMPLATE_VARIABLE_STMT: if (stmt->value != NULL) { config_value = blogc_format_variable(stmt->value, - config, inside_block ? tmp_source : NULL); + config, inside_block ? tmp_source : NULL, foreach_var); if (config_value != NULL) { b_string_append(str, config_value); free(config_value); @@ -203,10 +236,11 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing case BLOGC_TEMPLATE_IF_STMT: case BLOGC_TEMPLATE_IFDEF_STMT: + if_count = 0; defined = NULL; if (stmt->value != NULL) defined = blogc_format_variable(stmt->value, config, - inside_block ? tmp_source : NULL); + inside_block ? tmp_source : NULL, foreach_var); evaluate = false; if (stmt->op != 0) { // Strings that start with a '"' are actually strings, the @@ -223,7 +257,8 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing } else { defined2 = blogc_format_variable(stmt->value2, - config, inside_block ? tmp_source : NULL); + config, inside_block ? tmp_source : NULL, + foreach_var); } } @@ -248,7 +283,6 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing evaluate = true; } if (!evaluate) { - if_skip = if_count; // at this point we can just skip anything, counting the // number of 'if's, to know how many 'endif's we need to @@ -264,11 +298,11 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing continue; } if (stmt->type == BLOGC_TEMPLATE_ENDIF_STMT) { - if (if_count > if_skip) { + if (if_count > 0) { if_count--; continue; } - if (if_count == if_skip) + if (if_count == 0) break; } } @@ -279,11 +313,56 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing break; case BLOGC_TEMPLATE_ENDIF_STMT: - if_count--; + if (if_count > 0) + if_count--; + break; + + case BLOGC_TEMPLATE_FOREACH_STMT: + if (foreach_var_start == NULL) { + if (stmt->value != NULL) + foreach_var_start = blogc_split_list_variable(stmt->value, + config, inside_block ? tmp_source : NULL); + + if (foreach_var_start != NULL) { + foreach_var = foreach_var_start; + foreach_start = tmp; + } + else { + + // we can just skip anything and walk until the next + // 'endforeach' + while (stmt->type != BLOGC_TEMPLATE_ENDFOREACH_STMT) { + tmp = tmp->next; + stmt = tmp->data; + } + break; + } + } + + if (foreach_var == NULL) { + foreach_start = tmp; + foreach_var = foreach_var_start; + } + break; + + case BLOGC_TEMPLATE_ENDFOREACH_STMT: + if (foreach_start != NULL && foreach_var != NULL) { + foreach_var = foreach_var->next; + if (foreach_var != NULL) { + tmp = foreach_start; + continue; + } + } + foreach_start = NULL; + b_slist_free_full(foreach_var_start, free); + foreach_var_start = NULL; break; } tmp = tmp->next; } + // no need to free temporary variables here. the template parser makes sure + // that templates are sane and statements are closed. + return b_string_free(str, false); } |