poe

Уређивач .po фајлова
git clone https://git.sr.ht/~strahinja/poe
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување fdd05361bfeb8eac18c6d0653b22d9639211e148
родитељ c7a458f3a45badfd8094e5cd69e10d556a6ab846
Аутор: Страхиња Радић <sr@strahinja.org>
Датум:   Sun, 22 Mar 2026 20:20:54 +0000

Replace sscanf with new function: strtonum, for more robust number 
parsing

Diffstat:
MMakefile | 2+-
Mconfig.Haiku | 7++++---
Mconfig.Linux | 7++++---
Mconfig.OpenBSD | 7++++---
Mpo.c | 6+++++-
Mpoe.c | 5++++-
Astrtonum.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astrtonum.h | 16++++++++++++++++
измењених датотека: 8, додавања: 134(+), брисања: 12(-)

diff --git a/Makefile b/Makefile @@ -28,7 +28,7 @@ makedate: makeversion: sh lib/makeversion -l -poe.o: poe.c config.h draw.h limit.h po.h termbox.h util.h version.h +poe.o: poe.c config.h draw.h limit.h po.h strtonum.h termbox.h util.h version.h $(MANPAGE): $(MANPAGE).in date version diff --git a/config.Haiku b/config.Haiku @@ -5,9 +5,10 @@ CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \ DESTDIR = /boot/home/config/non-packaged INSTALL = install LIBS = -SRC = draw.c limit.c po.c poe.c util.c -HEADERS = config.h draw.h limit.h po.h termbox.h util.h version.h -OBJS = draw.o limit.o po.o poe.o util.o +SRC = draw.c limit.c po.c poe.c strtonum.c util.c +HEADERS = config.h draw.h limit.h po.h strtonum.h termbox.h util.h \ + version.h +OBJS = draw.o limit.o po.o poe.o strtonum.o util.o PREFIX = PROG = poe diff --git a/config.Linux b/config.Linux @@ -3,9 +3,10 @@ CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \ -D_XOPEN_SOURCE=700 -DNDEBUG INSTALL = install LIBS = -SRC = draw.c limit.c po.c poe.c util.c -HEADERS = config.h draw.h limit.h po.h termbox.h util.h version.h -OBJS = draw.o limit.o po.o poe.o util.o +SRC = draw.c limit.c po.c poe.c strtonum.c util.c +HEADERS = config.h draw.h limit.h po.h strtonum.h termbox.h util.h \ + version.h +OBJS = draw.o limit.o po.o poe.o strtonum.o util.o PREFIX = /usr/local PROG = poe diff --git a/config.OpenBSD b/config.OpenBSD @@ -3,9 +3,10 @@ CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \ -D_XOPEN_SOURCE=700 -D_BSD_SOURCE -DNDEBUG INSTALL = install LIBS = -SRC = draw.c limit.c po.c poe.c util.c -HEADERS = config.h draw.h limit.h po.h termbox.h util.h version.h -OBJS = draw.o limit.o po.o poe.o util.o +SRC = draw.c limit.c po.c poe.c strtonum.c util.c +HEADERS = config.h draw.h limit.h po.h strtonum.h termbox.h util.h \ + version.h +OBJS = draw.o limit.o po.o poe.o strtonum.o util.o PREFIX = /usr/local PROG = poe diff --git a/po.c b/po.c @@ -14,6 +14,7 @@ #include "config.h" #include "limit.h" #include "po.h" +#include "strtonum.h" #include "util.h" #include "version.h" @@ -1335,6 +1336,7 @@ set_nplurals(struct DrawState* state, struct PoEntry* entry) uint32_t* ppf; uint32_t* temp; char* ptoken = token; + int errornum; int read_number = 0; int nplurals_len = 0; @@ -1376,7 +1378,9 @@ set_nplurals(struct DrawState* state, struct PoEntry* entry) } if (*ptoken) { - if (sscanf(ptoken, "%d", &state->nplurals) < 1) + state->nplurals + = strtonumber(ptoken, 0, INT_MAX, &errornum); + if (errornum != STN_NONE) { state->error = ERR_BAD_NPLURALS; return 1; diff --git a/poe.c b/poe.c @@ -33,6 +33,7 @@ #include "config.h" #include "limit.h" #include "po.h" +#include "strtonum.h" #include "util.h" #include "version.h" @@ -2592,6 +2593,7 @@ main(int argc, char** argv) long lineno = 1; int dir_access; int dir_access_errno; + int errornum; int optind = 1; int result; int saved_errno = 0; @@ -2695,7 +2697,8 @@ main_options_loop: || !strcmp(argv[optind], "--wrap-width=")) { optind++; - if (sscanf(argv[optind], "%d", &wrap_width) < 1) + wrap_width = strtonumber(argv[optind], 0, INT_MAX, &errornum); + if (errornum != STN_NONE) { if (*argv[optind] == '-') state.error = ERR_NO_CL_ARG_PARAM; diff --git a/strtonum.c b/strtonum.c @@ -0,0 +1,96 @@ +/* This program is licensed under the terms of GNU GPL v3 or (at your option) + * any later version. Copyright (C) 2026 Страхиња Радић. + * See the file LICENSE for exact copyright and license details. */ + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "strtonum.h" + +/* Returns 0 on no error, otherwise returns 1 after outputting error message */ +int +stn_handle_error(const char* str, const long long minval, + const long long maxval, const int errornum) +{ + switch (errornum) + { + case STN_NOTNUM: + fprintf(stderr, "strtonumber: Not a number: %s\n", str); + return 1; + case STN_INVLIMITS: + fprintf(stderr, "strtonumber: Invalid limit specification\n"); + return 1; + case STN_UNDERFLOW: + fprintf(stderr, "strtonumber: Underflow: %s < %lld\n", str, + minval); + return 1; + case STN_OVERFLOW: + fprintf(stderr, "strtonumber: Overflow: %s > %lld\n", str, + maxval); + return 1; + default:; + } + return 0; +} + +/* - Returns the converted number or 0 on error (*not* indicative of error; see + * below) + * - Clears errno (discards any previous value) because of strtoll + * - Instead, returns any errors in errornum (if non-NULL); + * *errornum == STN_NONE indicates success, any other value indicates error */ +long long +strtonumber(const char* str, const long long minval, const long long maxval, + int* errornum) +{ + long long n; + char* end = NULL; + + if (minval > maxval) + { + if (errornum) + *errornum = STN_INVLIMITS; + return 0; + } + errno = 0; + if (errornum) + *errornum = STN_NONE; + n = strtoll(str, &end, 10); + if (!*str || *end) + { + errno = 0; + if (errornum) + *errornum = STN_NOTNUM; + return 0; + } + else if (errno == ERANGE) + { + errno = 0; + if (errornum) + *errornum + = n == LLONG_MIN ? STN_UNDERFLOW : STN_OVERFLOW; + return 0; + } + else + { + errno = 0; + if (n > maxval) + { + if (errornum) + *errornum = STN_OVERFLOW; + return 0; + } + else if (n < minval) + { + if (errornum) + *errornum = STN_UNDERFLOW; + return 0; + } + else + return n; + } + /* Not reached */ + return n; +} diff --git a/strtonum.h b/strtonum.h @@ -0,0 +1,16 @@ +/* This program is licensed under the terms of GNU GPL v3 or (at your option) + * any later version. Copyright (C) 2026 Страхиња Радић. + * See the file LICENSE for exact copyright and license details. */ + +enum { + STN_NONE, + STN_NOTNUM, + STN_INVLIMITS, + STN_UNDERFLOW, + STN_OVERFLOW, +}; + +int stn_handle_error(const char* str, const long long minval, + const long long maxval, const int errornum); +long long strtonumber(const char* str, const long long minval, + const long long maxval, int* errornum);