slweb

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

defs.h (9864B)


      1 /* This program is licensed under the terms of GNU GPL v3 or (at your option)
      2  * any later version. Copyright (C) 2020-2026  Страхиња Радић.
      3  * See the file LICENSE for exact copyright and license details. */
      4 
      5 #define COPYRIGHT_YEAR "2020-2026"
      6 #define MADEBY_URL     "https://strahinja.srht.site/slweb/"
      7 
      8 #define BUFSIZE	      1024
      9 #define KEYSIZE	      256
     10 #define LINE_DEFAULT  85
     11 #define SMALL_ARGSIZE 256
     12 #define DATEBUFSIZE   12
     13 
     14 #define SLWEB_ERR_CODE(num) (200 + (num))
     15 
     16 enum {
     17 	ERR_NONE	     = 0,
     18 	ERR_ARG_NOTNUM	     = SLWEB_ERR_CODE(1),
     19 	ERR_ARG_NOTSTR	     = SLWEB_ERR_CODE(2),
     20 	ERR_BAD_CL_ARG	     = SLWEB_ERR_CODE(3),
     21 	ERR_BAD_CND_MARK     = SLWEB_ERR_CODE(4),
     22 	ERR_BAD_EMPTY_CND    = SLWEB_ERR_CODE(5),
     23 	ERR_BAD_HR_MARK	     = SLWEB_ERR_CODE(6),
     24 	ERR_BAD_REG_MARK     = SLWEB_ERR_CODE(7),
     25 	ERR_FORMAT_DATE_FAIL = SLWEB_ERR_CODE(8),
     26 	ERR_MACRO_UNDEF	     = SLWEB_ERR_CODE(9),
     27 	ERR_NEST_CSV	     = SLWEB_ERR_CODE(10),
     28 	ERR_NEST_MACRO	     = SLWEB_ERR_CODE(11),
     29 	ERR_NEST_MATH	     = SLWEB_ERR_CODE(12),
     30 	ERR_NO_ARG	     = SLWEB_ERR_CODE(13),
     31 	ERR_POPEN_FAIL	     = SLWEB_ERR_CODE(14),
     32 	ERR_SCANDIR_FAIL     = SLWEB_ERR_CODE(15),
     33 };
     34 
     35 typedef enum {
     36 	CMD_NONE,
     37 	CMD_BODY_ONLY,
     38 	CMD_BASEDIR,
     39 	CMD_HELP,
     40 	CMD_LINK_PREFIX,
     41 	CMD_VERSION,
     42 	CMD_FULL_VERSION
     43 } Command;
     44 
     45 typedef struct {
     46 	u8* key;
     47 	u8* value;
     48 	size_t value_size;
     49 } KeyValue;
     50 
     51 typedef void (*csv_callback_t)(FILE* output, u8** csv_header, u8** csv_register);
     52 typedef void (*tsv_callback_t)(FILE* output, u8** tsv_header, u8** tsv_register);
     53 
     54 static const char article_timestamp_format[] = "d.m.y";
     55 static const char list_timestamp_format[]    = "y-m-d";
     56 static const char timestamp_output_ext[]     = ".html";
     57 
     58 static const char CMD_GIT_LOG[]	      = "xargs";
     59 static const char* CMD_GIT_LOG_ARGS[] = {"xargs", "-I{}", "git", "log", "-1",
     60 	"--pretty=format:{} %h %ci (%cn) %d", NULL};
     61 
     62 static const char CMD_KATEX[]		    = "katex";
     63 static const char* CMD_KATEX_INLINE_ARGS[]  = {"katex", NULL};
     64 static const char* CMD_KATEX_DISPLAY_ARGS[] = {"katex", "-d", NULL};
     65 
     66 static const char* CMD_IDENTIFY
     67 	= "identify %s | sed -e's/.* \\([0-9]\\{1,\\}\\)x\\([0-9]\\{1,\\}\\)"
     68 	  ".*/width=\"\\1\" height=\"\\2\"/g'";
     69 
     70 /* clang-format off */
     71 /* True iff all given "members" are present in the set */
     72 /* Usage: ALL(state, STATE1 | STATE2 | ...) 	       */
     73 #define ALL(var, mask)	(((var) & (mask)) == (mask))
     74 /* True if any of the given "members" are present in the set */
     75 /* Usage: ANY(state, STATE1 | STATE2 | ...) 		     */
     76 #define ANY(var, mask)	(((var) & (mask)) != 0)
     77 /* Removes the given "members" from the set 	*/
     78 /* Usage: CLEAR(state, STATE1 | STATE2 | ...) 	*/
     79 #define CLEAR(v, c)	do { (v) &= ~(c); } while(0)
     80 #define IN(var, mask)	ALL(var, mask)
     81 /* Adds the given "members" to the set 		*/
     82 /* Usage: SET(state, STATE1 | STATE2 | ...) 	*/
     83 #define SET(v, c)	do { (v) |= (c); } while(0)
     84 /* Adds/removes the given "members" to/from the set */
     85 /* Usage: TOGGLE(state, STATE1 | STATE2 | ...) 	    */
     86 #define TOGGLE(v, c)	do { (v) ^= (c); } while(0)
     87 /* clang-format on */
     88 
     89 #define MIN(a, b) ((a < b) ? (a) : (b))
     90 #define UNUSED(x) ((void)(x))
     91 
     92 #define COPYRIGHT                                                            \
     93 	("  This program is licensed under the terms of GNU GPL v3"          \
     94 	 " or (at your option)\n"                                            \
     95 	 "  any later version. Copyright (C) 2020-2026  Strahinya Radich.\n" \
     96 	 "  See the file LICENSE for exact copyright and license "           \
     97 	 "details.")
     98 
     99 #define CALLOC(ptr, ptrtype, nmemb)                                      \
    100 	do                                                               \
    101 	{                                                                \
    102 		errno = 0;                                               \
    103 		ptr   = calloc(nmemb, sizeof(ptrtype));                  \
    104 		if (!ptr)                                                \
    105 		{                                                        \
    106 			perror(PROGRAMNAME ": calloc");                  \
    107 			exit(error(ENOMEM, __FILE__, __func__, __LINE__, \
    108 				"Allocation error"));                    \
    109 		}                                                        \
    110 	} while (0)
    111 
    112 #define REALLOC(ptr, ptrtype, newsize)                                   \
    113 	do                                                               \
    114 	{                                                                \
    115 		ptrtype* newptr = NULL;                                  \
    116 		errno		= 0;                                     \
    117 		newptr		= realloc(ptr, newsize);                 \
    118 		if (!newptr)                                             \
    119 		{                                                        \
    120 			perror(PROGRAMNAME ": realloc");                 \
    121 			exit(error(ENOMEM, __FILE__, __func__, __LINE__, \
    122 				"Allocation error"));                    \
    123 		}                                                        \
    124 		ptr = newptr;                                            \
    125 	} while (0)
    126 
    127 #define REALLOCARRAY(ptr, membtype, newcount) \
    128 	REALLOC(ptr, membtype, sizeof(membtype) * newcount);
    129 
    130 #define MEMCCPY(to, from, tolen, temp)                     \
    131 	do                                                 \
    132 	{                                                  \
    133 		temp = memccpy(to, from, 0, tolen);        \
    134 		if (!temp)                                 \
    135 			to[tolen > 0 ? tolen - 1 : 0] = 0; \
    136 	} while (0)
    137 #define MEMCCPY_EXT(to, fallbackto, from, tolen, temp)             \
    138 	do                                                         \
    139 	{                                                          \
    140 		temp = memccpy(to, from, 0, tolen);                \
    141 		if (!temp)                                         \
    142 			fallbackto[tolen > 0 ? tolen - 1 : 0] = 0; \
    143 	} while (0)
    144 
    145 /* Copy *pline to *ptoken and increase ptoken */
    146 #define CHECKCOPY(token, ptoken, token_size, pline)     \
    147 	do                                              \
    148 	{                                               \
    149 		if (ptoken + 2 > token + token_size)    \
    150 		{                                       \
    151 			size_t old_size = token_size;   \
    152 			token_size += BUFSIZE;          \
    153 			REALLOC(token, u8, token_size); \
    154 			ptoken = token + old_size - 1;  \
    155 		}                                       \
    156 		*ptoken++ = *pline++;                   \
    157 	} while (0)
    158 
    159 #define RESET_TOKEN(token, ptoken, token_size)  \
    160 	do                                      \
    161 	{                                       \
    162 		token_size = BUFSIZE;           \
    163 		REALLOC(token, u8, token_size); \
    164 		*token = 0;                     \
    165 		ptoken = token;                 \
    166 	} while (0)
    167 
    168 #define ENSURE_SIZE(to, temp, tosize, testsize, fromsize, label, type)   \
    169 	do                                                               \
    170 	{                                                                \
    171 		if (!(to) || (tosize) < (testsize))                      \
    172 		{                                                        \
    173 			(tosize) = fromsize;                             \
    174 			errno	 = 0;                                    \
    175 			temp	 = realloc(to, (tosize) * sizeof(type)); \
    176 			if (!temp)                                       \
    177 			{                                                \
    178 				perror(PROGRAMNAME ": realloc");         \
    179 				goto label;                              \
    180 			}                                                \
    181 			(to) = temp;                                     \
    182 		}                                                        \
    183 	} while (0)
    184 
    185 #define MAX_HEADING_LEVEL 4
    186 #define MAX_CSV_REGISTERS 9
    187 #define MAX_TSV_REGISTERS 9
    188 
    189 #define ST_NONE		       0
    190 #define ST_YAML		       1
    191 #define ST_YAML_VAL	       ((unsigned long long)1 << 1)
    192 #define ST_PARA_OPEN	       ((unsigned long long)1 << 2)
    193 #define ST_TAG		       ((unsigned long long)1 << 3)
    194 #define ST_HEADING	       ((unsigned long long)1 << 4)
    195 #define ST_HEADING_TEXT	       ((unsigned long long)1 << 5)
    196 #define ST_BOLD		       ((unsigned long long)1 << 6)
    197 #define ST_ITALIC	       ((unsigned long long)1 << 7)
    198 #define ST_PRE		       ((unsigned long long)1 << 8)
    199 #define ST_CODE		       ((unsigned long long)1 << 9)
    200 #define ST_BLOCKQUOTE	       ((unsigned long long)1 << 10)
    201 #define ST_LINK		       ((unsigned long long)1 << 11)
    202 #define ST_LINK_SECOND_ARG     ((unsigned long long)1 << 12)
    203 #define ST_LINK_SECOND_ARG_END ((unsigned long long)1 << 13)
    204 #define ST_LINK_SPAN	       ((unsigned long long)1 << 14)
    205 #define ST_LINK_MACRO	       ((unsigned long long)1 << 15)
    206 #define ST_IMAGE	       ((unsigned long long)1 << 16)
    207 #define ST_IMAGE_SECOND_ARG    ((unsigned long long)1 << 17)
    208 #define ST_MACRO_BODY	       ((unsigned long long)1 << 18)
    209 #define ST_CSV_BODY	       ((unsigned long long)1 << 19)
    210 #define ST_TSV_BODY	       ((unsigned long long)1 << 20)
    211 #define ST_HTML_TAG	       ((unsigned long long)1 << 21)
    212 #define ST_KBD		       ((unsigned long long)1 << 22)
    213 #define ST_LIST		       ((unsigned long long)1 << 23)
    214 #define ST_NUMLIST	       ((unsigned long long)1 << 24)
    215 #define ST_FOOTNOTE	       ((unsigned long long)1 << 25)
    216 #define ST_FOOTNOTE_TEXT       ((unsigned long long)1 << 26)
    217 #define ST_INLINE_FOOTNOTE     ((unsigned long long)1 << 27)
    218 #define ST_FORMULA	       ((unsigned long long)1 << 28)
    219 #define ST_DISPLAY_FORMULA     ((unsigned long long)1 << 29)
    220 #define ST_TABLE_HEADER	       ((unsigned long long)1 << 30)
    221 #define ST_TABLE_LINE	       ((unsigned long long)1 << 31)
    222 #define ST_TABLE	       ((unsigned long long)1 << 32)
    223 #define ST_STRIKE	       ((unsigned long long)1 << 33)
    224 #define ST_SUMMARY	       ((unsigned long long)1 << 34)
    225 #define ST_INCDIR	       ((unsigned long long)1 << 35)
    226 
    227 #define ST_CS_NONE	    0
    228 #define ST_CS_HEADER	    1
    229 #define ST_CS_REGISTER	    (1 << 2)
    230 #define ST_CS_QUOTE	    (1 << 3)
    231 #define ST_CS_COND	    (1 << 4)
    232 #define ST_CS_COND_NONEMPTY (1 << 5)
    233 #define ST_CS_COND_EMPTY    (1 << 6)
    234 #define ST_CS_ESCAPE	    (1 << 7)