summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/api.rst43
-rw-r--r--doc/changelog.rst58
-rw-r--r--doc/inline_clist.rst2
-rw-r--r--doc/inline_list.rst2
-rw-r--r--doc/misc_functions.rst2
-rw-r--r--doc/option_parsing.rst326
-rw-r--r--doc/string_ops.rst74
7 files changed, 312 insertions, 195 deletions
diff --git a/doc/api.rst b/doc/api.rst
index 2579486..332fca9 100644
--- a/doc/api.rst
+++ b/doc/api.rst
@@ -4,11 +4,20 @@ Function reference
* R column: Recommend version number to use in ``PKG_CONFIG_CHECK`` in
projects using libHX. Includes important bugfixes.
* M column: Lowest possible version with the same ABI (minus cv qualification).
-* F column: First version that the function name was in use.
+* F column: First version that the symbol name was in use.
====== ====== ====== ========================================
RMV MinVer FirstA Name
====== ====== ====== ========================================
+5.0 5.0 4.28 HXdeque_to_vecx
+5.2 4.28 4.28 HX_getopt6
+4.28 4.28 4.28 HX_getopt6_clean
+4.28 inline 4.28 HXOPT_CONST_INPUT
+4.28 inline 4.28 HXOPT_ITER_OPTS
+4.28 inline 4.28 HXOPT_ITER_ARGS
+4.28 inline 4.28 HXOPT_ITER_OA
+4.28 inline 4.28 HXOPT_DUP_ARGS
+4.28 4.28 4.28 HX_strtoull8601p_sec
4.27 inline 4.27 float_cpu_to_{le,be}{32,64}p
4.27 inline 4.27 float_{le,be}{32,64}p_to_cpu
4.25 inline 4.25 HX_isascii
@@ -17,7 +26,6 @@ RMV MinVer FirstA Name
4.25 inline 4.25 le{16,32,64}p_to_cpu be{16,32,64}p_to_cpu
4.25 4.25 4.25 HXSIZEOF_UNITSEC64
4.24 4.24 4.24 HX_getcwd
-4.19 4.18 4.18 HX_getopt5
4.16 4.16 4.16 HX_strtoull_nsec
4.15 4.15 4.15 HX_flpr
4.15 4.15 4.15 HX_flprf
@@ -35,7 +43,6 @@ RMV MinVer FirstA Name
4.2 4.2 4.2 HX_unit_size_cu
4.2 4.2 4.2 HX_strtod_unit
4.2 4.2 4.2 HX_strtoull_unit
-3.27 3.27 3.27 HXOPT_KEEP_ARGV
3.27 3.27 3.27 HXproc_top_fd
3.27 3.27 3.27 HXproc_switch_user
3.27 3.27 3.27 HXPROC_SU_SUCCESS
@@ -49,10 +56,7 @@ RMV MinVer FirstA Name
3.27 3.27 3.27 HX_slurp_file
3.25 3.25 3.25 HX_split_fixed
3.25 3.25 3.25 HX_split_inplace
-3.22 3.22 3.22 HXQUOTE_SQLBQUOTE
3.21 3.21 3.21 xml_getnsprop
-3.19 3.19 3.19 HXQUOTE_SQLSQUOTE
-3.18 3.18 3.18 HX_stpltrim
3.17 3.17 3.17 HX_LONGLONG_FMT
3.17 3.17 3.17 HX_SIZET_FMT
3.16 3.16 3.16 container_of
@@ -75,7 +79,6 @@ RMV MinVer FirstA Name
3.13 3.13 3.13 HX_timeval_sub
3.12 3.12 1.10.0 HX_mkdir
3.12 3.12 3.12 HX_strndup
-3.12 3.12 3.12 HX_strnlen
3.12 3.0 3.0 HXMAP_CDATA
3.12 3.0 3.0 HXMAP_CKEY
3.12 3.0 3.0 HXMAP_SCDATA
@@ -87,9 +90,9 @@ RMV MinVer FirstA Name
3.12 3.12 3.12 HXOPT_ERR_SYS
3.12 3.12 3.12 HXOPTCB_BY_LONG
3.12 3.12 3.12 HXOPTCB_BY_SHORT
-3.12 3.0 1.10.0 HXformat_aprintf
-3.12 3.0 1.10.0 HXformat_fprintf
-3.12 3.0 1.10.0 HXformat_sprintf
+3.12 4.9 1.10.0 HXformat_aprintf / HXformat3_aprintf
+3.12 4.9 1.10.0 HXformat_fprintf / HXformat3_fprintf
+3.12 4.9 1.10.0 HXformat_sprintf / HXformat3_sprintf
3.11 3.11 3.11 HXQUOTE_BASE64
3.10 3.10 3.10 BUILD_BUG_ON_EXPR
3.10 3.10 3.10 HX_readlink
@@ -216,7 +219,7 @@ RMV MinVer FirstA Name
1.28 1.28 1.28 HXTYPE_UINT32
1.28 1.28 1.28 HXTYPE_UINT64
1.28 1.28 1.28 HXTYPE_UINT8
-1.26 1.26 1.26 HX_hexdump
+1.26 5.0 1.26 HX_hexdump
1.26 1.26 1.26 HX_time_compare
1.25 1.25 1.25 HX_getl
1.25 1.25 1.25 HXmc_free
@@ -266,7 +269,6 @@ RMV MinVer FirstA Name
1.10.0 1.10.0 1.10.0 HXOPT_AND
1.10.0 1.10.0 1.10.0 HXOPT_AUTOHELP
1.10.0 1.10.0 1.10.0 HXOPT_DEC
-1.10.0 1.10.0 1.10.0 HXOPT_DESTROY_OLD
1.10.0 1.10.0 1.10.0 HXOPT_ERR_MIS
1.10.0 1.10.0 1.10.0 HXOPT_ERR_UNKN
1.10.0 1.10.0 1.10.0 HXOPT_ERR_VOID
@@ -275,7 +277,6 @@ RMV MinVer FirstA Name
1.10.0 1.10.0 1.10.0 HXOPT_NOT
1.10.0 1.10.0 1.10.0 HXOPT_OPTIONAL
1.10.0 1.10.0 1.10.0 HXOPT_OR
-1.10.0 1.10.0 1.10.0 HXOPT_PTHRU
1.10.0 1.10.0 1.10.0 HXOPT_QUIET
1.10.0 1.10.0 1.10.0 HXOPT_TABLEEND
1.10.0 1.10.0 1.10.0 HXOPT_USAGEONERR
@@ -307,13 +308,10 @@ RMV MinVer FirstA Name
1.10.0 1.10.0 1.10.0 HX_dlerror
1.10.0 1.10.0 1.10.0 HX_dlopen
1.10.0 1.10.0 1.10.0 HX_dlsym
-1.10.0 1.10.0 1.10.0 HX_dlsym<>
-1.10.0 1.10.0 1.10.0 HX_getopt
1.10.0 1.10.0 1.10.0 HX_getopt_help
1.10.0 1.10.0 1.10.0 HX_getopt_usage
1.10.0 1.10.0 1.10.0 HX_irand
1.10.0 1.10.0 1.10.0 HX_memdup
-1.10.0 1.10.0 1.10.0 HX_memdup<>
1.10.0 1.10.0 1.10.0 HX_rand
1.10.0 1.10.0 1.10.0 HX_rrmdir
1.10.0 1.10.0 1.10.0 HX_shconfig_free
@@ -329,7 +327,6 @@ RMV MinVer FirstA Name
1.10.0 1.10.0 1.10.0 HX_strrcspn
1.10.0 1.10.0 1.10.0 HX_strrev
1.10.0 1.10.0 1.10.0 HX_strrtrim
-1.10.0 1.10.0 1.10.0 HX_strsep
1.10.0 1.10.0 1.10.0 HX_strsep2
1.10.0 1.10.0 1.10.0 HX_strupper
1.10.0 1.10.0 1.10.0 HX_zvecfree
@@ -342,8 +339,7 @@ RMV MinVer FirstA Name
1.10.0 1.10.0 1.10.0 HXdeque_pop
1.10.0 1.10.0 1.10.0 HXdeque_push
1.10.0 1.10.0 1.10.0 HXdeque_shift
-1.10.0 1.10.0 1.10.0 HXdeque_to_vec
-1.10.0 1.10.0 1.10.0 HXdeque_to_vec<>
+5.0 5.0 1.10.0 HXdeque_to_vec
1.10.0 1.10.0 1.10.0 HXdeque_unshift
1.10.0 1.10.0 1.10.0 SHCONF_ONE
====== ====== ====== ========================================
@@ -355,6 +351,7 @@ Struct reference
====== ====== ================================================
MinVer FirstA
====== ====== ================================================
+4.28 4.28 struct HXopt6_result
2.0 2.0 struct HXdeque_node.sptr
1.10.0 1.10.0 struct HXdeque_node
1.10.0 1.10.0 struct HXdeque
@@ -376,6 +373,12 @@ Header reference
====== ===================================
MinVer Name
====== ===================================
+4.27 endian_float.h
+4.25 endian.h
+4.25 scope.hpp
+4.18 cast.h
+4.0 socket.h
+3.25 intdiff.hpp
3.9 libHX/io.h
3.4 libHX/init.h
3.0 libHX/map.h
@@ -384,7 +387,7 @@ MinVer Name
2.0 libHX/ctype_helper.h
1.23 libHX/misc.h
1.23 libHX/defs.h
-1.22 libHX/xml_helper.h
+1.22 libHX/libxml_helper.h
1.15 libHX/string.h
1.15 libHX/option.h
1.15 libHX/list.h
diff --git a/doc/changelog.rst b/doc/changelog.rst
index 94708fb..6d399ae 100644
--- a/doc/changelog.rst
+++ b/doc/changelog.rst
@@ -1,3 +1,61 @@
+v5.2 (2025-10-19)
+=================
+
+Fixes:
+
+* Cure buffer overflows in HXdir_read, HX_getopt6 and a use-after-free
+ in conjunction with HX_getopt6's result struct.
+
+
+v5.1 (2025-10-11)
+=================
+
+Enhancements:
+
+* getopt6: ``HXTYPE_STRP`` can now be used for HXoption::type. This will
+ perform assignment without strdup.
+* io: handle undocumented return code from FreeBSD/OpenBSD mkdir("/")
+
+Fixes:
+
+* map: resolve corruption of HXmap::items field
+
+
+v5.0 (2025-10-01)
+=================
+
+Enhancements:
+
+* getopt6: new function set ``HX_getopt6`` which allows for parsing options
+ with an iterative style.
+* getopt6: the result set no longer forces strdup-ed results on the user.
+
+Changes:
+
+* Deleted functions ``HX_getopt``, ``HX_getopt5`` (use ``HX_getopt6`` instead),
+ ``HX_strnlen`` (use ``strnlen`` instead), ``HX_strsep`` (use ``strtok_r``
+ instead), ``HX_stpltrim`` (no replacement).
+* The struct members ``HXclist::items``, ``HXdeque::items``, ``HXmap::items``
+ have changed from ``unsigned int`` to ``size_t``. The function
+ ``HXdeque_to_vec`` has accordingly changed the result parameter type.
+
+
+v4.28 (2025-09-10)
+==================
+
+Enhancements:
+
+* string: make HX_strtoull_sec support some ISO 8601 periods
+* string: add function HX_strtoull8601p_sec
+* opt: new getopt API that facilitates iterating over options and non-options
+ and doing away with unnecessary memory allocations
+
+Changes:
+
+* opt: the implementation for the HXOPT_PTHRU flag was deleted (its use will
+ now be rejected by the parser)
+
+
v4.27 (2025-03-17)
==================
diff --git a/doc/inline_clist.rst b/doc/inline_clist.rst
index f7bf138..f0b7821 100644
--- a/doc/inline_clist.rst
+++ b/doc/inline_clist.rst
@@ -53,7 +53,7 @@ Synopsis
Removes the first node in the list and returns it.
``HXclist_del``
- Deletes the node from the list.
+ Unlinks the node from the list.
The list count in the clist head is updated whenever a modification is done on
the clist through these functions.
diff --git a/doc/inline_list.rst b/doc/inline_list.rst
index 3e4cb7c..a9dca65 100644
--- a/doc/inline_list.rst
+++ b/doc/inline_list.rst
@@ -80,7 +80,7 @@ Synopsis
Adds ``elem`` to the end of the list.
``HXlist_del``
- Deletes the given element from the list.
+ Unlinks the given element from the list.
``HXlist_empty``
Tests whether the list is empty. (Note: For clists, you could also use
diff --git a/doc/misc_functions.rst b/doc/misc_functions.rst
index c988f37..0d9e11e 100644
--- a/doc/misc_functions.rst
+++ b/doc/misc_functions.rst
@@ -36,7 +36,7 @@ Miscellaneous functions
.. code-block:: c
#include <libHX/io.h>
- void HX_hexdump(FILE *fp, const void *ptr, unsigned int len);
+ void HX_hexdump(FILE *fp, const void *ptr, size_t len);
``HX_hexdump``
Outputs a nice pretty-printed hex and ASCII dump to the filedescriptor
diff --git a/doc/option_parsing.rst b/doc/option_parsing.rst
index fa928e0..a824559 100644
--- a/doc/option_parsing.rst
+++ b/doc/option_parsing.rst
@@ -12,13 +12,11 @@ Characteristics:
* recognition of the double dash as option list terminator
* offers POSIX strictness where the option list terminates at the first
non-option argument
-* option passthrough (conceptuall only works for options taking no argument,
- or when the argument is joined to a long option with a '=')
-* the parse function is one-shot; there is no context object (like popt),
- no global state (like getopt) and no ``while`` loop (either of the two others)
-* exclusively uses an option table
-* value storing is performed through pointers in the option table
-* or user-provided callbacks can be invoked per option
+* the parse function is one-shot; there is no state, just a result set
+* value storing is possible in different ways
+ * using pointers with type declarators in the option table
+ * with user-provided callbacks invoked per option
+ * by specifying the ITER_OPTS flag and iterating after HX_getopt6
Synopsis
@@ -38,7 +36,7 @@ Synopsis
const char *help, *htyp;
};
- int HX_getopt5(const struct HXoption *options_table, char **argv, int *new_argc, char ***new_argv, unsigned int flags);
+ int HX_getopt6(const struct HXoption *options_table, int argc, char **argv, struct HXopt6_result *result, unsigned int flags);
The various fields of ``struct HXoption`` are:
@@ -117,6 +115,29 @@ Type map
allocation so that subsequently modifying the original argument string
in any way will not falsely propagate.
+ HXTYPE_STRING is deprecated: When a user passes e.g. ``-S foo -S bar``
+ to HX_getopt, ptr would be assigned twice before control returns back
+ to the HX_getopt caller, thus leaking the memory for "foo" leaks. We
+ cannot retroactively make the assign routine call free(ptr) inbetween,
+ as some code might have assigned ptr a static buffer before the call to
+ HX_getopt, e.g.:
+
+ .. code-block:: c
+
+ char *p = "foo"; // default to foo
+ options_table[] = {
+ {0,'S',HXTYPE_STRING,&p,...},
+ };
+ HX_getopt(...);
+ // p is always valid, but may point to either static or allocated
+ // storage. [Also assumes a program that never frees these
+ // strings for brevity.]
+
+``HXTYPE_STRP``
+ The argument string pointer is stored in ``*(char **)ptr``.
+ No allocation occurs, but you are responsible for ensuring lifetime
+ adherence.
+
``HXTYPE_STRDQ``
The argument string is duplicated to a new memory region and the
resulting pointer is added to the given HXdeque. Note that you often
@@ -268,23 +289,23 @@ Invoking the parser
.. code-block:: c
- int HX_getopt5(const struct HXoption *options_table, char **argv, int *new_argc, char **new_argv, unsigned int flags);
- int HX_getopt(const struct HXoption *options_table, int *argc, char ***argv, unsigned int flags);
+ struct HXopt6_result {
+ int nargs;
+ const char **uarg;
+ char **dup_argv;
+ };
-``HX_getopt5`` is the central parsing function. ``options_table`` specifies
-the options that the parser will recognize. ``argv`` must be a NULL-terminated
-array of C strings.
+ int HX_getopt6(const struct HXoption *options_table, int argc, char **argv, struct HXopt6_result *result, unsigned int flags);
+ void HX_getopt6_clean(struct HXopt6_result *);
-If ``new_argv`` is non-NULL, the leftover arguments will be output as a new
-string vector on success. (That array can be freed with ``HX_zvecfree``). If
-``new_argc`` is non-NULL, the argument count for new_argv will be output too.
+``HX_getopt6`` is the central parsing function. ``options_table`` specifies the
+options that the parser will recognize. ``argv`` must be a vector of C strings,
+and ``argc`` be the count of strings that should be processed at most. ``argc``
+may be -1, in which case argc is auto-computed from ``argv``, and in this case,
+argv must be NULL-terminated.
The ``flags`` argument control the general behavior of ``HX_getopt``:
-``HXOPT_PTHRU``
- “Passthrough mode”. Any unknown options are passed through into
- ``new_argv``.
-
``HXOPT_QUIET``
Do not print any diagnostics when encountering errors in the user's
input.
@@ -299,12 +320,42 @@ The ``flags`` argument control the general behavior of ``HX_getopt``:
``HXOPT_RQ_ORDER``
Specifying this option terminates option processing when the first
non-option argument in argv is encountered. This behavior is also
- implicit when the environment variable ``POSIXLY_CORRECT`` is set.
-
-``HXOPT_KEEP_ARGV``
- Do not set ``*new_argc`` and ``*new_argv`` at all.
-
-The return value can be one of the following:
+ implicit when the environment variable ``POSIXLY_CORRECT`` is set
+ (and ``HXOPT_ANY_ORDER`` is not used).
+
+``HXOPT_ANY_ORDER``
+ Specifying this option allows mixing of options and non-options,
+ basically the opposite of the strict POSIX order.
+
+``HXOPT_CONST_INPUT``
+ Declaration by the user that elements in input argv must *not* be
+ reordered by the parser.
+
+``HXOPT_ITER_OPTS``
+ ``result->desc`` will be filled with pointers to the definitions of the
+ parsed options. ``result->oarg`` will be filled with pointers to the
+ option argument strings (potentially %nullptr if the option did not
+ take anything). ``result->nopts`` will be filled with the option count.
+
+``HXOPT_ITER_ARGS``
+ ``result->uarg`` will be filled with pointers to leftover arguments
+ (pointing into the memory regions of the original argv), and
+ ``result->nargs`` will contain the string count. uarg does *not*
+ contain NULL sentinel, so you cannot iterate with something like ``for
+ (const char **p = result.uarg; p != nullptr && *p != nullptr; ++p)``
+ but must use ``for (int uidx = 0; uidx < result.nargs; ++uidx)``.
+
+``HXOPT_ITER_OA``
+ Shortcut for ``HXOPT_ITER_OPTS | HXOPT_ITER_ARGS``.
+
+``HXOPT_DUP_ARGS``
+ ``result->dup_argv`` will be filled with copies of leftover arguments,
+ and ``result->nargs`` will contain the string count. dup_argv will
+ include the original argv[0]. dup_argv will also include a NULL
+ sentinel (not counted in nargs). You can move ``dup_argv`` out of the
+ result struct and free it yourself with ``HX_zvecfree`.
+
+The return value of HX_getopt6 can be one of the following:
``HXOPT_ERR_SUCCESS``
Parsing was successful.
@@ -325,17 +376,15 @@ The return value can be one of the following:
``HXOPT_ERR_AMBIG``
An abbreviation of a long option was ambiguous.
+``HXOPT_ERR_FLAGS``
+ HX_getopt6 was called with a ``flags`` value that contained illegal or
+ silly bit combinations.
+
negative non-zero
Failure on behalf of lower-level calls; errno.
-``HX_getopt`` is an older API where ``argv`` is both used for input and output.
-It recognizes additional flags/has additional behavior:
-
-``HXOPT_KEEP_ARGV``
- ``argc`` and ``argv`` is not updated.
-
-``HXOPT_DESTROY_OLD``
- Call ``HX_zvecfree`` on ``argv`` before updating it.
+Upon HXOPT_ERR_SUCCESS, ``HX_getopt6_clean`` must be called to release
+resources.
Pitfalls
@@ -358,11 +407,12 @@ The following is an example of a possible pitfall regarding ``HXTYPE_STRDQ``:
.help = "Add name"},
HXOPT_TABLEEND,
};
- if (HX_getopt5(options_table, *argv, &argc, &argv,
+ struct HXopt6_result result;
+ if (HX_getopt6(options_table, -1, *argv, &result,
HXOPT_USAGEONERR) != HXOPT_ERR_SUCCESS)
return EXIT_FAILURE;
/* ... */
- HX_zvecfree(argv);
+ HX_getopt6_clean(&result);
return EXIT_SUCCESS;
}
@@ -379,38 +429,32 @@ Limitations
The HX option parser has been influenced by both popt and Getopt::Long, but
eventually, there are differences:
-* Long options with a single dash (``-foo bar``). This unsupported
- syntax clashes easily with support for option bundling or squashing. In case
- of bundling, ``-foo`` might actually be ``-f -o -o``, or ``-f oo`` in case of
- squashing. It also introduces redundant ways to specify options, which is not
- in the spirit of the author.
+* Long options with a single dash (``-foo bar``) are not supported in HXopt.
+ This syntax clashes easily with support for option bundling or squashing. In
+ case of bundling, ``-foo`` might actually be ``-f -o -o``, or ``-f oo`` in
+ case of squashing. It also introduces redundant ways to specify options,
+ which is not in the spirit of the author.
-* Options using a ``+`` as a prefix, as in ``+foo``. Xterm for
- example uses it as a way to negate an option. In the author's opinion, using
- one character to specify options is enough — by GNU standards, a negator is
- named ``--no-foo``.
+* Options using a ``+`` as a prefix, as in ``+foo`` are not supported in HXopt.
+ Xterm for example uses it as a way to negate an option. In the author's
+ opinion, using one character to specify options is enough — by GNU standards,
+ a negator is named ``--no-foo``.
-* Table nesting like implemented in popt. HXopt has no provision for nested
- tables, as the need has not come up yet. It does however support chained
- processing. You cannot do nested tables even with callbacks, as the new argv
- array is only put in place shortly before ``HX_getopt`` returns.
+* Table nesting (like in popt) is not supported in HXopt. The need
+ has not come up yet. It does however support some forms of chained
+ processing, e.g. by using the option terminator, "--".
Examples
========
-Basic example
--------------
-
-The following code snippet should provide an equivalent of the
-GNU getopt sample.[#f5]
-
-.. [#f5] http://www.gnu.org/software/libtool/manual/libc/Example-of-Getopt.html\#Example-of-Getopt
+Storing through pointers
+------------------------
.. code-block:: c
#include <stdio.h>
- #include <stdilb.h>
+ #include <stdlib.h>
#include <libHX/option.h>
int main(int argc, char **argv)
@@ -418,7 +462,6 @@ GNU getopt sample.[#f5]
int aflag = 0;
int bflag = 0;
char *cflag = NULL;
-
struct HXoption options_table[] = {
{.sh = 'a', .type = HXTYPE_NONE, .ptr = &aflag},
{.sh = 'b', .type = HXTYPE_NONE, .ptr = &bflag},
@@ -427,20 +470,121 @@ GNU getopt sample.[#f5]
HXOPT_TABLEEND,
};
- if (HX_getopt5(options_table, argv, &argc, &argv,
- HXOPT_USAGEONERR) != HXOPT_ERR_SUCCESS)
+ if (HX_getopt6(options_table, argc, argv, nullptr,
+ HXOPT_USAGEONERR) != HXOPT_ERR_SUCCESS) {
+ free(cflag);
return EXIT_FAILURE;
+ }
printf("aflag = %d, bflag = %d, cvalue = %s\n",
- aflag, bflag, cvalue);
+ aflag, bflag, cflag != NULL ? cflag : "(null)");
+ free(cflag);
+ return EXIT_SUCCESS;
+ }
+
+Note how HXTYPE_STRING in conjunction with ``.ptr=&cflag`` will allocate a
+buffer that needs to be freed.
+
+Storing via iteration
+---------------------
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <libHX/option.h>
- while (*++argv != NULL)
- printf("Non-option argument %s\n", *argv);
+ int main(int argc, char **argv)
+ {
+ int aflag = 0;
+ int bflag = 0;
+ char *cflag = NULL;
+ struct HXoption options_table[] = {
+ {.sh = 'a', .type = HXTYPE_NONE},
+ {.sh = 'b', .type = HXTYPE_NONE},
+ {.sh = 'c', .type = HXTYPE_STRING},
+ HXOPT_AUTOHELP,
+ HXOPT_TABLEEND,
+ };
+
+ struct HXopt6_result result;
+ if (HX_getopt6(options_table, argc, argv, &result,
+ HXOPT_USAGEONERR | HXOPT_ITER_OPTS) != HXOPT_ERR_SUCCESS)
+ return EXIT_FAILURE;
+ for (int i = 1; i < result.nopts; ++i) {
+ switch (result.desc[i]->sh) {
+ case 'a':
+ aflag = 1;
+ break;
+ case 'b':
+ bflag = 1;
+ break;
+ case 'c':
+ cflag = result.oarg[i];
+ break;
+ }
+ }
+ printf("aflag = %d, bflag = %d, cvalue = %s\n",
+ aflag, bflag, cflag ? cflag : "(null)");
+ HX_getopt6_clean(&result);
+ return EXIT_SUCCESS;
+ }
+
+Note that the pointers in ``oarg`` point to the original argv and so should not
+be freed. Upon success of HX_getopt6, HX_getopt6_clean must be called.
+
+Obtaining non-option arguments
+------------------------------
+
+.. code-block:: c
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <libHX/option.h>
+
+ int main(int argc, char **argv)
+ {
+ int aflag = 0;
+ int bflag = 0;
+ char *cflag = NULL;
+ struct HXoption options_table[] = {
+ {.sh = 'a', .type = HXTYPE_NONE, .ptr = &aflag},
+ {.sh = 'b', .type = HXTYPE_NONE, .ptr = &bflag},
+ {.sh = 'c', .type = HXTYPE_STRING, .ptr = &cflag},
+ HXOPT_AUTOHELP,
+ HXOPT_TABLEEND,
+ };
- HX_zvecfree(argv);
+ struct HXopt6_result result;
+ if (HX_getopt6(options_table, argc, argv, &result,
+ HXOPT_USAGEONERR | HXOPT_ITER_ARGS) != HXOPT_ERR_SUCCESS) {
+ free(cflag);
+ return EXIT_FAILURE;
+ }
+ printf("aflag = %d, bflag = %d, cvalue = %s\n",
+ aflag, bflag, cflag);
+ for (int i = 1; i < result.nargs; ++i)
+ printf("Non-option argument %s\n", result.uarg[i]);
+ free(cflag);
+ HX_getopt6_clean(&result);
return EXIT_SUCCESS;
}
+C++ extension
+-------------
+
+.. code-block:: c++
+
+ {
+ struct HXopt6_auto_result result;
+ auto ret = HX_getopt6(&table, argc, argv, &result,
+ HXOPT_USAGEONERR | HXOPT_ITER_ARGS);
+ if (ret != HXOPT_ERR_SUCCESS)
+ return ret;
+ }
+
+
+For C++ mode, a struct "HXopt6_auto_result" is offered with a constructor for
+zero initialization and a destructor invoking HX_getopt6_clean.
+
Verbosity levels
----------------
@@ -504,8 +648,8 @@ Mask operations
What this options table does is ``cpu_mask &= ~x`` and ``net_mask |= y``, the
classic operations of clearing and setting bits.
-Support for non-standard actions
---------------------------------
+Callbacks
+---------
Supporting additional types or custom storage formats is easy, by simply using
``HXTYPE_STRING``, ``NULL`` as the data pointer (usually by not specifying it
@@ -539,53 +683,3 @@ the callback function in ``cb``.
.uptr = &number, .help = "Do this or that",
HXOPT_TABLEEND,
};
-
-Chained argument processing
----------------------------
-
-On the first run, only ``--cake`` and ``--fruit`` is considered, which is then
-used to select the next set of accepted options.
-
-.. code-block:: c
-
- static int get_cakes(int *argc, char ***argv)
- {
- struct HXoption cake_table[] = {
- ...
- };
- if (HX_getopt5(cake_table, *argv, &argc, &argv,
- HXOPT_USAGEONERR) != HXOPT_ERR_SUCCESS)
- return EXIT_FAILURE;
- /* ... */
- HX_zvecfree(argv);
- return EXIT_SUCCESS;
- }
-
- static int fruit_main(int argc, char **argv)
- {
- struct HXoption fruit_table[] = {
- ...
- };
- if (HX_getopt5(fruit_table, *argv, &argc, &argv,
- HXOPT_PTHRU) != HXOPT_ERR_SUCCESS)
- return EXIT_FAILURE;
- /* ... */
- HX_zvecfree(argv);
- return EXIT_SUCCESS;
- }
-
- int main(int argc, char **argv)
- {
- int cake = 0, fruit = 0;
- struct HXoption option_table[] = {
- {.ln = "cake", .type = HXTYPE_NONE, .ptr = &cake},
- {.ln = "fruit", .type = HXTYPE_NONE, .ptr = &fruit},
- HXOPT_TABLEEND,
- };
- if (HX_getopt5(option_table, *argv, &argc, &argv,
- HXOPT_PTHRU) != HXOPT_ERR_SUCCESS)
- return EXIT_FAILURE;
- int ret = cake ? cake_main(argc, argv) : fruit_main(argc, argv);
- HX_zvecfree(argv);
- return EXIT_FAILURE;
- }
diff --git a/doc/string_ops.rst b/doc/string_ops.rst
index aea4896..ab7f19b 100644
--- a/doc/string_ops.rst
+++ b/doc/string_ops.rst
@@ -102,7 +102,6 @@ In-place transformations
char *HX_chomp(char *s);
size_t HX_strltrim(char *s);
- char *HX_stpltrim(const char *s);
char *HX_strlower(char *s);
char *HX_strrev(char *s);
size_t HX_strrtrim(char *s);
@@ -117,9 +116,6 @@ In-place transformations
on the left edge of the string. Returns the number of characters that
were stripped.
-``HX_stpltrim``
- Returns a pointer to the first non-whitespace character in ``s``.
-
``HX_strlower``
Transforms all characters in the string ``s`` into lowercase using
``tolower``(3). Returns the original argument.
@@ -184,18 +180,6 @@ Possible values for type:
``HXQUOTE_URIENC``
Escapes the string so that it becomes a valid part for an URI.
-``HXQUOTE_SQLSQUOTE``
- Escapes all single quotes in the string by double single-quotes, as
- required for using it in a single-quoted SQL string. No surrounding
- quotes will be generated to facilitate concatenating of HX_strquote
- results.
-
-``HXQUOTE_SQLBQUOTE``
- Escape all backticks in the string by double backticks, as required for
- using it in a backtick-quoted SQL string (used for table names and
- columns). No surrounding ticks will be generated to facilitate
- concatenation.
-
.. _RFC 4514: http://tools.ietf.org/html/rfc4514
.. _RFC 4515: http://tools.ietf.org/html/rfc4515
.. _RFC 4648: http://tools.ietf.org/html/rfc4648
@@ -246,7 +230,6 @@ Tokenizing
char **HX_split(const char *s, const char *delimiters, size_t *fields, int max);
char **HX_split_inplace(char *s, const char *delimiters, int *fields, int max);
int HX_split_fixed(char *s, const char *delimiters, int max, char **arr);
- char *HX_strsep(char **sp, const char *delimiters);
char *HX_strsep2(char **sp, const char *dstr);
``HX_split``
@@ -277,20 +260,15 @@ Tokenizing
.. [#fixfoot] An implementation may however decide to put ``NULL`` in the
unassigned fields, but this is implementation-dependent.
-``HX_strsep``
- Extract tokens from a string. This implementation of strsep has been
- added since the function is non-standard (according to the manpage,
- conforms to BSD4.4 only) and may not be available on every operating
- system. This function extracts tokens, separated by one of the
- characters in ``delimiters``. The string is modified in-place and thus
- must be mutable. The delimiters in the string are then overwritten with
- ``'\0'``, ``*sp`` is advanced to the character after the delimiter, and
- the original pointer is returned. After the final token, ``HX_strsep``
- will return ``NULL``.
-
``HX_strsep2``
- Like ``HX_strsep``, but ``dstr`` is not an array of delimiting
- characters, but an entire substring that acts as one delimiter.
+ strsep is a string tokenization function from BSD4.4; the POSIX
+ replacement is
+
+ strsep(&string, delim) <=>
+ strtok_r(nullptr, delim, &string).
+
+ Whereas strsep/strtok would split on any character in ``delim``,
+ our strsep2 splits only on the entire ``delim`` string.
Size-bounded string operations
@@ -303,7 +281,6 @@ Size-bounded string operations
char *HX_strlcat(char *dest, const char *src, size_t length);
char *HX_strlcpy(char *dest, const char *src, size_t length);
char *HX_strlncat(char *dest, const char *src, size_t dlen, size_t slen);
- size_t HX_strnlen(const char *src, size_t max);
``HX_strlcat`` and ``HX_strlcpy`` provide implementations of the
BSD-originating ``strlcat``(3) and ``strlcpy``(3) functions. ``strlcat`` and
@@ -312,10 +289,6 @@ they always take the length of the entire buffer specified by ``dest``, instead
of just the length that is to be written. The functions guarantee that the
buffer is ``'\0'``-terminated.
-``HX_strnlen`` will return the length of the input string or the upper bound
-given by ``max``, whichever is less. It will not attempt to access more than
-this many bytes in the input buffer.
-
Allocation-related
==================
@@ -462,7 +435,7 @@ Conversion from/to human-readable durations with units
unsigned int flags);
``HX_strtoull_sec`` and ``HX_strtoull_nsec`` convert a time duration with
-units, such as ``"15min30s"`` into an all-seconds and all-nanoseconds value,
+units, such as ``15min30s`` into an all-seconds and all-nanoseconds value,
respectively. The recognized unit strings are: ``years``, ``year``, ``y``,
``months``, ``month``, ``days``, ``day``, ``d``, ``hours``, ``hour``, ``h``,
``minutes``, ``minute``, ``min``, ``seconds``, ``second``, ``s``, the empty
@@ -471,8 +444,15 @@ string (to mean seconds), ``msec``, ``ms``, ``µsec``, ``µs``, ``nsec`` and
implementation-defined. When parsing stops at any point, ``*end`` is set to the
location, similar to how the ``strtoull`` C function would.
-One year is defined to be 365.25 days of 86400 seconds; one month is defined to
-be 1/12 such a year. This is consistent with the units employed by systemd.
+One day is defined as 86400 seconds. One year is defined to be 365.25 days of
+86400 seconds. One month is defined to be 1/12 such a year (30.4375 days). This
+is consistent with the units employed by systemd.
+
+In addition, HX_strtoull_sec recognizes the most common ISO 8601-style period
+syntax, e.g. ``PT15M30S``. Time lengths are applied as mentioned above, so
+``P1M`` is treated as 2629800 seconds, *not* as a "calendaric month" that would
+expand to 28—31 days relative to some start date. There is no function offered
+to return a ``struct tm``.
``HX_unit_seconds`` is the reverse and transforms the duration given by
``seconds`` into a string representation broken into days, hours, minutes, and
@@ -555,21 +535,3 @@ full-fledged ``HX_split`` that allocates space for each substring.
callme(line);
HX_zvecfree(field);
}
-
-Using HX_strsep
----------------
-
-``HX_strsep`` provides for thread- and reentrant-safe tokenizing a string where
-strtok from the C standard would otherwise fail.
-
-.. code-block:: c
-
- #include <stdio.h>
- #include <libHX/string.h>
-
- char line[] = "root:x:0:0:root:/root:/bin/bash";
- char *wp, *p;
-
- wp = line;
- while ((p = HX_strsep(&wp, ":")) != NULL)
- printf("%s\n", p)