slweb

Једноставни генератор статичких веб страна
git clone https://git.sr.ht/~strahinja/slweb
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 7b80817d05997c1c2db48ef89ca571e6ad0c0c3c
родитељ 145b69d2686b446f1e649fdd8b9caa456600cef5
Аутор: Страхиња Радић <sr@strahinja.org>
Датум:   Mon, 22 Jul 2024 11:08:22 +0200

New macro: APPEND_TOKEN; move macro definitions to defs.h

Diffstat:
Mdefs.h | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mslweb.c | 334++++++++++++++++---------------------------------------------------------------
измењених датотека: 2, додавања: 189(+), брисања: 271(-)

diff --git a/defs.h b/defs.h @@ -2,11 +2,12 @@ * any later version. Copyright (C) 2020-2024 Страхиња Радић. * See the file LICENSE for exact copyright and license details. */ -#define COPYRIGHTYEAR "2020-2024" -#define MADEBY_URL "https://strahinja.srht.site/slweb/" +#define COPYRIGHT_YEAR "2020-2024" +#define MADEBY_URL "https://strahinja.srht.site/slweb/" #define BUFSIZE 1024 #define KEYSIZE 256 +#define LINE_DEFAULT 85 #define SMALL_ARGSIZE 256 #define DATEBUFSIZE 12 @@ -23,7 +24,7 @@ static const char* CMD_KATEX_INLINE_ARGS[] = {"katex", NULL}; static const char* CMD_KATEX_DISPLAY_ARGS[] = {"katex", "-d", NULL}; static const char* CMD_IDENTIFY - = "identify %s | sed -e's/.* \\([0-9]\\+\\)x\\([0-9]\\+\\)" + = "identify %s | sed -e's/.* \\([0-9]\\{1,\\}\\)x\\([0-9]\\{1,\\}\\)" ".*/width=\"\\1\" height=\"\\2\"/g'"; #define ALL(var, mask) (((var) & (mask)) == (mask)) @@ -33,6 +34,125 @@ static const char* CMD_IDENTIFY #define MIN(a, b) ((a < b) ? (a) : (b)) #define UNUSED(x) ((void)(x)) +#define COPYRIGHT \ + (" This program is licensed under the terms of GNU GPL v3" \ + " or (at your option)\n" \ + " any later version. Copyright (C) 2020-2024 Strahinya Radich.\n" \ + " See the file LICENSE for exact copyright and license " \ + "details.") + +#define CALLOC(ptr, ptrtype, nmemb) \ + do \ + { \ + ptr = calloc(nmemb, sizeof(ptrtype)); \ + if (!ptr) \ + { \ + perror(PROGRAMNAME ": calloc"); \ + exit(error(ENOMEM, __FILE__, __func__, __LINE__, \ + "Allocation error")); \ + } \ + } while (0) + +#define REALLOC(ptr, ptrtype, newsize) \ + do \ + { \ + ptrtype* newptr = realloc(ptr, newsize); \ + if (!newptr) \ + { \ + perror(PROGRAMNAME ": realloc"); \ + exit(error(ENOMEM, __FILE__, __func__, __LINE__, \ + "Allocation error")); \ + } \ + ptr = newptr; \ + } while (0) + +#define REALLOCARRAY(ptr, membtype, newcount) \ + REALLOC(ptr, membtype, sizeof(membtype) * newcount); + +#define MEMCCPY(to, from, tolen, temp) \ + do \ + { \ + temp = memccpy(to, from, 0, tolen); \ + if (!temp) \ + to[tolen > 0 ? tolen - 1 : 0] = 0; \ + } while (0) +#define MEMCCPY_EXT(to, fallbackto, from, tolen, temp) \ + do \ + { \ + temp = memccpy(to, from, 0, tolen); \ + if (!temp) \ + fallbackto[tolen > 0 ? tolen - 1 : 0] = 0; \ + } while (0) + +/* Copy *pline to *ptoken and increase ptoken */ +#define CHECKCOPY(token, ptoken, token_size, pline) \ + do \ + { \ + if (ptoken + 2 > token + token_size) \ + { \ + size_t old_size = token_size; \ + token_size += BUFSIZE; \ + REALLOC(token, u8, token_size); \ + ptoken = token + old_size - 1; \ + } \ + *ptoken++ = *pline++; \ + } while (0) + +#define RESET_TOKEN(token, ptoken, token_size) \ + do \ + { \ + token_size = BUFSIZE; \ + REALLOC(token, u8, token_size); \ + *token = 0; \ + ptoken = token; \ + } while (0) + +#define ENSURE_SIZE(to, temp, tosize, testsize, fromsize, label, type) \ + do \ + { \ + if (!to || tosize < testsize) \ + { \ + tosize = fromsize; \ + temp = realloc(to, tosize * sizeof(type)); \ + if (!temp) \ + { \ + perror("realloc"); \ + goto label; \ + } \ + to = temp; \ + } \ + } while (0) + +/* + * - Make sure the size of the destination string is large enough to copy, and + * copy + * - Sizes are in bytes + * - lval: to, temp, tosize + * - indexable: to + * - We explicitly use fromsize in MEMCCPY, because we ensured that tosize is + * at least as big, and to allow a subset of from to be copied + */ +#define U8_SAFE_COPY(to, temp, tosize, from, fromsize, label) \ + do \ + { \ + ENSURE_SIZE(to, temp, tosize, fromsize, fromsize, label, char); \ + MEMCCPY(to, from, fromsize, temp); \ + } while (0) +/* + * - Make sure the size of the destination string is large enough to copy, and + * copy + * - Sizes are in uint32_t units + * - We explicitly use fromsize in U32_MEMCCPY, because we ensured that tosize + * is at least as big, and to allow a subset of from to be copied + */ +#define U32_SAFE_COPY(to, temp, tosize, from, fromsize, label) \ + do \ + { \ + ENSURE_SIZE(to, temp, tosize, fromsize, fromsize, label, \ + uint32_t); \ + U32_MEMCCPY(to, from, fromsize, temp); \ + } while (0) + typedef unsigned char UBYTE; typedef unsigned long ULONG; typedef unsigned long long ULLONG; diff --git a/slweb.c b/slweb.c @@ -64,79 +64,6 @@ static long tsv_iter = 0; static ULLONG state = ST_NONE; static int incdir_only_summary = 0; -#define COPYRIGHT \ - (" This program is licensed under the terms of GNU GPL v3" \ - " or (at your option)\n" \ - " any later version. Copyright (C) 2020-2024 Strahinya Radich.\n" \ - " See the file LICENSE for exact copyright and license " \ - "details.") - -#define CALLOC(ptr, ptrtype, nmemb) \ - do \ - { \ - ptr = calloc(nmemb, sizeof(ptrtype)); \ - if (!ptr) \ - { \ - perror(PROGRAMNAME ": calloc"); \ - exit(error(ENOMEM, __FILE__, __func__, __LINE__, \ - "Allocation error")); \ - } \ - } while (0) - -#define REALLOC(ptr, ptrtype, newsize) \ - do \ - { \ - ptrtype* newptr = realloc(ptr, newsize); \ - if (!newptr) \ - { \ - perror(PROGRAMNAME ": realloc"); \ - exit(error(ENOMEM, __FILE__, __func__, __LINE__, \ - "Allocation error")); \ - } \ - ptr = newptr; \ - } while (0) - -#define REALLOCARRAY(ptr, membtype, newcount) \ - REALLOC(ptr, membtype, sizeof(membtype) * newcount); - -#define MEMCCPY(to, from, tolen, temp) \ - do \ - { \ - temp = memccpy(to, from, 0, tolen); \ - if (!temp) \ - to[tolen > 0 ? tolen - 1 : 0] = 0; \ - } while (0) -#define MEMCCPY_EXT(to, fallbackto, from, tolen, temp) \ - do \ - { \ - temp = memccpy(to, from, 0, tolen); \ - if (!temp) \ - fallbackto[tolen > 0 ? tolen - 1 : 0] = 0; \ - } while (0) - -/* Copy *pline to *ptoken and increase ptoken */ -#define CHECKCOPY(token, ptoken, token_size, pline) \ - do \ - { \ - if (ptoken + 2 > token + token_size) \ - { \ - size_t old_size = token_size; \ - token_size += BUFSIZE; \ - REALLOC(token, u8, token_size); \ - ptoken = token + old_size - 1; \ - } \ - *ptoken++ = *pline++; \ - } while (0) - -#define RESET_TOKEN(token, ptoken, token_size) \ - do \ - { \ - token_size = BUFSIZE; \ - REALLOC(token, u8, token_size); \ - *token = 0; \ - ptoken = token; \ - } while (0) - int cleanup(void); int usage(void); int version(const int full); @@ -384,6 +311,7 @@ strip_ext(const char* fn, const size_t fn_size) while (pfn != dot && *pfn) *pnewname++ = *pfn++; + *pnewname = 0; return newname; } @@ -2449,7 +2377,7 @@ process_madeby(FILE* output) "Generated by <a href=\"%s\">slweb</a>\n" "© %s Strahinya Radich.\n" "</small></div><!--made-by-->\n", - MADEBY_URL, COPYRIGHTYEAR); + MADEBY_URL, COPYRIGHT_YEAR); return 0; } @@ -3155,6 +3083,17 @@ simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count, return 0; } +#define APPEND_TOKEN(what, what_len) \ + do \ + { \ + token_len = ptoken - token; \ + ENSURE_SIZE(token, temp, token_size, token_len + what_len, \ + token_len + what_len, parse_alloc_error, u8); \ + MEMCCPY((token + token_len), what, token_size - token_len, \ + temp); \ + ptoken = temp ? temp - 1 : &token[token_size - 1]; \ + } while (0) + int slweb_parse(FILE* output, const char* source_filename, const size_t sfn_size, const u8* buffer, const int body_only, @@ -3181,7 +3120,6 @@ slweb_parse(FILE* output, const char* source_filename, const size_t sfn_size, size_t line_len = 0; size_t line_size = 0; size_t entity_len = 0; - size_t tag_len = 0; u8* token = NULL; u8* ptoken = NULL; size_t token_size = 0; @@ -3441,23 +3379,13 @@ do_line: if (strlen((char*)pline) > 1 && *(pline + 1) == '~') { u8* entity = (u8*)"&nbsp;"; + entity_len = strlen((char*)entity); /* Handle ~~ within footnotes, headings and link * text specially */ if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - entity_len = strlen((char*)entity); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + entity_len < BUFSIZE) - { - MEMCCPY((token + token_len), entity, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(entity, entity_len); else { /* Output existing text up to ~~ */ @@ -3481,23 +3409,13 @@ do_line: else if (strlen((char*)pline) > 1 && *(pline + 1) == '-') { u8* entity = (u8*)"&#8209;"; + entity_len = strlen((char*)entity); /* Handle ~- within footnotes, headings and link * text specially */ if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - entity_len = strlen((char*)entity); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + entity_len < BUFSIZE) - { - MEMCCPY((token + token_len), entity, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(entity, entity_len); else { /* Output existing text up to ~~ */ @@ -3525,20 +3443,10 @@ do_line: if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - u8* tag = IN(state, ST_STRIKE) ? (u8*)"</s>" - : (u8*)"<s>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(IN(state, ST_STRIKE) ? "</s>" + : "<s>", + sizeof(IN(state, ST_STRIKE) ? "</s>" + : "<s>")); else { /* Output existing text up to ~ */ @@ -3606,20 +3514,10 @@ do_line: if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - u8* tag = IN(state, ST_CODE) ? (u8*)"</code>" - : (u8*)"<code>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(IN(state, ST_CODE) ? "</code>" + : "<code>", + sizeof(IN(state, ST_CODE) ? "</code>" + : "<code>")); else { /* Output existing text up to ` */ @@ -3712,20 +3610,11 @@ do_line: if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - u8* tag = IN(state, ST_BOLD) ? (u8*)"</strong>" - : (u8*)"<strong>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(IN(state, ST_BOLD) ? "</strong>" + : "<strong>", + sizeof(IN(state, ST_BOLD) + ? "</strong>" + : "<strong>")); else { /* Output existing text up to __ */ @@ -3754,20 +3643,10 @@ do_line: if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - u8* tag = IN(state, ST_ITALIC) ? (u8*)"</em>" - : (u8*)"<em>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(IN(state, ST_ITALIC) ? "</em>" + : "<em>", + sizeof(IN(state, ST_ITALIC) ? "</em>" + : "<em>")); else { /* Output existing text up to _ */ @@ -3907,20 +3786,11 @@ do_line: if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - u8* tag = IN(state, ST_BOLD) ? (u8*)"</strong>" - : (u8*)"<strong>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(IN(state, ST_BOLD) ? "</strong>" + : "<strong>", + sizeof(IN(state, ST_BOLD) + ? "</strong>" + : "<strong>")); else { /* Output existing text up to * */ @@ -3950,20 +3820,10 @@ do_line: ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - u8* tag = IN(state, ST_ITALIC) ? (u8*)"</em>" - : (u8*)"<em>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(IN(state, ST_ITALIC) ? "</em>" + : "<em>", + sizeof(IN(state, ST_ITALIC) ? "</em>" + : "<em>")); else { /* Output existing text up to * */ @@ -4033,11 +3893,7 @@ do_line: if (strlen((char*)pline) == 2 && *(pline + 1) == ' ') { - size_t ptoken_len = strlen((char*)ptoken); - *ptoken = 0; - MEMCCPY((ptoken + ptoken_len), "<br>", - token_size - ptoken_len, temp); - ptoken = temp ? temp - 1 : &token[token_size - 1]; + APPEND_TOKEN("<br>", sizeof("<br>")); output_firstcol = 0; pline += 2; colno++; @@ -4271,20 +4127,10 @@ do_line: if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING | ST_FOOTNOTE_TEXT | ST_LINK)) - { - u8* tag = IN(state, ST_KBD) ? (u8*)"</kbd>" - : (u8*)"<kbd>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len + 1 < token_size) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - } + APPEND_TOKEN(IN(state, ST_KBD) ? "</kbd>" + : "<kbd>", + sizeof(IN(state, ST_KBD) ? "</kbd>" + : "<kbd>")); else { /* Output existing text up to || */ @@ -4479,11 +4325,7 @@ do_line: if (ANY(state, ST_CODE | ST_KBD | ST_PRE)) { - *ptoken = 0; - token_len = strlen((char*)token); - MEMCCPY((token + token_len), "&lt;", - token_size - token_len, temp); - ptoken = temp ? temp - 1 : &token[token_size - 1]; + APPEND_TOKEN("&lt;", sizeof("&lt;")); pline++; colno++; break; @@ -4662,18 +4504,7 @@ do_line: if (*pline == '(') { - u8* tag = (u8*)"<span>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } - + APPEND_TOKEN("<span>", sizeof("<span>")); state |= ST_LINK_SPAN; pline++; colno++; @@ -4690,17 +4521,7 @@ do_line: CHECKCOPY(token, ptoken, token_size, pline); else if (*link_macro && (IN(state, ST_LINK))) { - u8* tag = (u8*)"<span>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len + 1 < token_size) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } + APPEND_TOKEN("<span>", sizeof("<span>")); state |= ST_LINK_SPAN; pline++; } @@ -4724,17 +4545,7 @@ do_line: if (IN(state, ST_LINK_SPAN) && pline_len > 1 && *(pline + 1) == ']') { - u8* tag = (u8*)"</span>"; - tag_len = strlen((char*)tag); - *ptoken = 0; - token_len = strlen((char*)token); - if (token_len + tag_len + 1 < token_size) - { - MEMCCPY((token + token_len), tag, - token_size - token_len, temp); - ptoken = temp ? temp - 1 - : &token[token_size - 1]; - } + APPEND_TOKEN("</span>", sizeof("</span>")); state &= ~ST_LINK_SPAN; pline++; colno++; @@ -5146,11 +4957,7 @@ do_line: case '"': if (ANY(state, ST_CODE | ST_KBD | ST_PRE)) { - *ptoken = 0; - token_len = strlen((char*)token); - MEMCCPY((token + token_len), "&quot;", - token_size - token_len, temp); - ptoken = temp ? temp - 1 : &token[token_size - 1]; + APPEND_TOKEN("&quot;", sizeof("&quot;")); pline++; } else @@ -5163,11 +4970,7 @@ do_line: if (ANY(state, ST_CODE | ST_KBD | ST_PRE) || !*(pline + 1) || isspace(*(pline + 1))) { - *ptoken = 0; - token_len = strlen((char*)token); - MEMCCPY((token + token_len), "&amp;", - token_size - token_len, temp); - ptoken = temp ? temp - 1 : &token[token_size - 1]; + APPEND_TOKEN("&amp;", sizeof("&amp;")); pline++; } else @@ -5199,21 +5002,7 @@ done_line: MEMCCPY(pvars->value, (char*)token, pvars->value_size, temp); } else if (keep_token) - { - if (ptoken + 2 > token + token_size) - { - size_t old_size = token_size; - token_size += BUFSIZE; - REALLOC(token, u8, token_size); - ptoken = token + old_size - 1; - } - token_len = strlen((char*)token); - MEMCCPY((token + token_len), - ANY(state, ST_IMAGE | ST_LINK) ? " " : "\n", - token_size - token_len, temp); - ptoken++; - *ptoken = 0; - } + APPEND_TOKEN(ANY(state, ST_IMAGE | ST_LINK) ? " " : "\n", 1); else { if (*token) @@ -5440,8 +5229,10 @@ done_line: pfootnotes->value_size); } MEMCCPY((pfootnotes->value + token_len), - token, pfootnotes->value_size - - token_len, temp); + token, + pfootnotes->value_size + - token_len, + temp); } else { @@ -5540,6 +5331,13 @@ done_buffer: free(line); return 0; + +parse_alloc_error: + free(link_text); + free(link_macro); + free(token); + free(line); + return 1; } int