slweb

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

чување 5e6983bbb3d9e72efcc1fbaa83ce52d6a429f2db
родитељ f798b7975018cbe191e2234280256a1aa2bbd5f9
Аутор: Страхиња Радић <sr@strahinja.org>
Датум:   Tue, 23 Jul 2024 10:17:45 +0200

Add exact exit codes for errors not related to errno; error reporting cleanup

Diffstat:
Mdefs.h | 69++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mslweb.1.in | 48++++++++++++++++++++++++++++++++++++++++++++++++
Mslweb.c | 292++++++++++++++++++++++++++++++++++++++++++-------------------------------------
измењених датотека: 3, додавања: 251(+), брисања: 158(-)

diff --git a/defs.h b/defs.h @@ -11,6 +11,46 @@ #define SMALL_ARGSIZE 256 #define DATEBUFSIZE 12 +#define SLWEB_ERR_CODE(num) (200 + (num)) + +enum { + ERR_NONE = 0, + ERR_ARG_NOTNUM = SLWEB_ERR_CODE(1), + ERR_ARG_NOTSTR = SLWEB_ERR_CODE(2), + ERR_BAD_CL_ARG = SLWEB_ERR_CODE(3), + ERR_BAD_CND_MARK = SLWEB_ERR_CODE(4), + ERR_BAD_EMPTY_CND = SLWEB_ERR_CODE(5), + ERR_BAD_HR_MARK = SLWEB_ERR_CODE(6), + ERR_BAD_REG_MARK = SLWEB_ERR_CODE(7), + ERR_FORMAT_DATE_FAIL = SLWEB_ERR_CODE(8), + ERR_MACRO_UNDEF = SLWEB_ERR_CODE(9), + ERR_NEST_CSV = SLWEB_ERR_CODE(10), + ERR_NEST_MACRO = SLWEB_ERR_CODE(11), + ERR_NEST_MATH = SLWEB_ERR_CODE(12), + ERR_NO_ARG = SLWEB_ERR_CODE(13), + ERR_POPEN_FAIL = SLWEB_ERR_CODE(14), + ERR_SCANDIR_FAIL = SLWEB_ERR_CODE(15), +}; + +typedef enum { + CMD_NONE, + CMD_BODY_ONLY, + CMD_BASEDIR, + CMD_HELP, + CMD_LINK_PREFIX, + CMD_VERSION, + CMD_FULL_VERSION +} Command; + +typedef struct { + u8* key; + u8* value; + size_t value_size; +} KeyValue; + +typedef void (*csv_callback_t)(FILE* output, u8** csv_header, u8** csv_register); +typedef void (*tsv_callback_t)(FILE* output, u8** tsv_header, u8** tsv_register); + static const char article_timestamp_format[] = "d.m.y"; static const char list_timestamp_format[] = "y-m-d"; static const char timestamp_output_ext[] = ".html"; @@ -59,7 +99,8 @@ static const char* CMD_IDENTIFY #define CALLOC(ptr, ptrtype, nmemb) \ do \ { \ - ptr = calloc(nmemb, sizeof(ptrtype)); \ + errno = 0; \ + ptr = calloc(nmemb, sizeof(ptrtype)); \ if (!ptr) \ { \ perror(PROGRAMNAME ": calloc"); \ @@ -71,7 +112,9 @@ static const char* CMD_IDENTIFY #define REALLOC(ptr, ptrtype, newsize) \ do \ { \ - ptrtype* newptr = realloc(ptr, newsize); \ + ptrtype* newptr = NULL; \ + errno = 0; \ + newptr = realloc(ptr, newsize); \ if (!newptr) \ { \ perror(PROGRAMNAME ": realloc"); \ @@ -128,6 +171,7 @@ static const char* CMD_IDENTIFY if (!(to) || (tosize) < (testsize)) \ { \ (tosize) = fromsize; \ + errno = 0; \ temp = realloc(to, (tosize) * sizeof(type)); \ if (!temp) \ { \ @@ -138,27 +182,6 @@ static const char* CMD_IDENTIFY } \ } while (0) -typedef unsigned long ULONG; - -typedef enum { - CMD_NONE, - CMD_BODY_ONLY, - CMD_BASEDIR, - CMD_HELP, - CMD_LINK_PREFIX, - CMD_VERSION, - CMD_FULL_VERSION -} Command; - -typedef struct { - u8* key; - u8* value; - size_t value_size; -} KeyValue; - -typedef int (*csv_callback_t)(FILE* output, u8** csv_header, u8** csv_register); -typedef int (*tsv_callback_t)(FILE* output, u8** tsv_header, u8** tsv_register); - #define MAX_HEADING_LEVEL 4 #define MAX_CSV_REGISTERS 9 #define MAX_TSV_REGISTERS 9 diff --git a/slweb.1.in b/slweb.1.in @@ -1313,6 +1313,54 @@ directive, similar to the macro\-form of links. . .Sh EXIT STATUS .Ex -std +.Pp +For errors caused by the unsuccessful calls to libc functions setting +.Va errno , +that value is returned as the exit status. +Otherwise, the exit status is one of the following: +.Bl -tag -width Ds -offset indent -compact +.It Li 201 +Argument to a function is not numeric. +.It Li 202 +Argument to a function is not beginning and ending with double quotes (not a +.Do string Dc Ns ). +.It Li 203 +Command line argument is not recognized. +.It Li 204 +Conditional mark is not recognized. +.It Li 205 +Empty conditional mark is before or without the corresponding nonempty +conditional. +.It Li 206 +Header register mark is not recognized. +.It Li 207 +Register mark is not recognized. +.It Li 208 +Parsing arguments failed when formatting date. +.It Li 209 +Macro is not defined. +.It Li 210 +There are nested CSV/TSV directives. +.It Li 211 +There are nested macro definitions. +.It Li 212 +There are nested formulas. +.It Li 213 +No arguments are supplied to a directive or to a command line argument which +requires at least one. +.It Li 214 +The function +.Xr popen 3 +(which doesn't set +.Va errno ) +failed. +.It Li 215 +The function +.Xr scandir 3 +(which doesn't set +.Va errno ) +failed. +.El . .Sh EXAMPLES Given the file diff --git a/slweb.c b/slweb.c @@ -65,10 +65,10 @@ static int add_css(FILE* output, int output_yaml); static int error(const int code, const char* file, const char* func, const int line, const char* fmt, ...); static u8* format_date(const u8* date_arg, const char* timestamp_format); -static int free_keyvalue(KeyValue** list, const size_t list_count); +static void free_keyvalue(KeyValue** list, const size_t list_count); static u8* get_value(KeyValue* list, const size_t list_count, const u8* key, KeyValue** cursor); -static int print_meta_var(FILE* output, u8** tsv_header, u8** tsv_register); +static void print_meta_var(FILE* output, u8** tsv_header, u8** tsv_register); static int print_output(FILE* output, const char* fmt, ...); static void process_horizontal_rule(FILE* output); static void process_incdir_subdir(FILE* output, const char* subdirname, @@ -342,7 +342,7 @@ end_footnotes(FILE* output, int add_footnote_div) } pfootnote = footnotes; - footnote = 0; + footnote = 0; while (pfootnote && footnote < footnote_count) { print_output(output, @@ -400,10 +400,10 @@ filter_slw(const struct dirent* node) && !(*(node->d_name + 2)))))) return 0; node_len = strlen(node->d_name); - slw_len = strlen(".slw"); + slw_len = sizeof(".slw"); if (slw_len >= node_len) return 0; - return !strcmp(node->d_name + strlen(node->d_name) - slw_len, ".slw"); + return !strcmp(node->d_name + node_len - slw_len, ".slw"); } static int @@ -418,18 +418,14 @@ filter_subdirs(const struct dirent* node) || ((*(node->d_name + 1) == '.') && !(*(node->d_name + 2)))))) return 0; - CALLOC(nodename, char, BUFSIZE); snprintf(nodename, BUFSIZE, "%s/%s", incdir, node->d_name); - if (lstat(nodename, &st) < 0 || !S_ISDIR(st.st_mode)) { free(nodename); return 0; } - free(nodename); - return 1; } @@ -447,9 +443,14 @@ format_date(const u8* date_arg, const char* timestamp_format) size_t formatted_date_len; assert((date_arg != NULL) && (timestamp_format != NULL)); - date = (u8*)strdup((const char*)date_arg); + errno = 0; + date = (u8*)strdup((const char*)date_arg); if (!date) - goto format_date_cleanup; + { + perror(PROGRAMNAME ": strdup"); + exit(error(errno, __FILE__, __func__, __LINE__, + "Allocation error")); + } CALLOC(formatted_date, u8, DATEBUFSIZE); ptr = NULL; year = (u8*)strtok_r((char*)date, "-", (char**)&ptr); @@ -496,19 +497,19 @@ format_date_cleanup: return NULL; } -static int +static void free_keyvalue(KeyValue** list, const size_t list_count) { - if (!list || !*list) - return 1; - + assert(list != NULL); + if (!*list) + return; for (size_t index = 0; index < list_count; index++) { KeyValue* current = *list + index; free(current->value); free(current->key); } - return 0; + return; } static u8* @@ -559,7 +560,8 @@ print_command(FILE* output, const char* command, const u8* pass_arguments[], fflush(output); pipe(arg_pipe_fds); pipe(output_pipe_fds); - pid = fork(); + errno = 0; + pid = fork(); if (pid == 0) { close(arg_pipe_fds[PIPE_WRITE_INDEX]); @@ -572,19 +574,23 @@ print_command(FILE* output, const char* command, const u8* pass_arguments[], exit(1); } else if (pid < 0) + { + perror(PROGRAMNAME ": fork"); exit(error(errno, __FILE__, __func__, __LINE__, "fork failed")); + } /* Parent */ close(arg_pipe_fds[PIPE_READ_INDEX]); close(output_pipe_fds[PIPE_WRITE_INDEX]); - errno = 0; - cmd_input = fdopen(arg_pipe_fds[PIPE_WRITE_INDEX], "w"); + errno = 0; + cmd_input = fdopen(arg_pipe_fds[PIPE_WRITE_INDEX], "w"); if (cmd_input) cmd_output = fdopen(output_pipe_fds[PIPE_READ_INDEX], "r"); if (!cmd_input || !cmd_output) { perror(PROGRAMNAME ": fdopen"); - exit(error(errno, __FILE__, __func__, __LINE__, "fdopen failed")); + exit(error(errno, __FILE__, __func__, __LINE__, + "fdopen failed")); } if (pipe_arguments) @@ -638,7 +644,7 @@ print_command(FILE* output, const char* command, const u8* pass_arguments[], } \ } while (0) -static int +static void print_csv_row(FILE* output, u8** csv_header, u8** csv_register) { u8* pcsv_template = csv_template; @@ -649,7 +655,7 @@ print_csv_row(FILE* output, u8** csv_header, u8** csv_register) && (csv_register != NULL)); csv_template_start: if (!*pcsv_template) - goto csv_template_done; + return; if (IN(csv_state, ST_CS_ESCAPE)) { PRINTCSVIF("%c", *pcsv_template); @@ -677,7 +683,7 @@ csv_template_start: case '#': if (IN(csv_state, ST_CS_HEADER)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_HR_MARK, __FILE__, __func__, __LINE__, "Invalid header register mark"); CLEAR(csv_state, ST_CS_REGISTER | ST_CS_HEADER); } @@ -693,7 +699,7 @@ csv_template_start: case '?': if (IN(csv_state, ST_CS_COND)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_CND_MARK, __FILE__, __func__, __LINE__, "Invalid conditional mark"); CLEAR(csv_state, ST_CS_COND); } @@ -714,7 +720,7 @@ csv_template_start: } else if (IN(csv_state, ST_CS_COND)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_EMPTY_CND, __FILE__, __func__, __LINE__, "Empty conditional before/without nonempty " "conditional"); CLEAR(csv_state, ST_CS_COND | ST_CS_COND_EMPTY); @@ -766,13 +772,13 @@ csv_template_start: default: if (IN(csv_state, ST_CS_HEADER)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_HR_MARK, __FILE__, __func__, __LINE__, "Invalid header register mark"); CLEAR(csv_state, ST_CS_HEADER); } else if (IN(csv_state, ST_CS_REGISTER)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_REG_MARK, __FILE__, __func__, __LINE__, "Invalid register mark"); CLEAR(csv_state, ST_CS_REGISTER); } @@ -781,8 +787,6 @@ csv_template_start: pcsv_template++; } goto csv_template_start; -csv_template_done: - return 0; } static int @@ -811,7 +815,7 @@ print_image_dimensions(FILE* output, const u8* image_file_prefix, const u8* path cmd_output = popen(command, "r"); /* popen(3): "The popen() function does not reliably set errno." */ if (!cmd_output) - return error(1, __FILE__, __func__, __LINE__, + return error(ERR_POPEN_FAIL, __FILE__, __func__, __LINE__, "popen failed"); if (!fgets(cmd_output_line, BUFSIZE, cmd_output)) goto print_dimensions_cleanup; @@ -827,7 +831,7 @@ print_dimensions_cleanup: return 0; } -static int +static void print_meta_var(FILE* output, u8** tsv_header, u8** tsv_register) { u8* pvalue; @@ -837,7 +841,7 @@ print_meta_var(FILE* output, u8** tsv_header, u8** tsv_register) assert((output != NULL) && (tsv_header != NULL) && (tsv_register != NULL)); if (!*tsv_register || !*(tsv_register + 1)) - return 0; + return; pvalue = *(tsv_register + 1); value_len = strlen((char*)pvalue); if (*pvalue == '%' && *(pvalue + value_len - 1) == '%') @@ -854,7 +858,6 @@ print_meta_var(FILE* output, u8** tsv_header, u8** tsv_register) else print_output(output, "<meta name=\"%s\" content=\"%s\">\n", *tsv_register, *(tsv_register + 1)); - return 0; } #define PRINTTSVIF(format, arg) \ @@ -869,7 +872,7 @@ print_meta_var(FILE* output, u8** tsv_header, u8** tsv_register) fprintf(output, format, arg); \ } while (0) -static int +static void print_tsv_row(FILE* output, u8** tsv_header, u8** tsv_register) { u8* ptsv_template = tsv_template; @@ -881,7 +884,7 @@ print_tsv_row(FILE* output, u8** tsv_header, u8** tsv_register) && (tsv_register != NULL)); tsv_template_start: if (!*ptsv_template) - goto tsv_template_done; + return; if (IN(tsv_state, ST_CS_ESCAPE)) { PRINTTSVIF("%c", *ptsv_template); @@ -909,7 +912,7 @@ tsv_template_start: case '#': if (IN(tsv_state, ST_CS_HEADER)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_HR_MARK, __FILE__, __func__, __LINE__, "Invalid header register mark"); CLEAR(tsv_state, ST_CS_REGISTER | ST_CS_HEADER); } @@ -925,7 +928,7 @@ tsv_template_start: case '?': if (IN(tsv_state, ST_CS_COND)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_CND_MARK, __FILE__, __func__, __LINE__, "Invalid conditional mark"); CLEAR(tsv_state, ST_CS_COND); } @@ -946,7 +949,7 @@ tsv_template_start: } else if (IN(tsv_state, ST_CS_COND)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_EMPTY_CND, __FILE__, __func__, __LINE__, "Empty conditional before/without nonempty " "conditional"); CLEAR(tsv_state, ST_CS_COND | ST_CS_COND_EMPTY); @@ -998,13 +1001,13 @@ tsv_template_start: default: if (IN(tsv_state, ST_CS_HEADER)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_HR_MARK, __FILE__, __func__, __LINE__, "Invalid header register mark"); CLEAR(tsv_state, ST_CS_HEADER); } else if (IN(tsv_state, ST_CS_REGISTER)) { - error(1, __FILE__, __func__, __LINE__, + error(ERR_BAD_REG_MARK, __FILE__, __func__, __LINE__, "Invalid register mark"); CLEAR(tsv_state, ST_CS_REGISTER); } @@ -1013,8 +1016,6 @@ tsv_template_start: ptsv_template++; } goto tsv_template_start; -tsv_template_done: - return 0; } static int @@ -1133,7 +1134,7 @@ process_csv(FILE* output, const u8* arg_token, else { if (ANY(state, ST_CSV_BODY | ST_TSV_BODY)) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_NEST_CSV, __FILE__, __func__, __LINE__, "Can't nest csv/tsv directives")); SET(state, ST_CSV_BODY); if (read_yaml_macros_and_links) @@ -1142,11 +1143,11 @@ process_csv(FILE* output, const u8* arg_token, (void)strtok_r((char*)arg_token, " ", (char**)&saveptr); args = (u8*)strtok_r(NULL, " ", (char**)&saveptr); if (!args) - exit(error(EINVAL, __FILE__, __func__, __LINE__, + exit(error(ERR_NO_ARG, __FILE__, __func__, __LINE__, "Arguments required")); args_len = strlen((char*)args); if (*args != '"' || *(args + args_len - 1) != '"') - exit(error(EINVAL, __FILE__, __func__, __LINE__, + exit(error(ERR_ARG_NOTSTR, __FILE__, __func__, __LINE__, "First argument must be a string")); if (!csv_filename) CALLOC(csv_filename, char, BUFSIZE); @@ -1161,8 +1162,11 @@ process_csv(FILE* output, const u8* arg_token, errno = 0; csv_iter = (size_t)strtol((char*)args, NULL, 10); if (errno) + { + perror(PROGRAMNAME ": strtol"); exit(error(errno, __FILE__, __func__, __LINE__, "Invalid argument '%s'", args)); + } } } return 0; @@ -1294,8 +1298,8 @@ process_image(FILE* output, const u8* image_text, const u8* image_file_prefix, const int add_figcaption) { u8* url = get_value(links, links_count, image_id, NULL); - process_inline_image(output, image_text, image_file_prefix, - link_prefix, url, add_link, add_figcaption); + process_inline_image(output, image_text, image_file_prefix, link_prefix, + url, add_link, add_figcaption); } static int @@ -1324,11 +1328,11 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix, (void)strtok_r((char*)token, " ", (char**)&saveptr); arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr); if (!arg) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_NO_ARG, __FILE__, __func__, __LINE__, "Arguments required")); arg_len = strlen((char*)arg); if (*arg != '"' || *(arg + arg_len - 1) != '"') - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_ARG_NOTSTR, __FILE__, __func__, __LINE__, "First argument not string")); incdir = strdup((char*)(arg + 1)); @@ -1349,15 +1353,18 @@ incdir_next_arg: while (parg && *parg) { if (*parg < '0' || *parg > '9') - exit(error(1, __FILE__, __func__, __LINE__, - "Invalid argument")); + exit(error(ERR_ARG_NOTNUM, __FILE__, __func__, + __LINE__, "Argument not a number")); parg++; } errno = 0; num = strtol((char*)arg, NULL, 10); if (errno) + { + perror(PROGRAMNAME ": strtol"); exit(error(errno, __FILE__, __func__, __LINE__, "Invalid parameter 'num'")); + } } pass++; if (pass < 3) @@ -1369,7 +1376,7 @@ incdir_done_args: if ((names_total = scandir(incdir, &namelist, &filter_subdirs, &reverse_alphacompare)) < 0) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_SCANDIR_FAIL, __FILE__, __func__, __LINE__, "scandir '%s' failed", incdir)); pnamelist = namelist; names_output = 0; @@ -1446,7 +1453,7 @@ process_incdir_subdir(FILE* output, const char* subdirname, &reverse_alphacompare)) < 0) { - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_SCANDIR_FAIL, __FILE__, __func__, __LINE__, "scandir '%s' failed", abs_subdirname)); } @@ -1458,7 +1465,8 @@ process_incdir_subdir(FILE* output, const char* subdirname, if (!list_only) print_output(output, "<article>\n"); fflush(output); - pid = fork(); + errno = 0; + pid = fork(); if (pid > 0) wait(&pstatus); else if (pid == 0) @@ -1511,7 +1519,8 @@ process_incdir_subdir(FILE* output, const char* subdirname, formatted_date = format_date(date, list_timestamp_format); if (!formatted_date) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_FORMAT_DATE_FAIL, __FILE__, + __func__, __LINE__, "format_date error")); /* Have to temporarily reset this because of potential @@ -1599,8 +1608,11 @@ process_incdir_subdir(FILE* output, const char* subdirname, exit(result); } else - exit(error(1, __FILE__, __func__, __LINE__, + { + perror(PROGRAMNAME ": fork"); + exit(error(errno, __FILE__, __func__, __LINE__, "fork failed")); + } if (!list_only) print_output(output, "</article>\n"); @@ -1622,7 +1634,7 @@ process_incdir_subdir(FILE* output, const char* subdirname, output_firstcol = 0; } -static int +static void process_include(FILE* output, const u8* token, const int read_yaml_macros_and_links) { @@ -1645,15 +1657,19 @@ process_include(FILE* output, const u8* token, assert((output != NULL) && (token != NULL)); ptoken = (u8*)strchr((char*)token, ' '); if (!input_filename) - return warning(1, + { + warning(1, (u8*)"process_include: Cannot use 'include' in stdin"); + return; + } if (!ptoken) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_NO_ARG, __FILE__, __func__, __LINE__, "Directive 'include' requires an argument")); fflush(output); pipe(arg_pipe_fds); pipe(output_pipe_fds); - pid = fork(); + errno = 0; + pid = fork(); if (pid > 0) /* parent */ { child_output = NULL; @@ -1760,8 +1776,10 @@ process_include(FILE* output, const u8* token, exit(result); } else - exit(error(1, __FILE__, __func__, __LINE__, "fork failed")); - return 0; + { + perror(PROGRAMNAME ": fork"); + exit(error(errno, __FILE__, __func__, __LINE__, "fork failed")); + } } static int @@ -2010,7 +2028,7 @@ process_macro(FILE* output, const u8* token, const int end_tag) assert((output != NULL) && (token != NULL)); macro_body = get_value(macros, macros_count, token + 1, NULL); if (!macro_body) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_MACRO_UNDEF, __FILE__, __func__, __LINE__, "Macro '%s' undefined", token + 1)); eol = (u8*)strrchr((char*)macro_body, '\n'); @@ -2039,7 +2057,7 @@ process_macro_def(FILE* output, const u8* token, return 0; } if (IN(state, ST_MACRO_BODY)) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_NEST_MACRO, __FILE__, __func__, __LINE__, "Cannot nest definitions")); if (read_yaml_macros_and_links) @@ -2351,7 +2369,7 @@ process_tsv(FILE* output, const u8* arg_token, else { if (ANY(state, ST_CSV_BODY | ST_TSV_BODY)) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_NEST_CSV, __FILE__, __func__, __LINE__, "Can't nest csv/tsv directives")); SET(state, ST_TSV_BODY); if (read_yaml_macros_and_links) @@ -2360,11 +2378,11 @@ process_tsv(FILE* output, const u8* arg_token, (void)strtok_r((char*)arg_token, " ", (char**)&saveptr); args = (u8*)strtok_r(NULL, " ", (char**)&saveptr); if (!args) - exit(error(EINVAL, __FILE__, __func__, __LINE__, + exit(error(ERR_NO_ARG, __FILE__, __func__, __LINE__, "Arguments required")); args_len = strlen((char*)args); if (*args != '"' || *(args + args_len - 1) != '"') - exit(error(EINVAL, __FILE__, __func__, __LINE__, + exit(error(ERR_ARG_NOTSTR, __FILE__, __func__, __LINE__, "First argument must be a string")); if (!tsv_filename) CALLOC(tsv_filename, char, BUFSIZE); @@ -2379,8 +2397,11 @@ process_tsv(FILE* output, const u8* arg_token, errno = 0; tsv_iter = (size_t)strtol((char*)args, NULL, 10); if (errno) + { + perror(PROGRAMNAME ": strtol"); exit(error(errno, __FILE__, __func__, __LINE__, "Invalid argument '%s'", args)); + } } } } @@ -2405,11 +2426,11 @@ process_tsv_count(FILE* output, const u8* arg_token, (void)strtok_r((char*)arg_token, " ", (char**)&saveptr); args = (u8*)strtok_r(NULL, " ", (char**)&saveptr); if (!args) - exit(error(EINVAL, __FILE__, __func__, __LINE__, + exit(error(ERR_NO_ARG, __FILE__, __func__, __LINE__, "Arguments required")); args_len = strlen((char*)args); if (*args != '"' || *(args + args_len - 1) != '"') - exit(error(EINVAL, __FILE__, __func__, __LINE__, + exit(error(ERR_ARG_NOTSTR, __FILE__, __func__, __LINE__, "First argument must be a string")); if (!tsv_filename) CALLOC(tsv_filename, char, BUFSIZE); @@ -2470,7 +2491,7 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback) assert((output != NULL) && (filename != NULL) && (callback != NULL)); csv_delimiter = get_value(vars, vars_count, (u8*)"csv-delimiter", NULL); - errno = 0; + errno = 0; if (!(csv = fopen(filename, "rt"))) { perror(PROGRAMNAME ": fopen"); @@ -2910,7 +2931,7 @@ strip_ext(const char* fn, const size_t fn_size) dot = strrchr(fn, '.'); if (!dot) return NULL; - errno = 0; + errno = 0; newname = strndup(fn, fn_size); if (!newname) { @@ -2981,60 +3002,59 @@ slweb_parse(FILE* output, const char* source_filename, const size_t sfn_size, const u8* buffer, const int body_only, const int read_yaml_macros_and_links) { - u8* title = NULL; - u8* title_heading_level = NULL; - u8* header_text = NULL; - u8* author = NULL; - u8* date = NULL; - u8* permalink_url = NULL; - u8* ext_in_permalink = NULL; - u8* var_add_article_header = NULL; - u8* var_add_image_links = NULL; - u8* var_add_figcaption = NULL; - u8* var_add_footnote_div = NULL; - u8* footer_permalink_text = NULL; - u8* var_incdir_only_summary = NULL; - u8* image_file_prefix = NULL; - u8* link_prefix = NULL; - const u8* pbuffer = NULL; - u8* line = NULL; - u8* pline = NULL; - u8* token = NULL; - u8* ptoken = NULL; - u8* link_text = NULL; - u8* link_macro = NULL; - u8* temp = NULL; - u8* temp2 = NULL; - u8* eol = NULL; - size_t line_len = 0; - size_t line_size = 0; - size_t entity_len = 0; - size_t token_size = 0; - size_t token_len = 0; - size_t value_len = 0; - size_t link_size = 0; - size_t heading_count = 0; - size_t pline_len = 0; - int break_mark = 0; - int end_tag = 0; - int first_line_in_doc = 1; + const u8* pbuffer = NULL; + u8* author = NULL; + u8* date = NULL; + u8* eol = NULL; + u8* ext_in_permalink = NULL; + u8* footer_permalink_text = NULL; + u8* header_text = NULL; + u8* image_file_prefix = NULL; + u8* line = NULL; + u8* link_macro = NULL; + u8* link_prefix = NULL; + u8* link_text = NULL; + u8* permalink_url = NULL; + u8* pline = NULL; + u8* ptoken = NULL; + u8* temp = NULL; + u8* temp2 = NULL; + u8* title = NULL; + u8* title_heading_level = NULL; + u8* token = NULL; + u8* var_add_article_header = NULL; + u8* var_add_figcaption = NULL; + u8* var_add_footnote_div = NULL; + u8* var_add_image_links = NULL; + u8* var_incdir_only_summary = NULL; + size_t entity_len = 0; + size_t heading_count = 0; + size_t line_len = 0; + size_t line_size = 0; + size_t link_size = 0; + size_t pline_len = 0; + size_t token_len = 0; + size_t token_size = 0; + size_t value_len = 0; + int add_figcaption = 1; + int add_footnote_div = 0; + int add_image_links = 1; + int break_mark = 0; + int end_tag = 0; + int first_line_in_doc = 1; + int footnote_at_line_start = 0; + int keep_token = 0; + int list_para = 0; + int madeby_present = 0; + int previous_line_blank = 0; + int previous_line_block = 0; + int processed_start_of_line = 0; + int save_errno; int skip_change_first_line_in_doc = 0; int skip_eol = 0; - int keep_token = 0; - int previous_line_blank = 0; - int previous_line_block = 0; - int processed_start_of_line = 0; - int add_image_links = 1; - int add_figcaption = 1; - int add_footnote_div = 0; - int list_para = 0; - int footnote_at_line_start = 0; - int madeby_present = 0; unsigned char heading_level = 0; - if (!buffer) - exit(error(1, __FILE__, __func__, __LINE__, "Empty buffer")); - + assert((output != NULL) && (buffer != NULL)); title = get_value(vars, vars_count, (u8*)"title", NULL); title_heading_level = get_value(vars, vars_count, (u8*)"title-heading-level", NULL); @@ -4699,7 +4719,8 @@ do_line: if (strlen((char*)pline) > 1 && *(pline + 1) == '$') { if (IN(state, ST_FORMULA)) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_NEST_MATH, __FILE__, __func__, + __LINE__, "Display formula within an open " "formula")); @@ -4731,7 +4752,8 @@ do_line: else { if (IN(state, ST_DISPLAY_FORMULA)) - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_NEST_MATH, __FILE__, __func__, + __LINE__, "Formula within an open display " "formula")); if (!(IN(state, ST_FORMULA))) @@ -5189,14 +5211,15 @@ done_buffer: free(link_macro); free(token); free(line); - return 0; + return ERR_NONE; parse_alloc_error: + save_errno = errno; free(link_text); free(link_macro); free(token); free(line); - return 1; + return save_errno; } int @@ -5211,7 +5234,7 @@ main(const int argc, const char** argv) Command cmd = CMD_NONE; size_t buffer_size = 0; int body_only = 0; - int result = 0; + int result = ERR_NONE; UNUSED(argc); basedir_size = 2; @@ -5222,9 +5245,9 @@ main(const int argc, const char** argv) { if (*arg == '-') { + char c; arg++; - char c = *arg++; - int result; + c = *arg++; if (c == '-') { @@ -5256,8 +5279,8 @@ main(const int argc, const char** argv) exit(usage()); else { - error(EINVAL, __FILE__, __func__, - __LINE__, + error(ERR_BAD_CL_ARG, __FILE__, + __func__, __LINE__, "Invalid argument: --%s", arg); exit(usage()); } @@ -5285,16 +5308,15 @@ main(const int argc, const char** argv) cmd = CMD_VERSION; break; default: - error(EINVAL, __FILE__, __func__, - __LINE__, + usage(); + return error(ERR_BAD_CL_ARG, __FILE__, + __func__, __LINE__, "Invalid argument: -%c", c); - return usage(); } } } else { - int result; switch (cmd) { case CMD_BASEDIR: @@ -5321,7 +5343,7 @@ main(const int argc, const char** argv) switch (cmd) { case CMD_BASEDIR: - exit(error(1, __FILE__, __func__, __LINE__, + exit(error(ERR_NO_ARG, __FILE__, __func__, __LINE__, "Argument required")); case CMD_FULL_VERSION: version(1);