slweb

Једноставни генератор статичких веб страна
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување cb512a8b8a31311d0c47f1a744fd4c9d702953f9
родитељ 92a411ceec8bdb2c0b36444d99df81085cb1dcb8
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Fri, 17 Jun 2022 15:11:02 +0200

Clearly separate macro definitions from macro calls; update manpage accordingly

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
Mdefs.h | 1-
Mexamples/links/index.slw | 4++--
Mexamples/macros/index.slw | 4++--
Mslweb.1.in | 7++++---
Mslweb.c | 233++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
измењених датотека: 5, додавања: 137(+), брисања: 112(-)

diff --git a/defs.h b/defs.h @@ -68,7 +68,6 @@ typedef struct { u8* key; u8* value; size_t value_size; - int seen; /* for use with macros */ } KeyValue; typedef int (*csv_callback_t)(FILE* output, u8** csv_header, u8** csv_register); diff --git a/examples/links/index.slw b/examples/links/index.slw @@ -2,11 +2,11 @@ stylesheet: style.css site-name: Links test --- -{=icon}<svg style="width:24px;height:24px" viewBox="0 0 24 24"> +{=!icon}<svg style="width:24px;height:24px" viewBox="0 0 24 24"> <path fill="currentColor" d="M12,17.56L16.07,16.43L16.62,10.33H9.38L9.2,8.3H16.8L17,6.31H7L7.56,12.32H14.45L14.22,14.9L12,15.5L9.78,14.9L9.64,13.24H7.64L7.93,16.43L12,17.56M4.07,3H19.93L18.5,19.2L12,21L5.5,19.2L4.07,3Z" /> -</svg>{/=icon} +</svg>{/=!icon} Links [Test][1]. diff --git a/examples/macros/index.slw b/examples/macros/index.slw @@ -2,8 +2,8 @@ stylesheet: style.css --- -{=copyright}Copyright &copy; John Doe. <br /> -All rights reserved.{/=copyright} +{=!copyright}Copyright &copy; John Doe. <br /> +All rights reserved.{/=!copyright} {header}Header: {=copyright}{/header} diff --git a/slweb.1.in b/slweb.1.in @@ -572,19 +572,20 @@ Directive \fC{include "somefile"}\fP will fork, parse .IR basedir ) and output the resulting .SM HTML -as if the option \fC\-\-body\-only\fP was specified. All macros and +as if the option \fC\-\-body\-only\fP was specified. All .SM YAML variables will be preserved. . .IP \[bu] .BR Macros . -Macros can be declared using the directive \fC{=macroname}{/=macroname}\fP, +Macros can be declared using the directive \fC{=!macroname}{/=!macroname}\fP, where .I macroname is the name of the macro. Anything between those two tags will then become the body of a macro. Whenever \fC{=macroname}\fP is subsequently encountered in the file, it will be replaced by the macro body. Macro definitions can't be nested -nor can they contain macro calls, and doing so will produce an error. +nor can they contain macro calls, and doing so will produce an error. Tags won't +be processed within the body of a macro. . .IP \[bu] .BR "Previous Git commit information" . diff --git a/slweb.c b/slweb.c @@ -211,7 +211,7 @@ endswith(const char* s, const char* what) } u8* -get_value(KeyValue* list, const size_t list_count, const u8* key, int* seen) +get_value(KeyValue* list, const size_t list_count, const u8* key) { if (!list) return NULL; @@ -219,14 +219,7 @@ get_value(KeyValue* list, const size_t list_count, const u8* key, int* seen) while (plist < list + list_count) { if (!strcmp((char*)plist->key, (char*)key)) - { - if (seen) - { - *seen = plist->seen; - plist->seen = 1; - } return plist->value; - } plist++; } return NULL; @@ -502,7 +495,7 @@ print_meta_var(FILE* output, u8** tsv_header, u8** tsv_register) u8* var_name = NULL; var_name = (u8*)strdup((char*)pvalue + 1); *(var_name + value_len - 2) = 0; - u8* value = get_value(vars, vars_count, var_name, NULL); + u8* value = get_value(vars, vars_count, var_name); if (value) print_output(output, @@ -1121,8 +1114,7 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback) UBYTE current_header = 0; u8* csv_register[MAX_CSV_REGISTERS]; UBYTE current_register = 0; - u8* csv_delimiter - = get_value(vars, vars_count, (u8*)"csv-delimiter", NULL); + u8* csv_delimiter = get_value(vars, vars_count, (u8*)"csv-delimiter"); if (!(csv = fopen(filename, "rt"))) exit(error(ENOENT, (u8*)"csv: No such file: %s", filename)); @@ -1301,7 +1293,7 @@ int process_include(FILE* output, const u8* token, const int read_yaml_macros_and_links) { - u8* ptoken = (u8*)strchr((char*)token, ' '); + u8* ptoken; char* include_filename = NULL; char* pinclude_filename = NULL; pid_t pid = 0; @@ -1309,6 +1301,8 @@ process_include(FILE* output, const u8* token, int arg_pipe_fds[2]; int output_pipe_fds[2]; + ptoken = (u8*)strchr((char*)token, ' '); + if (!input_filename) return warning(1, (u8*)"Cannot use 'include' in stdin"); @@ -1426,6 +1420,7 @@ process_include(FILE* output, const u8* token, result = slweb_parse(output, filename, buffer, 1, 0); process_include_child_cleanup: + fflush(output); slweb_cleanup(); free(filename); free(buffer); @@ -1714,7 +1709,7 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix, exit(error(1, (u8*)"incdir: Second argument required")); if (*arg == '=') - macro_body = get_value(macros, macros_count, arg + 1, NULL); + macro_body = get_value(macros, macros_count, arg + 1); else { u8* parg = arg; @@ -1740,8 +1735,7 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix, (u8*)"incdir: Third argument not " "macro")); } - macro_body = get_value(macros, macros_count, arg + 1, - NULL); + macro_body = get_value(macros, macros_count, arg + 1); } } @@ -1838,70 +1832,66 @@ process_timestamp_cleanup: } int -process_macro(FILE* output, const u8* token, +process_macro_def(FILE* output, const u8* token, const int read_yaml_macros_and_links, const int end_tag) { - if (!end_tag) + if (end_tag) { - if (IN(state, ST_MACRO_BODY)) - exit(error(1, (u8*)"Macro undefined or nested")); + fflush(output); + state &= ~ST_MACRO_BODY; + return 0; + } - int seen = 0; - u8* macro_body = get_value(macros, macros_count, token + 1, - read_yaml_macros_and_links ? NULL : &seen); + if (IN(state, ST_MACRO_BODY)) + exit(error(1, (u8*)"Cannot nest definitions")); - if (macro_body && !read_yaml_macros_and_links) + if (read_yaml_macros_and_links) + { + macros_count++; + + if (!macros) { - if (seen) - { - u8* eol = (u8*)strrchr((char*)macro_body, '\n'); - size_t macro_body_len - = strlen((char*)macro_body); - if (eol) - output_firstcol = macro_body - + macro_body_len - - (u8*)strrchr( - (char*)macro_body, - '\n') - > 0; - else - output_firstcol = !*macro_body - || *(macro_body + macro_body_len - - 1) - == '\n'; - print_output(output, "%s", macro_body); - } - else - state |= ST_MACRO_BODY; + CALLOC(macros, KeyValue, macros_count); + pmacros = macros; } - else if (!macro_body) + else { - if (read_yaml_macros_and_links) - { - macros_count++; - - if (!macros) - { - CALLOC(macros, KeyValue, macros_count); - pmacros = macros; - } - else - { - REALLOC(macros, KeyValue, - macros_count * sizeof(KeyValue)); - pmacros = macros + macros_count - 1; - } - CALLOC(pmacros->key, u8, KEYSIZE); - pmacros->seen = 0; - strcpy((char*)pmacros->key, (char*)token + 1); - pmacros->value = NULL; - pmacros->value_size = 0; - } - state |= ST_MACRO_BODY; + REALLOC(macros, KeyValue, + macros_count * sizeof(KeyValue)); + pmacros = macros + macros_count - 1; } + CALLOC(pmacros->key, u8, KEYSIZE); + strcpy((char*)pmacros->key, (char*)token + 2); + pmacros->value = NULL; + pmacros->value_size = 0; } + fflush(output); + state |= ST_MACRO_BODY; + + return 0; +} + +int +process_macro(FILE* output, const u8* token, const int end_tag) +{ + u8* macro_body; + u8* eol; + size_t macro_body_len; + + macro_body = get_value(macros, macros_count, token + 1); + if (!macro_body) + exit(error(1, (u8*)"Macro '%s' undefined", token + 1)); + + eol = (u8*)strrchr((char*)macro_body, '\n'); + macro_body_len = strlen((char*)macro_body); + if (eol) + output_firstcol = macro_body + macro_body_len + - (u8*)strrchr((char*)macro_body, '\n') + > 0; else - state &= ~ST_MACRO_BODY; + output_firstcol = !*macro_body + || *(macro_body + macro_body_len - 1) == '\n'; + print_output(output, "%s", macro_body); return 0; } @@ -1948,8 +1938,11 @@ process_tag(FILE* output, const u8* token, const u8* link_prefix, } else if (*token == '=') /* {=macro} */ { - process_macro(output, token, read_yaml_macros_and_links, - end_tag); + if (*(token + 1) == '!') + process_macro_def(output, token, + read_yaml_macros_and_links, end_tag); + else if ((*(token + 1) != '!') && !read_yaml_macros_and_links) + process_macro(output, token, end_tag); *skip_eol = 1; } else if (!read_yaml_macros_and_links) /* general tags */ @@ -2138,7 +2131,7 @@ int process_link(FILE* output, const u8* link_text, const u8* link_prefix, const u8* link_macro_body, const u8* link_id) { - u8* url = get_value(links, links_count, link_id, NULL); + u8* url = get_value(links, links_count, link_id); return process_inline_link(output, link_text, link_prefix, link_macro_body, url); } @@ -2225,7 +2218,7 @@ process_image(FILE* output, const u8* image_text, const u8* image_file_prefix, const u8* link_prefix, const u8* image_id, const int add_link, const int add_figcaption) { - u8* url = get_value(links, links_count, image_id, NULL); + u8* url = get_value(links, links_count, image_id); return process_inline_image(output, image_text, image_file_prefix, link_prefix, url, add_link, add_figcaption); } @@ -2436,14 +2429,14 @@ process_formula(FILE* output, const u8* token, const int display_formula) int begin_html_and_head(FILE* output) { - u8* lang = get_value(vars, vars_count, (u8*)"lang", NULL); - u8* site_name = get_value(vars, vars_count, (u8*)"site-name", NULL); - u8* site_desc = get_value(vars, vars_count, (u8*)"site-desc", NULL); - u8* canonical = get_value(vars, vars_count, (u8*)"canonical", NULL); - u8* favicon_url = get_value(vars, vars_count, (u8*)"favicon-url", NULL); - u8* meta = get_value(vars, vars_count, (u8*)"meta", NULL); - u8* feed = get_value(vars, vars_count, (u8*)"feed", NULL); - u8* feed_desc = get_value(vars, vars_count, (u8*)"feed-desc", NULL); + u8* lang = get_value(vars, vars_count, (u8*)"lang"); + u8* site_name = get_value(vars, vars_count, (u8*)"site-name"); + u8* site_desc = get_value(vars, vars_count, (u8*)"site-desc"); + u8* canonical = get_value(vars, vars_count, (u8*)"canonical"); + u8* favicon_url = get_value(vars, vars_count, (u8*)"favicon-url"); + u8* meta = get_value(vars, vars_count, (u8*)"meta"); + u8* feed = get_value(vars, vars_count, (u8*)"feed"); + u8* feed_desc = get_value(vars, vars_count, (u8*)"feed-desc"); print_output(output, "<!DOCTYPE html>\n" @@ -2546,10 +2539,10 @@ begin_article(FILE* output, const char* source_filename, const u8* link_prefix, if (date && source_filename) { - char* link = strip_ext((const char*)source_filename); - char* real_link = NULL; - u8* permalink_macro = get_value(macros, macros_count, - (u8*)"permalink", NULL); + char* link = strip_ext((const char*)source_filename); + char* real_link = NULL; + u8* permalink_macro + = get_value(macros, macros_count, (u8*)"permalink"); CALLOC(real_link, char, BUFSIZE); if (ext_in_permalink) @@ -2761,29 +2754,27 @@ slweb_parse(FILE* output, const char* source_filename, const u8* buffer, if (!buffer) exit(error(1, (u8*)"Empty buffer")); - title = get_value(vars, vars_count, (u8*)"title", NULL); + title = get_value(vars, vars_count, (u8*)"title"); title_heading_level - = get_value(vars, vars_count, (u8*)"title-heading-level", NULL); - header_text = get_value(vars, vars_count, (u8*)"header-text", NULL); - author = get_value(vars, vars_count, (u8*)"author", NULL); - date = get_value(vars, vars_count, (u8*)"date", NULL); - permalink_url = get_value(vars, vars_count, (u8*)"permalink-url", NULL); + = get_value(vars, vars_count, (u8*)"title-heading-level"); + header_text = get_value(vars, vars_count, (u8*)"header-text"); + author = get_value(vars, vars_count, (u8*)"author"); + date = get_value(vars, vars_count, (u8*)"date"); + permalink_url = get_value(vars, vars_count, (u8*)"permalink-url"); image_file_prefix - = get_value(vars, vars_count, (u8*)"image-file-prefix", NULL); - ext_in_permalink - = get_value(vars, vars_count, (u8*)"ext-in-permalink", NULL); + = get_value(vars, vars_count, (u8*)"image-file-prefix"); + ext_in_permalink = get_value(vars, vars_count, (u8*)"ext-in-permalink"); var_add_article_header - = get_value(vars, vars_count, (u8*)"add-article-header", NULL); + = get_value(vars, vars_count, (u8*)"add-article-header"); var_add_image_links - = get_value(vars, vars_count, (u8*)"add-image-links", NULL); + = get_value(vars, vars_count, (u8*)"add-image-links"); add_image_links = !(var_add_image_links && *var_add_image_links == '0'); - var_add_figcaption - = get_value(vars, vars_count, (u8*)"add-figcaption", NULL); + var_add_figcaption = get_value(vars, vars_count, (u8*)"add-figcaption"); add_figcaption = !(var_add_figcaption && *var_add_figcaption == '0'); var_add_footnote_div - = get_value(vars, vars_count, (u8*)"add-footnote-div", NULL); + = get_value(vars, vars_count, (u8*)"add-footnote-div"); add_footnote_div = var_add_footnote_div && *var_add_footnote_div == '1'; - link_prefix = get_value(vars, vars_count, (u8*)"link-prefix", NULL); + link_prefix = get_value(vars, vars_count, (u8*)"link-prefix"); CALLOC(line, u8, BUFSIZE); token_size = BUFSIZE; @@ -3645,7 +3636,7 @@ do_line: break; } - if ((IN(state, ST_TAG)) && pline - 1 && *(pline - 1) == '{') + if ((IN(state, ST_TAG)) && *(pline - 1) == '{') { end_tag = 1; pline++; @@ -3666,10 +3657,44 @@ do_line: break; } - if (IN(state, ST_TAG)) + *ptoken = 0; + + if (IN(state, ST_MACRO_BODY) + && !(end_tag && startswith((const char*)token, "="))) + { + size_t token_len; + size_t value_len; + + if (read_yaml_macros_and_links) + { + token_len = strlen((char*)token); + + skip_eol = 1; + value_len = strlen((char*)pmacros->value); + + if (pmacros->value_size + < value_len + token_len + 1) + { + pmacros->value_size += token_len; + REALLOC(pmacros->value, u8, + pmacros->value_size); + } + strcat((char*)pmacros->value, "{"); + if (end_tag) + strcat((char*)pmacros->value, "/"); + strcat(strcat((char*)pmacros->value, + (char*)token), + "}"); + } + + *token = 0; + ptoken = token; + state &= ~ST_TAG; + end_tag = 0; + } + else if (IN(state, ST_TAG)) { state &= ~ST_TAG; - *ptoken = 0; process_tag(output, token, link_prefix, read_yaml_macros_and_links, &skip_eol, end_tag); @@ -4176,7 +4201,7 @@ do_line: process_inline_link(output, link_text, link_prefix, get_value(macros, macros_count, - link_macro, NULL), + link_macro), token); else process_inline_image(output, link_text, @@ -4250,7 +4275,7 @@ do_line: if (!read_yaml_macros_and_links) process_link(output, link_text, link_prefix, get_value(macros, macros_count, - link_macro, NULL), + link_macro), token); RESET_TOKEN(token, ptoken, token_size); state &= ~(ST_LINK | ST_LINK_SECOND_ARG);