From 5205db347cb9f56187c2ad5e767281a7a4016533 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Mon, 27 Apr 2015 00:10:26 -0300 Subject: added global variable support --- src/main.c | 54 ++++++++++++++++++++++++++++------ src/renderer.c | 80 +++++++++++++++++++++++++++++++-------------------- src/renderer.h | 3 +- src/template-parser.c | 46 ++++++++--------------------- 4 files changed, 108 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/main.c b/src/main.c index e43b71b..0680728 100644 --- a/src/main.c +++ b/src/main.c @@ -36,24 +36,25 @@ blogc_print_help(void) { printf( "usage:\n" - " blogc [-h] [-v] [-l] -t TEMPLATE [-o OUTPUT] SOURCE [SOURCE ...] - A blog compiler.\n" + " blogc [-h] [-v] [-l] [-D KEY=VALUE ...] -t TEMPLATE [-o OUTPUT] SOURCE [SOURCE ...] - A blog compiler.\n" "\n" "positional arguments:\n" - " SOURCE source file(s)\n" + " SOURCE source file(s)\n" "\n" "optional arguments:\n" - " -h show this help message and exit\n" - " -v show version and exit\n" - " -l build listing page, from multiple source files\n" - " -t TEMPLATE template file\n" - " -o OUTPUT output file\n"); + " -h show this help message and exit\n" + " -v show version and exit\n" + " -l build listing page, from multiple source files\n" + " -D KEY=VALUE set global configuration parameter\n" + " -t TEMPLATE template file\n" + " -o OUTPUT output file\n"); } static void blogc_print_usage(void) { - printf("usage: blogc [-h] [-v] [-l] -t TEMPLATE [-o OUTPUT] SOURCE [SOURCE ...]\n"); + printf("usage: blogc [-h] [-v] [-l] [-D KEY=VALUE ...] -t TEMPLATE [-o OUTPUT] SOURCE [SOURCE ...]\n"); } @@ -100,9 +101,14 @@ main(int argc, char **argv) bool listing = false; char *template = NULL; char *output = NULL; + char *tmp = NULL; + char **pieces = NULL; + b_slist_t *sources = NULL; + b_trie_t *config = b_trie_new(free); for (unsigned int i = 1; i < argc; i++) { + tmp = NULL; if (argv[i][0] == '-') { switch (argv[i][1]) { case 'h': @@ -126,6 +132,35 @@ main(int argc, char **argv) else if (i + 1 < argc) output = b_strdup(argv[++i]); break; + case 'D': + if (argv[i][2] != '\0') + tmp = argv[i] + 2; + else if (i + 1 < argc) + tmp = argv[++i]; + if (tmp != NULL) { + pieces = b_str_split(tmp, '=', 2); + if (b_strv_length(pieces) != 2) { + fprintf(stderr, "blogc: error: invalid value for " + "-D (must have an '='): %s\n", tmp); + b_strv_free(pieces); + rv = 2; + goto cleanup; + } + for (unsigned int j = 0; pieces[0][j] != '\0'; j++) { + if (!(pieces[0][j] >= 'A' && pieces[0][j] <= 'Z')) { + fprintf(stderr, "blogc: error: invalid value " + "for -D (configuration key must be uppercase): " + "%s\n", pieces[0]); + b_strv_free(pieces); + rv = 2; + goto cleanup; + } + } + b_trie_insert(config, pieces[0], b_strdup(pieces[1])); + b_strv_free(pieces); + pieces = NULL; + } + break; default: blogc_print_usage(); fprintf(stderr, "blogc: error: invalid argument: -%c\n", @@ -177,7 +212,7 @@ main(int argc, char **argv) goto cleanup3; } - char *out = blogc_render(l, s, listing); + char *out = blogc_render(l, s, config, listing); bool write_to_stdout = (output == NULL || (0 == strcmp(output, "-"))); @@ -206,6 +241,7 @@ cleanup2: blogc_template_free_stmts(l); blogc_error_free(err); cleanup: + b_trie_free(config); free(template); free(output); b_slist_free_full(sources, free); diff --git a/src/renderer.c b/src/renderer.c index 92fa7d4..905c42f 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -18,7 +18,7 @@ char* -blogc_render(b_slist_t *tmpl, b_slist_t *sources, bool listing) +blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing) { if (tmpl == NULL || sources == NULL) return NULL; @@ -35,6 +35,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, bool listing) unsigned int if_skip = 0; bool if_not = false; + bool defined = false; b_slist_t *tmp = tmpl; while (tmp != NULL) { @@ -86,11 +87,25 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, bool listing) break; case BLOGC_TEMPLATE_VARIABLE_STMT: - if (stmt->value != NULL && tmp_source != NULL) { - config_value = b_trie_lookup(tmp_source, stmt->value); - if (config_value != NULL) - b_string_append(str, config_value); - break; + if (stmt->value != NULL) { + + // try local config first + if (tmp_source != NULL) { + config_value = b_trie_lookup(tmp_source, stmt->value); + if (config_value != NULL) { + b_string_append(str, config_value); + break; + } + } + + // if not found, try global config + if (config != NULL) { + config_value = b_trie_lookup(config, stmt->value); + if (config_value != NULL) { + b_string_append(str, config_value); + break; + } + } } break; @@ -110,36 +125,39 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, bool listing) if_not = true; case BLOGC_TEMPLATE_IF_STMT: - if (stmt->value != NULL && tmp_source != NULL) { - if ((!if_not && (b_trie_lookup(tmp_source, stmt->value) == NULL)) || - (if_not && (b_trie_lookup(tmp_source, stmt->value) != NULL))) - { - 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 - // skip as well. - while (1) { - tmp = tmp->next; - stmt = tmp->data; - if ((stmt->type == BLOGC_TEMPLATE_IF_STMT) || - (stmt->type == BLOGC_TEMPLATE_IF_NOT_STMT)) - { - if_count++; + defined = false; + if (stmt->value != NULL) { + if (tmp_source != NULL && b_trie_lookup(tmp_source, stmt->value) != NULL) + defined = true; + if (config != NULL && b_trie_lookup(config, stmt->value) != NULL) + defined = true; + } + if ((!if_not && !defined) || (if_not && defined)) { + 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 + // skip as well. + while (1) { + tmp = tmp->next; + stmt = tmp->data; + if ((stmt->type == BLOGC_TEMPLATE_IF_STMT) || + (stmt->type == BLOGC_TEMPLATE_IF_NOT_STMT)) + { + if_count++; + continue; + } + if (stmt->type == BLOGC_TEMPLATE_ENDIF_STMT) { + if (if_count > if_skip) { + if_count--; continue; } - if (stmt->type == BLOGC_TEMPLATE_ENDIF_STMT) { - if (if_count > if_skip) { - if_count--; - continue; - } - if (if_count == if_skip) - break; - } + if (if_count == if_skip) + break; } } - if_not = false; } + if_not = false; break; case BLOGC_TEMPLATE_ENDIF_STMT: diff --git a/src/renderer.h b/src/renderer.h index a6b7a2c..c9a0ed1 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -12,6 +12,7 @@ #include #include "utils/utils.h" -char* blogc_render(b_slist_t *tmpl, b_slist_t *sources, bool listing); +char* blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, + bool listing); #endif /* _RENDERER_H */ diff --git a/src/template-parser.c b/src/template-parser.c index 69402cf..a91182f 100644 --- a/src/template-parser.c +++ b/src/template-parser.c @@ -143,36 +143,22 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) break; } else if (0 == strncmp("if", src + start, current - start)) { - if (block_state == BLOCK_ENTRY || block_state == BLOCK_LISTING) { - state = TEMPLATE_BLOCK_IF_START; - type = BLOGC_TEMPLATE_IF_STMT; - start = current; - if_count++; - break; - } - *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, - src, src_len, current, - "'if' statements only allowed inside 'entry' and " - "'listing' blocks."); + state = TEMPLATE_BLOCK_IF_START; + type = BLOGC_TEMPLATE_IF_STMT; + start = current; + if_count++; break; } else if (0 == strncmp("endif", src + start, current - start)) { - if (block_state == BLOCK_ENTRY || block_state == BLOCK_LISTING) { - if (if_count > 0) { - state = TEMPLATE_BLOCK_END; - type = BLOGC_TEMPLATE_ENDIF_STMT; - if_count--; - break; - } - *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, - src, src_len, current, - "'endif' statement without an open 'if' statement."); + if (if_count > 0) { + state = TEMPLATE_BLOCK_END; + type = BLOGC_TEMPLATE_ENDIF_STMT; + if_count--; break; } *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, src_len, current, - "'endif' statements only allowed inside 'entry' " - "and 'listing' blocks."); + "'endif' statement without an open 'if' statement."); break; } } @@ -250,7 +236,6 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) break; if (c == ' ') { if (0 == strncmp("not", src + start, current - start)) { - block_state = BLOCK_ENTRY; end = current; state = TEMPLATE_BLOCK_IF_START; type = BLOGC_TEMPLATE_IF_NOT_STMT; @@ -293,16 +278,9 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) if (c == ' ') break; if (c >= 'A' && c <= 'Z') { - if (block_state == BLOCK_ENTRY || block_state == BLOCK_LISTING) { - state = TEMPLATE_VARIABLE; - type = BLOGC_TEMPLATE_VARIABLE_STMT; - start = current; - break; - } - *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, - src, src_len, current, - "Variable statements only allowed inside 'entry' and " - "'listing' blocks."); + state = TEMPLATE_VARIABLE; + type = BLOGC_TEMPLATE_VARIABLE_STMT; + start = current; break; } *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, -- cgit v1.2.3-18-g5258