чување 7b80817d05997c1c2db48ef89ca571e6ad0c0c3c
родитељ 145b69d2686b446f1e649fdd8b9caa456600cef5
Аутор: Страхиња Радић <sr@strahinja.org>
Датум: Mon, 22 Jul 2024 11:08:22 +0200
New macro: APPEND_TOKEN; move macro definitions to defs.h
Diffstat:
| M | defs.h | | | 126 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
| M | slweb.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*)" ";
+ 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*)"‑";
+ 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), "<",
- token_size - token_len, temp);
- ptoken = temp ? temp - 1 : &token[token_size - 1];
+ APPEND_TOKEN("<", sizeof("<"));
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), """,
- token_size - token_len, temp);
- ptoken = temp ? temp - 1 : &token[token_size - 1];
+ APPEND_TOKEN(""", sizeof("""));
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), "&",
- token_size - token_len, temp);
- ptoken = temp ? temp - 1 : &token[token_size - 1];
+ APPEND_TOKEN("&", sizeof("&"));
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