+#define ARGPAR_REALLOC(_ptr, _type, _nmemb) \
+ ((_type *) realloc(_ptr, (_nmemb) * sizeof(_type)))
+
+#define ARGPAR_CALLOC(_type, _nmemb) \
+ ((_type *) calloc((_nmemb), sizeof(_type)))
+
+#define ARGPAR_ZALLOC(_type) ARGPAR_CALLOC(_type, 1)
+
+#ifdef NDEBUG
+/*
+ * Force usage of the assertion condition to prevent unused variable warnings
+ * when `assert()` are disabled by the `NDEBUG` definition.
+ */
+# define ARGPAR_ASSERT(_cond) ((void) sizeof((void) (_cond), 0))
+#else
+# include <assert.h>
+# define ARGPAR_ASSERT(_cond) assert(_cond)
+#endif
+
+/*
+ * An argpar iterator.
+ *
+ * Such a structure contains the state of an iterator between calls to
+ * argpar_iter_next().
+ */
+struct argpar_iter {
+ /*
+ * Data provided by the user to argpar_iter_create(); immutable
+ * afterwards.
+ */
+ struct {
+ unsigned int argc;
+ const char * const *argv;
+ const argpar_opt_descr_t *descrs;
+ } user;
+
+ /*
+ * Index of the argument to process in the next
+ * argpar_iter_next() call.
+ */
+ unsigned int i;
+
+ /* Counter of non-option arguments */
+ int non_opt_index;
+
+ /*
+ * Current character within the current short option group: if
+ * it's not `NULL`, the parser is within a short option group,
+ * therefore it must resume there in the next argpar_iter_next()
+ * call.
+ */
+ const char *short_opt_group_ch;
+
+ /* Temporary character buffer which only grows */
+ struct {
+ size_t size;
+ char *data;
+ } tmp_buf;
+};
+
+/* Base parsing item */
+struct argpar_item {
+ argpar_item_type_t type;
+};
+
+/* Option parsing item */
+typedef struct argpar_item_opt {
+ argpar_item_t base;
+
+ /* Corresponding descriptor */
+ const argpar_opt_descr_t *descr;
+
+ /* Argument, or `NULL` if none; owned by this */
+ char *arg;
+} argpar_item_opt_t;
+
+/* Non-option parsing item */
+typedef struct argpar_item_non_opt {
+ argpar_item_t base;
+
+ /*
+ * Complete argument, pointing to one of the entries of the
+ * original arguments (`argv`).
+ */
+ const char *arg;
+
+ /*
+ * Index of this argument amongst all original arguments
+ * (`argv`).
+ */
+ unsigned int orig_index;
+
+ /* Index of this argument amongst other non-option arguments */
+ unsigned int non_opt_index;
+} argpar_item_non_opt_t;
+
+/* Parsing error */
+struct argpar_error {
+ /* Error type */
+ argpar_error_type_t type;
+
+ /* Original argument index */
+ unsigned int orig_index;
+
+ /* Name of unknown option; owned by this */
+ char *unknown_opt_name;
+
+ /* Option descriptor */
+ const argpar_opt_descr_t *opt_descr;
+
+ /* `true` if a short option caused the error */
+ bool is_short;
+};
+
+ARGPAR_HIDDEN
+argpar_item_type_t argpar_item_type(const argpar_item_t * const item)
+{
+ ARGPAR_ASSERT(item);
+ return item->type;
+}
+
+ARGPAR_HIDDEN
+const argpar_opt_descr_t *argpar_item_opt_descr(
+ const argpar_item_t * const item)
+{
+ ARGPAR_ASSERT(item);
+ ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_OPT);
+ return ((const argpar_item_opt_t *) item)->descr;
+}
+
+ARGPAR_HIDDEN
+const char *argpar_item_opt_arg(const argpar_item_t * const item)
+{
+ ARGPAR_ASSERT(item);
+ ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_OPT);
+ return ((const argpar_item_opt_t *) item)->arg;
+}
+
+ARGPAR_HIDDEN
+const char *argpar_item_non_opt_arg(const argpar_item_t * const item)
+{
+ ARGPAR_ASSERT(item);
+ ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
+ return ((const argpar_item_non_opt_t *) item)->arg;
+}
+
+ARGPAR_HIDDEN
+unsigned int argpar_item_non_opt_orig_index(
+ const argpar_item_t * const item)
+{
+ ARGPAR_ASSERT(item);
+ ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
+ return ((const argpar_item_non_opt_t *) item)->orig_index;
+}
+
+ARGPAR_HIDDEN
+unsigned int argpar_item_non_opt_non_opt_index(
+ const argpar_item_t * const item)
+{
+ ARGPAR_ASSERT(item);
+ ARGPAR_ASSERT(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
+ return ((const argpar_item_non_opt_t *) item)->non_opt_index;
+}
+
+ARGPAR_HIDDEN
+void argpar_item_destroy(const argpar_item_t * const item)