+#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)
+
+#define ARGPAR_ASSERT(_cond) assert(_cond)
+
+#ifdef __MINGW_PRINTF_FORMAT
+# define ARGPAR_PRINTF_FORMAT __MINGW_PRINTF_FORMAT
+#else
+# define ARGPAR_PRINTF_FORMAT printf
+#endif
+
+/*
+ * An argpar iterator.
+ *
+ * Such a structure contains the state of an iterator between
+ * calls to argpar_iter_parse_next().
+ */
+struct argpar_iter {
+ /*
+ * Data provided by the user to argpar_iter_create(); immutable
+ * afterwards.
+ */
+ unsigned int argc;
+ const char * const *argv;
+ const struct argpar_opt_descr *descrs;
+
+ /*
+ * Index of the argument to process in the next
+ * argpar_iter_parse_next() call.
+ */
+ unsigned int i;
+
+ /* Counter of non-option arguments */
+ int non_opt_index;
+
+ /*
+ * Current character of the current short option group: if it's
+ * not `NULL`, the parser is in within a short option group,
+ * therefore it must resume there in the next
+ * argpar_iter_parse_next() call.
+ */
+ const char *short_opt_ch;
+};
+
+static __attribute__((format(ARGPAR_PRINTF_FORMAT, 1, 0)))
+char *argpar_vasprintf(const char * const fmt, va_list args)
+{
+ int len1, len2;
+ char *str;
+ va_list args2;
+
+ va_copy(args2, args);
+ len1 = vsnprintf(NULL, 0, fmt, args);
+ if (len1 < 0) {
+ str = NULL;
+ goto end;
+ }
+
+ str = malloc(len1 + 1);
+ if (!str) {
+ goto end;
+ }
+
+ len2 = vsnprintf(str, len1 + 1, fmt, args2);
+ ARGPAR_ASSERT(len1 == len2);
+
+end:
+ va_end(args2);
+ return str;
+}
+
+
+static __attribute__((format(ARGPAR_PRINTF_FORMAT, 1, 2)))
+char *argpar_asprintf(const char * const fmt, ...)
+{
+ va_list args;
+ char *str;
+
+ va_start(args, fmt);
+ str = argpar_vasprintf(fmt, args);
+ va_end(args);
+ return str;
+}
+
+static __attribute__((format(ARGPAR_PRINTF_FORMAT, 2, 3)))
+bool append_string_printf(char ** const str, const char *fmt, ...)
+{
+ char *new_str = NULL;
+ char *addendum;
+ bool success;
+ va_list args;
+
+ ARGPAR_ASSERT(str);
+ va_start(args, fmt);
+ addendum = argpar_vasprintf(fmt, args);
+ va_end(args);
+
+ if (!addendum) {
+ success = false;
+ goto end;
+ }
+
+ new_str = argpar_asprintf("%s%s", *str ? *str : "", addendum);
+ if (!new_str) {
+ success = false;
+ goto end;
+ }
+
+ free(*str);
+ *str = new_str;
+ success = true;
+
+end:
+ free(addendum);
+ return success;
+}
+
+ARGPAR_HIDDEN
+void argpar_item_destroy(const struct argpar_item * const item)