Merge branch 'feature/upgrade_argtable_3_2_1_files' into 'master'

console: upgrade argtable3 to v3.2.1 (multi-file approach)

See merge request espressif/esp-idf!17687
This commit is contained in:
Mahavir Jain 2022-04-12 12:42:29 +08:00
commit 8fac20d7dc
21 changed files with 5073 additions and 4575 deletions

View File

@ -1,12 +1,24 @@
set(argtable_srcs argtable3/arg_cmd.c
argtable3/arg_date.c
argtable3/arg_dbl.c
argtable3/arg_dstr.c
argtable3/arg_end.c
argtable3/arg_file.c
argtable3/arg_hashtable.c
argtable3/arg_int.c
argtable3/arg_lit.c
argtable3/arg_rem.c
argtable3/arg_rex.c
argtable3/arg_str.c
argtable3/arg_utils.c
argtable3/argtable3.c)
idf_component_register(SRCS "commands.c"
"esp_console_repl.c"
"split_argv.c"
"argtable3/argtable3.c"
"linenoise/linenoise.c"
${argtable_srcs}
INCLUDE_DIRS "."
REQUIRES vfs
PRIV_REQUIRES driver)
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
set_source_files_properties(argtable3/argtable3.c PROPERTIES COMPILE_FLAGS -Wno-clobbered)
endif()

View File

@ -23,3 +23,145 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
FreeBSD getopt library
======================
Copyright (c) 2000 The NetBSD Foundation, Inc.
All rights reserved.
This code is derived from software contributed to The NetBSD Foundation
by Dieter Baron and Thomas Klausner.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Tcl library
===========
This software is copyrighted by the Regents of the University of
California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
Corporation and other parties. The following terms apply to all files
associated with the software unless explicitly disclaimed in
individual files.
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
in the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.
C Hash Table library
====================
Copyright (c) 2002, Christopher Clark
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the original author; nor the names of any contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The Better String library
=========================
Copyright (c) 2014, Paul Hsieh
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of bstrlib nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,285 @@
/*
* SPDX-FileCopyrightText: 2013-2019 Tom G. Huang
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_cmd: Provides the sub-command mechanism
*
* This file is part of the argtable3 library.
*
* Copyright (C) 2013-2019 Tom G. Huang
* <tomghuang@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define MAX_MODULE_VERSION_SIZE 128
static arg_hashtable_t* s_hashtable = NULL;
static char* s_module_name = NULL;
static int s_mod_ver_major = 0;
static int s_mod_ver_minor = 0;
static int s_mod_ver_patch = 0;
static char* s_mod_ver_tag = NULL;
static char* s_mod_ver = NULL;
void arg_set_module_name(const char* name) {
size_t slen;
xfree(s_module_name);
slen = strlen(name);
s_module_name = (char*)xmalloc(slen + 1);
memset(s_module_name, 0, slen + 1);
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s(s_module_name, slen + 1, name, slen);
#else
memcpy(s_module_name, name, slen);
#endif
}
void arg_set_module_version(int major, int minor, int patch, const char* tag) {
size_t slen_tag, slen_ds;
arg_dstr_t ds;
s_mod_ver_major = major;
s_mod_ver_minor = minor;
s_mod_ver_patch = patch;
xfree(s_mod_ver_tag);
slen_tag = strlen(tag);
s_mod_ver_tag = (char*)xmalloc(slen_tag + 1);
memset(s_mod_ver_tag, 0, slen_tag + 1);
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s(s_mod_ver_tag, slen_tag + 1, tag, slen_tag);
#else
memcpy(s_mod_ver_tag, tag, slen_tag);
#endif
ds = arg_dstr_create();
arg_dstr_catf(ds, "%d.", s_mod_ver_major);
arg_dstr_catf(ds, "%d.", s_mod_ver_minor);
arg_dstr_catf(ds, "%d.", s_mod_ver_patch);
arg_dstr_cat(ds, s_mod_ver_tag);
xfree(s_mod_ver);
slen_ds = strlen(arg_dstr_cstr(ds));
s_mod_ver = (char*)xmalloc(slen_ds + 1);
memset(s_mod_ver, 0, slen_ds + 1);
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s(s_mod_ver, slen_ds + 1, arg_dstr_cstr(ds), slen_ds);
#else
memcpy(s_mod_ver, arg_dstr_cstr(ds), slen_ds);
#endif
arg_dstr_destroy(ds);
}
static unsigned int hash_key(const void* key) {
const char* str = (const char*)key;
int c;
unsigned int hash = 5381;
while ((c = *str++) != 0)
hash = ((hash << 5) + hash) + (unsigned int)c; /* hash * 33 + c */
return hash;
}
static int equal_keys(const void* key1, const void* key2) {
char* k1 = (char*)key1;
char* k2 = (char*)key2;
return (0 == strcmp(k1, k2));
}
void arg_cmd_init(void) {
s_hashtable = arg_hashtable_create(32, hash_key, equal_keys);
}
void arg_cmd_uninit(void) {
arg_hashtable_destroy(s_hashtable, 1);
}
void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description) {
arg_cmd_info_t* cmd_info;
size_t slen_name;
void* k;
assert(strlen(name) < ARG_CMD_NAME_LEN);
assert(strlen(description) < ARG_CMD_DESCRIPTION_LEN);
/* Check if the command already exists. */
/* If the command exists, replace the existing command. */
/* If the command doesn't exist, insert the command. */
cmd_info = (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, name);
if (cmd_info) {
arg_hashtable_remove(s_hashtable, name);
cmd_info = NULL;
}
cmd_info = (arg_cmd_info_t*)xmalloc(sizeof(arg_cmd_info_t));
memset(cmd_info, 0, sizeof(arg_cmd_info_t));
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s(cmd_info->name, ARG_CMD_NAME_LEN, name, strlen(name));
strncpy_s(cmd_info->description, ARG_CMD_DESCRIPTION_LEN, description, strlen(description));
#else
memcpy(cmd_info->name, name, strlen(name));
memcpy(cmd_info->description, description, strlen(description));
#endif
cmd_info->proc = proc;
slen_name = strlen(name);
k = xmalloc(slen_name + 1);
memset(k, 0, slen_name + 1);
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s((char*)k, slen_name + 1, name, slen_name);
#else
memcpy((char*)k, name, slen_name);
#endif
arg_hashtable_insert(s_hashtable, k, cmd_info);
}
void arg_cmd_unregister(const char* name) {
arg_hashtable_remove(s_hashtable, name);
}
int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res) {
arg_cmd_info_t* cmd_info = arg_cmd_info(name);
assert(cmd_info != NULL);
assert(cmd_info->proc != NULL);
return cmd_info->proc(argc, argv, res);
}
arg_cmd_info_t* arg_cmd_info(const char* name) {
return (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, name);
}
unsigned int arg_cmd_count(void) {
return arg_hashtable_count(s_hashtable);
}
arg_cmd_itr_t arg_cmd_itr_create(void) {
return (arg_cmd_itr_t)arg_hashtable_itr_create(s_hashtable);
}
int arg_cmd_itr_advance(arg_cmd_itr_t itr) {
return arg_hashtable_itr_advance((arg_hashtable_itr_t*)itr);
}
char* arg_cmd_itr_key(arg_cmd_itr_t itr) {
return (char*)arg_hashtable_itr_key((arg_hashtable_itr_t*)itr);
}
arg_cmd_info_t* arg_cmd_itr_value(arg_cmd_itr_t itr) {
return (arg_cmd_info_t*)arg_hashtable_itr_value((arg_hashtable_itr_t*)itr);
}
void arg_cmd_itr_destroy(arg_cmd_itr_t itr) {
arg_hashtable_itr_destroy((arg_hashtable_itr_t*)itr);
}
int arg_cmd_itr_search(arg_cmd_itr_t itr, void* k) {
return arg_hashtable_itr_search((arg_hashtable_itr_t*)itr, s_hashtable, k);
}
static const char* module_name(void) {
if (s_module_name == NULL || strlen(s_module_name) == 0)
return "<name>";
return s_module_name;
}
static const char* module_version(void) {
if (s_mod_ver == NULL || strlen(s_mod_ver) == 0)
return "0.0.0.0";
return s_mod_ver;
}
void arg_make_get_help_msg(arg_dstr_t res) {
arg_dstr_catf(res, "%s v%s\n", module_name(), module_version());
arg_dstr_catf(res, "Please type '%s help' to get more information.\n", module_name());
}
void arg_make_help_msg(arg_dstr_t ds, char* cmd_name, void** argtable) {
arg_cmd_info_t* cmd_info = (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, cmd_name);
if (cmd_info) {
arg_dstr_catf(ds, "%s: %s\n", cmd_name, cmd_info->description);
}
arg_dstr_cat(ds, "Usage:\n");
arg_dstr_catf(ds, " %s", module_name());
arg_print_syntaxv_ds(ds, argtable, "\n \nAvailable options:\n");
arg_print_glossary_ds(ds, argtable, " %-23s %s\n");
arg_dstr_cat(ds, "\n");
}
void arg_make_syntax_err_msg(arg_dstr_t ds, void** argtable, struct arg_end* end) {
arg_print_errors_ds(ds, end, module_name());
arg_dstr_cat(ds, "Usage: \n");
arg_dstr_catf(ds, " %s", module_name());
arg_print_syntaxv_ds(ds, argtable, "\n");
arg_dstr_cat(ds, "\n");
}
int arg_make_syntax_err_help_msg(arg_dstr_t ds, char* name, int help, int nerrors, void** argtable, struct arg_end* end, int* exitcode) {
/* help handling
* note: '-h|--help' takes precedence over error reporting
*/
if (help > 0) {
arg_make_help_msg(ds, name, argtable);
*exitcode = EXIT_SUCCESS;
return 1;
}
/* syntax error handling */
if (nerrors > 0) {
arg_make_syntax_err_msg(ds, argtable, end);
*exitcode = EXIT_FAILURE;
return 1;
}
return 0;
}

View File

@ -0,0 +1,575 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_date: Implements the date command-line option
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
* <sheitmann@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdlib.h>
#include <string.h>
char* arg_strptime(const char* buf, const char* fmt, struct tm* tm);
static void arg_date_resetfn(struct arg_date* parent) {
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
static int arg_date_scanfn(struct arg_date* parent, const char* argval) {
int errorcode = 0;
if (parent->count == parent->hdr.maxcount) {
errorcode = ARG_ERR_MAXCOUNT;
} else if (!argval) {
/* no argument value was given, leave parent->tmval[] unaltered but still count it */
parent->count++;
} else {
const char* pend;
struct tm tm = parent->tmval[parent->count];
/* parse the given argument value, store result in parent->tmval[] */
pend = arg_strptime(argval, parent->format, &tm);
if (pend && pend[0] == '\0')
parent->tmval[parent->count++] = tm;
else
errorcode = ARG_ERR_BADDATE;
}
ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static int arg_date_checkfn(struct arg_date* parent) {
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static void arg_date_errorfn(struct arg_date* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
/* make argval NULL safe */
argval = argval ? argval : "";
arg_dstr_catf(ds, "%s: ", progname);
switch (errorcode) {
case ARG_ERR_MINCOUNT:
arg_dstr_cat(ds, "missing option ");
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
case ARG_ERR_MAXCOUNT:
arg_dstr_cat(ds, "excess option ");
arg_print_option_ds(ds, shortopts, longopts, argval, "\n");
break;
case ARG_ERR_BADDATE: {
struct tm tm;
char buff[200];
arg_dstr_catf(ds, "illegal timestamp format \"%s\"\n", argval);
memset(&tm, 0, sizeof(tm));
arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm);
strftime(buff, sizeof(buff), parent->format, &tm);
arg_dstr_catf(ds, "correct format is \"%s\"\n", buff);
break;
}
}
}
struct arg_date* arg_date0(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary) {
return arg_daten(shortopts, longopts, format, datatype, 0, 1, glossary);
}
struct arg_date* arg_date1(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary) {
return arg_daten(shortopts, longopts, format, datatype, 1, 1, glossary);
}
struct arg_date*
arg_daten(const char* shortopts, const char* longopts, const char* format, const char* datatype, int mincount, int maxcount, const char* glossary) {
size_t nbytes;
struct arg_date* result;
/* foolproof things by ensuring maxcount is not less than mincount */
maxcount = (maxcount < mincount) ? mincount : maxcount;
/* default time format is the national date format for the locale */
if (!format)
format = "%x";
nbytes = sizeof(struct arg_date) /* storage for struct arg_date */
+ (size_t)maxcount * sizeof(struct tm); /* storage for tmval[maxcount] array */
/* allocate storage for the arg_date struct + tmval[] array. */
/* we use calloc because we want the tmval[] array zero filled. */
result = (struct arg_date*)xcalloc(1, nbytes);
/* init the arg_hdr struct */
result->hdr.flag = ARG_HASVALUE;
result->hdr.shortopts = shortopts;
result->hdr.longopts = longopts;
result->hdr.datatype = datatype ? datatype : format;
result->hdr.glossary = glossary;
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_date_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_date_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_date_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_date_errorfn;
/* store the tmval[maxcount] array immediately after the arg_date struct */
result->tmval = (struct tm*)(result + 1);
/* init the remaining arg_date member variables */
result->count = 0;
result->format = format;
ARG_TRACE(("arg_daten() returns %p\n", result));
return result;
}
/*-
* Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code was contributed to The NetBSD Foundation by Klaus Klein.
* Heavily optimised by David Laight
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <ctype.h>
#include <string.h>
#include <time.h>
/*
* We do not implement alternate representations. However, we always
* check whether a given modifier is allowed for a certain conversion.
*/
#define ALT_E 0x01
#define ALT_O 0x02
#define LEGAL_ALT(x) \
{ \
if (alt_format & ~(x)) \
return (0); \
}
#define TM_YEAR_BASE (1900)
static int conv_num(const char**, int*, int, int);
static const char* day[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
static const char* abday[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static const char* mon[12] = {"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
static const char* abmon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
static const char* am_pm[2] = {"AM", "PM"};
static int arg_strcasecmp(const char* s1, const char* s2) {
const unsigned char* us1 = (const unsigned char*)s1;
const unsigned char* us2 = (const unsigned char*)s2;
while (tolower(*us1) == tolower(*us2++))
if (*us1++ == '\0')
return 0;
return tolower(*us1) - tolower(*--us2);
}
static int arg_strncasecmp(const char* s1, const char* s2, size_t n) {
if (n != 0) {
const unsigned char* us1 = (const unsigned char*)s1;
const unsigned char* us2 = (const unsigned char*)s2;
do {
if (tolower(*us1) != tolower(*us2++))
return tolower(*us1) - tolower(*--us2);
if (*us1++ == '\0')
break;
} while (--n != 0);
}
return 0;
}
char* arg_strptime(const char* buf, const char* fmt, struct tm* tm) {
char c;
const char* bp;
size_t len = 0;
int alt_format, i, split_year = 0;
bp = buf;
while ((c = *fmt) != '\0') {
/* Clear `alternate' modifier prior to new conversion. */
alt_format = 0;
/* Eat up white-space. */
if (isspace(c)) {
while (isspace((int)(*bp)))
bp++;
fmt++;
continue;
}
if ((c = *fmt++) != '%')
goto literal;
again:
switch (c = *fmt++) {
case '%': /* "%%" is converted to "%". */
literal:
if (c != *bp++)
return (0);
break;
/*
* "Alternative" modifiers. Just set the appropriate flag
* and start over again.
*/
case 'E': /* "%E?" alternative conversion modifier. */
LEGAL_ALT(0);
alt_format |= ALT_E;
goto again;
case 'O': /* "%O?" alternative conversion modifier. */
LEGAL_ALT(0);
alt_format |= ALT_O;
goto again;
/*
* "Complex" conversion rules, implemented through recursion.
*/
case 'c': /* Date and time, using the locale's format. */
LEGAL_ALT(ALT_E);
bp = arg_strptime(bp, "%x %X", tm);
if (!bp)
return (0);
break;
case 'D': /* The date as "%m/%d/%y". */
LEGAL_ALT(0);
bp = arg_strptime(bp, "%m/%d/%y", tm);
if (!bp)
return (0);
break;
case 'R': /* The time as "%H:%M". */
LEGAL_ALT(0);
bp = arg_strptime(bp, "%H:%M", tm);
if (!bp)
return (0);
break;
case 'r': /* The time in 12-hour clock representation. */
LEGAL_ALT(0);
bp = arg_strptime(bp, "%I:%M:%S %p", tm);
if (!bp)
return (0);
break;
case 'T': /* The time as "%H:%M:%S". */
LEGAL_ALT(0);
bp = arg_strptime(bp, "%H:%M:%S", tm);
if (!bp)
return (0);
break;
case 'X': /* The time, using the locale's format. */
LEGAL_ALT(ALT_E);
bp = arg_strptime(bp, "%H:%M:%S", tm);
if (!bp)
return (0);
break;
case 'x': /* The date, using the locale's format. */
LEGAL_ALT(ALT_E);
bp = arg_strptime(bp, "%m/%d/%y", tm);
if (!bp)
return (0);
break;
/*
* "Elementary" conversion rules.
*/
case 'A': /* The day of week, using the locale's form. */
case 'a':
LEGAL_ALT(0);
for (i = 0; i < 7; i++) {
/* Full name. */
len = strlen(day[i]);
if (arg_strncasecmp(day[i], bp, len) == 0)
break;
/* Abbreviated name. */
len = strlen(abday[i]);
if (arg_strncasecmp(abday[i], bp, len) == 0)
break;
}
/* Nothing matched. */
if (i == 7)
return (0);
tm->tm_wday = i;
bp += len;
break;
case 'B': /* The month, using the locale's form. */
case 'b':
case 'h':
LEGAL_ALT(0);
for (i = 0; i < 12; i++) {
/* Full name. */
len = strlen(mon[i]);
if (arg_strncasecmp(mon[i], bp, len) == 0)
break;
/* Abbreviated name. */
len = strlen(abmon[i]);
if (arg_strncasecmp(abmon[i], bp, len) == 0)
break;
}
/* Nothing matched. */
if (i == 12)
return (0);
tm->tm_mon = i;
bp += len;
break;
case 'C': /* The century number. */
LEGAL_ALT(ALT_E);
if (!(conv_num(&bp, &i, 0, 99)))
return (0);
if (split_year) {
tm->tm_year = (tm->tm_year % 100) + (i * 100);
} else {
tm->tm_year = i * 100;
split_year = 1;
}
break;
case 'd': /* The day of month. */
case 'e':
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
return (0);
break;
case 'k': /* The hour (24-hour clock representation). */
LEGAL_ALT(0);
/* FALLTHROUGH */
case 'H':
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
return (0);
break;
case 'l': /* The hour (12-hour clock representation). */
LEGAL_ALT(0);
/* FALLTHROUGH */
case 'I':
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
return (0);
if (tm->tm_hour == 12)
tm->tm_hour = 0;
break;
case 'j': /* The day of year. */
LEGAL_ALT(0);
if (!(conv_num(&bp, &i, 1, 366)))
return (0);
tm->tm_yday = i - 1;
break;
case 'M': /* The minute. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
return (0);
break;
case 'm': /* The month. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &i, 1, 12)))
return (0);
tm->tm_mon = i - 1;
break;
case 'p': /* The locale's equivalent of AM/PM. */
LEGAL_ALT(0);
/* AM? */
if (arg_strcasecmp(am_pm[0], bp) == 0) {
if (tm->tm_hour > 11)
return (0);
bp += strlen(am_pm[0]);
break;
}
/* PM? */
else if (arg_strcasecmp(am_pm[1], bp) == 0) {
if (tm->tm_hour > 11)
return (0);
tm->tm_hour += 12;
bp += strlen(am_pm[1]);
break;
}
/* Nothing matched. */
return (0);
case 'S': /* The seconds. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
return (0);
break;
case 'U': /* The week of year, beginning on sunday. */
case 'W': /* The week of year, beginning on monday. */
LEGAL_ALT(ALT_O);
/*
* XXX This is bogus, as we can not assume any valid
* information present in the tm structure at this
* point to calculate a real value, so just check the
* range for now.
*/
if (!(conv_num(&bp, &i, 0, 53)))
return (0);
break;
case 'w': /* The day of week, beginning on sunday. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
return (0);
break;
case 'Y': /* The year. */
LEGAL_ALT(ALT_E);
if (!(conv_num(&bp, &i, 0, 9999)))
return (0);
tm->tm_year = i - TM_YEAR_BASE;
break;
case 'y': /* The year within 100 years of the epoch. */
LEGAL_ALT(ALT_E | ALT_O);
if (!(conv_num(&bp, &i, 0, 99)))
return (0);
if (split_year) {
tm->tm_year = ((tm->tm_year / 100) * 100) + i;
break;
}
split_year = 1;
if (i <= 68)
tm->tm_year = i + 2000 - TM_YEAR_BASE;
else
tm->tm_year = i + 1900 - TM_YEAR_BASE;
break;
/*
* Miscellaneous conversions.
*/
case 'n': /* Any kind of white-space. */
case 't':
LEGAL_ALT(0);
while (isspace((int)(*bp)))
bp++;
break;
default: /* Unknown/unsupported conversion. */
return (0);
}
}
/* LINTED functional specification */
return ((char*)bp);
}
static int conv_num(const char** buf, int* dest, int llim, int ulim) {
int result = 0;
/* The limit also determines the number of valid digits. */
int rulim = ulim;
if (**buf < '0' || **buf > '9')
return (0);
do {
result *= 10;
result += *(*buf)++ - '0';
rulim /= 10;
} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
if (result < llim || result > ulim)
return (0);
*dest = result;
return (1);
}

View File

@ -0,0 +1,164 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_dbl: Implements the double command-line option
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
* <sheitmann@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdlib.h>
static void arg_dbl_resetfn(struct arg_dbl* parent) {
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
static int arg_dbl_scanfn(struct arg_dbl* parent, const char* argval) {
int errorcode = 0;
if (parent->count == parent->hdr.maxcount) {
/* maximum number of arguments exceeded */
errorcode = ARG_ERR_MAXCOUNT;
} else if (!argval) {
/* a valid argument with no argument value was given. */
/* This happens when an optional argument value was invoked. */
/* leave parent argument value unaltered but still count the argument. */
parent->count++;
} else {
double val;
char* end;
/* extract double from argval into val */
val = strtod(argval, &end);
/* if success then store result in parent->dval[] array otherwise return error*/
if (*end == 0)
parent->dval[parent->count++] = val;
else
errorcode = ARG_ERR_BADDOUBLE;
}
ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static int arg_dbl_checkfn(struct arg_dbl* parent) {
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static void arg_dbl_errorfn(struct arg_dbl* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
/* make argval NULL safe */
argval = argval ? argval : "";
arg_dstr_catf(ds, "%s: ", progname);
switch (errorcode) {
case ARG_ERR_MINCOUNT:
arg_dstr_cat(ds, "missing option ");
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
case ARG_ERR_MAXCOUNT:
arg_dstr_cat(ds, "excess option ");
arg_print_option_ds(ds, shortopts, longopts, argval, "\n");
break;
case ARG_ERR_BADDOUBLE:
arg_dstr_catf(ds, "invalid argument \"%s\" to option ", argval);
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
}
}
struct arg_dbl* arg_dbl0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_dbln(shortopts, longopts, datatype, 0, 1, glossary);
}
struct arg_dbl* arg_dbl1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_dbln(shortopts, longopts, datatype, 1, 1, glossary);
}
struct arg_dbl* arg_dbln(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) {
size_t nbytes;
struct arg_dbl* result;
size_t addr;
size_t rem;
/* foolproof things by ensuring maxcount is not less than mincount */
maxcount = (maxcount < mincount) ? mincount : maxcount;
nbytes = sizeof(struct arg_dbl) /* storage for struct arg_dbl */
+ (size_t)(maxcount + 1) * sizeof(double); /* storage for dval[maxcount] array plus one extra for padding to memory boundary */
result = (struct arg_dbl*)xmalloc(nbytes);
/* init the arg_hdr struct */
result->hdr.flag = ARG_HASVALUE;
result->hdr.shortopts = shortopts;
result->hdr.longopts = longopts;
result->hdr.datatype = datatype ? datatype : "<double>";
result->hdr.glossary = glossary;
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_dbl_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_dbl_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_dbl_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_dbl_errorfn;
/* Store the dval[maxcount] array on the first double boundary that
* immediately follows the arg_dbl struct. We do the memory alignment
* purely for SPARC and Motorola systems. They require floats and
* doubles to be aligned on natural boundaries.
*/
addr = (size_t)(result + 1);
rem = addr % sizeof(double);
result->dval = (double*)(addr + sizeof(double) - rem);
ARG_TRACE(("addr=%p, dval=%p, sizeof(double)=%d rem=%d\n", addr, result->dval, (int)sizeof(double), (int)rem));
result->count = 0;
ARG_TRACE(("arg_dbln() returns %p\n", result));
return result;
}

View File

@ -0,0 +1,344 @@
/*
* SPDX-FileCopyrightText: 2013-2019 Tom G. Huang
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_dstr: Implements the dynamic string utilities
*
* This file is part of the argtable3 library.
*
* Copyright (C) 2013-2019 Tom G. Huang
* <tomghuang@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
#define START_VSNBUFF 16
/*
* This dynamic string module is adapted from TclResult.c in the Tcl library.
* Here is the copyright notice from the library:
*
* This software is copyrighted by the Regents of the University of
* California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
* Corporation and other parties. The following terms apply to all files
* associated with the software unless explicitly disclaimed in
* individual files.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*
* IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
* FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
* DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
* IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
* NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
* MODIFICATIONS.
*
* GOVERNMENT USE: If you are acquiring this software on behalf of the
* U.S. government, the Government shall have only "Restricted Rights"
* in the software and related documentation as defined in the Federal
* Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
* are acquiring the software on behalf of the Department of Defense, the
* software shall be classified as "Commercial Computer Software" and the
* Government shall have only "Restricted Rights" as defined in Clause
* 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the
* authors grant the U.S. Government and others acting in its behalf
* permission to use and distribute the software in accordance with the
* terms specified in this license.
*/
typedef struct _internal_arg_dstr {
char* data;
arg_dstr_freefn* free_proc;
char sbuf[ARG_DSTR_SIZE + 1];
char* append_data;
int append_data_size;
int append_used;
} _internal_arg_dstr_t;
static void setup_append_buf(arg_dstr_t res, int newSpace);
arg_dstr_t arg_dstr_create(void) {
_internal_arg_dstr_t* h = (_internal_arg_dstr_t*)xmalloc(sizeof(_internal_arg_dstr_t));
memset(h, 0, sizeof(_internal_arg_dstr_t));
h->sbuf[0] = 0;
h->data = h->sbuf;
h->free_proc = ARG_DSTR_STATIC;
return h;
}
void arg_dstr_destroy(arg_dstr_t ds) {
if (ds == NULL)
return;
arg_dstr_reset(ds);
xfree(ds);
return;
}
void arg_dstr_set(arg_dstr_t ds, char* str, arg_dstr_freefn* free_proc) {
int length;
register arg_dstr_freefn* old_free_proc = ds->free_proc;
char* old_result = ds->data;
if (str == NULL) {
ds->sbuf[0] = 0;
ds->data = ds->sbuf;
ds->free_proc = ARG_DSTR_STATIC;
} else if (free_proc == ARG_DSTR_VOLATILE) {
length = (int)strlen(str);
if (length > ARG_DSTR_SIZE) {
ds->data = (char*)xmalloc((unsigned)length + 1);
ds->free_proc = ARG_DSTR_DYNAMIC;
} else {
ds->data = ds->sbuf;
ds->free_proc = ARG_DSTR_STATIC;
}
strcpy(ds->data, str);
} else {
ds->data = str;
ds->free_proc = free_proc;
}
/*
* If the old result was dynamically-allocated, free it up. Do it here,
* rather than at the beginning, in case the new result value was part of
* the old result value.
*/
if ((old_free_proc != 0) && (old_result != ds->data)) {
if (old_free_proc == ARG_DSTR_DYNAMIC) {
xfree(old_result);
} else {
(*old_free_proc)(old_result);
}
}
if ((ds->append_data != NULL) && (ds->append_data_size > 0)) {
xfree(ds->append_data);
ds->append_data = NULL;
ds->append_data_size = 0;
}
}
char* arg_dstr_cstr(arg_dstr_t ds) /* Interpreter whose result to return. */
{
return ds->data;
}
void arg_dstr_cat(arg_dstr_t ds, const char* str) {
setup_append_buf(ds, (int)strlen(str) + 1);
memcpy(ds->data + strlen(ds->data), str, strlen(str));
}
void arg_dstr_catc(arg_dstr_t ds, char c) {
setup_append_buf(ds, 2);
memcpy(ds->data + strlen(ds->data), &c, 1);
}
/*
* The logic of the `arg_dstr_catf` function is adapted from the `bformat`
* function in The Better String Library by Paul Hsieh. Here is the copyright
* notice from the library:
*
* Copyright (c) 2014, Paul Hsieh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of bstrlib nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
void arg_dstr_catf(arg_dstr_t ds, const char* fmt, ...) {
va_list arglist;
char* buff;
int n, r;
size_t slen;
if (fmt == NULL)
return;
/* Since the length is not determinable beforehand, a search is
performed using the truncating "vsnprintf" call (to avoid buffer
overflows) on increasing potential sizes for the output result. */
if ((n = (int)(2 * strlen(fmt))) < START_VSNBUFF)
n = START_VSNBUFF;
buff = (char*)xmalloc((size_t)(n + 2));
memset(buff, 0, (size_t)(n + 2));
for (;;) {
va_start(arglist, fmt);
r = vsnprintf(buff, (size_t)(n + 1), fmt, arglist);
va_end(arglist);
slen = strlen(buff);
if (slen < (size_t)n)
break;
if (r > n)
n = r;
else
n += n;
xfree(buff);
buff = (char*)xmalloc((size_t)(n + 2));
memset(buff, 0, (size_t)(n + 2));
}
arg_dstr_cat(ds, buff);
xfree(buff);
}
static void setup_append_buf(arg_dstr_t ds, int new_space) {
int total_space;
/*
* Make the append buffer larger, if that's necessary, then copy the
* data into the append buffer and make the append buffer the official
* data.
*/
if (ds->data != ds->append_data) {
/*
* If the buffer is too big, then free it up so we go back to a
* smaller buffer. This avoids tying up memory forever after a large
* operation.
*/
if (ds->append_data_size > 500) {
xfree(ds->append_data);
ds->append_data = NULL;
ds->append_data_size = 0;
}
ds->append_used = (int)strlen(ds->data);
} else if (ds->data[ds->append_used] != 0) {
/*
* Most likely someone has modified a result created by
* arg_dstr_cat et al. so that it has a different size. Just
* recompute the size.
*/
ds->append_used = (int)strlen(ds->data);
}
total_space = new_space + ds->append_used;
if (total_space >= ds->append_data_size) {
char* newbuf;
if (total_space < 100) {
total_space = 200;
} else {
total_space *= 2;
}
newbuf = (char*)xmalloc((unsigned)total_space);
memset(newbuf, 0, (size_t)total_space);
strcpy(newbuf, ds->data);
if (ds->append_data != NULL) {
xfree(ds->append_data);
}
ds->append_data = newbuf;
ds->append_data_size = total_space;
} else if (ds->data != ds->append_data) {
strcpy(ds->append_data, ds->data);
}
arg_dstr_free(ds);
ds->data = ds->append_data;
}
void arg_dstr_free(arg_dstr_t ds) {
if (ds->free_proc != NULL) {
if (ds->free_proc == ARG_DSTR_DYNAMIC) {
xfree(ds->data);
} else {
(*ds->free_proc)(ds->data);
}
ds->free_proc = NULL;
}
}
void arg_dstr_reset(arg_dstr_t ds) {
arg_dstr_free(ds);
if ((ds->append_data != NULL) && (ds->append_data_size > 0)) {
xfree(ds->append_data);
ds->append_data = NULL;
ds->append_data_size = 0;
}
ds->data = ds->sbuf;
ds->sbuf[0] = 0;
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif

View File

@ -0,0 +1,135 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_end: Implements the error handling utilities
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
* <sheitmann@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdlib.h>
static void arg_end_resetfn(struct arg_end* parent) {
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
static void arg_end_errorfn(void* parent, arg_dstr_t ds, int error, const char* argval, const char* progname) {
/* suppress unreferenced formal parameter warning */
(void)parent;
progname = progname ? progname : "";
argval = argval ? argval : "";
arg_dstr_catf(ds, "%s: ", progname);
switch (error) {
case ARG_ELIMIT:
arg_dstr_cat(ds, "too many errors to display");
break;
case ARG_EMALLOC:
arg_dstr_cat(ds, "insufficient memory");
break;
case ARG_ENOMATCH:
arg_dstr_catf(ds, "unexpected argument \"%s\"", argval);
break;
case ARG_EMISSARG:
arg_dstr_catf(ds, "option \"%s\" requires an argument", argval);
break;
case ARG_ELONGOPT:
arg_dstr_catf(ds, "invalid option \"%s\"", argval);
break;
default:
arg_dstr_catf(ds, "invalid option \"-%c\"", error);
break;
}
arg_dstr_cat(ds, "\n");
}
struct arg_end* arg_end(int maxcount) {
size_t nbytes;
struct arg_end* result;
nbytes = sizeof(struct arg_end) + (size_t)maxcount * sizeof(int) /* storage for int error[maxcount] array*/
+ (size_t)maxcount * sizeof(void*) /* storage for void* parent[maxcount] array */
+ (size_t)maxcount * sizeof(char*); /* storage for char* argval[maxcount] array */
result = (struct arg_end*)xmalloc(nbytes);
/* init the arg_hdr struct */
result->hdr.flag = ARG_TERMINATOR;
result->hdr.shortopts = NULL;
result->hdr.longopts = NULL;
result->hdr.datatype = NULL;
result->hdr.glossary = NULL;
result->hdr.mincount = 1;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_end_resetfn;
result->hdr.scanfn = NULL;
result->hdr.checkfn = NULL;
result->hdr.errorfn = (arg_errorfn*)arg_end_errorfn;
/* store error[maxcount] array immediately after struct arg_end */
result->error = (int*)(result + 1);
/* store parent[maxcount] array immediately after error[] array */
result->parent = (void**)(result->error + maxcount);
/* store argval[maxcount] array immediately after parent[] array */
result->argval = (const char**)(result->parent + maxcount);
ARG_TRACE(("arg_end(%d) returns %p\n", maxcount, result));
return result;
}
void arg_print_errors_ds(arg_dstr_t ds, struct arg_end* end, const char* progname) {
int i;
ARG_TRACE(("arg_errors()\n"));
for (i = 0; i < end->count; i++) {
struct arg_hdr* errorparent = (struct arg_hdr*)(end->parent[i]);
if (errorparent->errorfn)
errorparent->errorfn(end->parent[i], ds, end->error[i], end->argval[i], progname);
}
}
void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname) {
arg_dstr_t ds = arg_dstr_create();
arg_print_errors_ds(ds, end, progname);
fputs(arg_dstr_cstr(ds), fp);
arg_dstr_destroy(ds);
}

View File

@ -0,0 +1,213 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_file: Implements the file command-line option
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
* <sheitmann@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#define FILESEPARATOR1 '\\'
#define FILESEPARATOR2 '/'
#else
#define FILESEPARATOR1 '/'
#define FILESEPARATOR2 '/'
#endif
static void arg_file_resetfn(struct arg_file* parent) {
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
/* Returns ptr to the base filename within *filename */
static const char* arg_basename(const char* filename) {
const char *result = NULL, *result1, *result2;
/* Find the last occurrence of eother file separator character. */
/* Two alternative file separator chars are supported as legal */
/* file separators but not both together in the same filename. */
result1 = (filename ? strrchr(filename, FILESEPARATOR1) : NULL);
result2 = (filename ? strrchr(filename, FILESEPARATOR2) : NULL);
if (result2)
result = result2 + 1; /* using FILESEPARATOR2 (the alternative file separator) */
if (result1)
result = result1 + 1; /* using FILESEPARATOR1 (the preferred file separator) */
if (!result)
result = filename; /* neither file separator was found so basename is the whole filename */
/* special cases of "." and ".." are not considered basenames */
if (result && (strcmp(".", result) == 0 || strcmp("..", result) == 0))
result = filename + strlen(filename);
return result;
}
/* Returns ptr to the file extension within *basename */
static const char* arg_extension(const char* basename) {
/* find the last occurrence of '.' in basename */
const char* result = (basename ? strrchr(basename, '.') : NULL);
/* if no '.' was found then return pointer to end of basename */
if (basename && !result)
result = basename + strlen(basename);
/* special case: basenames with a single leading dot (eg ".foo") are not considered as true extensions */
if (basename && result == basename)
result = basename + strlen(basename);
/* special case: empty extensions (eg "foo.","foo..") are not considered as true extensions */
if (basename && result && strlen(result) == 1)
result = basename + strlen(basename);
return result;
}
static int arg_file_scanfn(struct arg_file* parent, const char* argval) {
int errorcode = 0;
if (parent->count == parent->hdr.maxcount) {
/* maximum number of arguments exceeded */
errorcode = ARG_ERR_MAXCOUNT;
} else if (!argval) {
/* a valid argument with no argument value was given. */
/* This happens when an optional argument value was invoked. */
/* leave parent arguiment value unaltered but still count the argument. */
parent->count++;
} else {
parent->filename[parent->count] = argval;
parent->basename[parent->count] = arg_basename(argval);
parent->extension[parent->count] =
arg_extension(parent->basename[parent->count]); /* only seek extensions within the basename (not the file path)*/
parent->count++;
}
ARG_TRACE(("%s4:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static int arg_file_checkfn(struct arg_file* parent) {
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static void arg_file_errorfn(struct arg_file* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
/* make argval NULL safe */
argval = argval ? argval : "";
arg_dstr_catf(ds, "%s: ", progname);
switch (errorcode) {
case ARG_ERR_MINCOUNT:
arg_dstr_cat(ds, "missing option ");
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
case ARG_ERR_MAXCOUNT:
arg_dstr_cat(ds, "excess option ");
arg_print_option_ds(ds, shortopts, longopts, argval, "\n");
break;
default:
arg_dstr_catf(ds, "unknown error at \"%s\"\n", argval);
}
}
struct arg_file* arg_file0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_filen(shortopts, longopts, datatype, 0, 1, glossary);
}
struct arg_file* arg_file1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_filen(shortopts, longopts, datatype, 1, 1, glossary);
}
struct arg_file* arg_filen(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) {
size_t nbytes;
struct arg_file* result;
int i;
/* foolproof things by ensuring maxcount is not less than mincount */
maxcount = (maxcount < mincount) ? mincount : maxcount;
nbytes = sizeof(struct arg_file) /* storage for struct arg_file */
+ sizeof(char*) * (size_t)maxcount /* storage for filename[maxcount] array */
+ sizeof(char*) * (size_t)maxcount /* storage for basename[maxcount] array */
+ sizeof(char*) * (size_t)maxcount; /* storage for extension[maxcount] array */
result = (struct arg_file*)xmalloc(nbytes);
/* init the arg_hdr struct */
result->hdr.flag = ARG_HASVALUE;
result->hdr.shortopts = shortopts;
result->hdr.longopts = longopts;
result->hdr.glossary = glossary;
result->hdr.datatype = datatype ? datatype : "<file>";
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_file_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_file_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_file_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_file_errorfn;
/* store the filename,basename,extension arrays immediately after the arg_file struct */
result->filename = (const char**)(result + 1);
result->basename = result->filename + maxcount;
result->extension = result->basename + maxcount;
result->count = 0;
/* foolproof the string pointers by initialising them with empty strings */
for (i = 0; i < maxcount; i++) {
result->filename[i] = "";
result->basename[i] = "";
result->extension[i] = "";
}
ARG_TRACE(("arg_filen() returns %p\n", result));
return result;
}

View File

@ -0,0 +1,428 @@
/*
* SPDX-FileCopyrightText: 2013-2019 Tom G. Huang
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_hashtable: Implements the hash table utilities
*
* This file is part of the argtable3 library.
*
* Copyright (C) 2013-2019 Tom G. Huang
* <tomghuang@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* This hash table module is adapted from the C hash table implementation by
* Christopher Clark. Here is the copyright notice from the library:
*
* Copyright (c) 2002, Christopher Clark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Credit for primes table: Aaron Krowne
* http://br.endernet.org/~akrowne/
* http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
*/
static const unsigned int primes[] = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289,
24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741};
const unsigned int prime_table_length = sizeof(primes) / sizeof(primes[0]);
const float max_load_factor = (float)0.65;
static unsigned int enhanced_hash(arg_hashtable_t* h, const void* k) {
/*
* Aim to protect against poor hash functions by adding logic here.
* The logic is taken from Java 1.4 hash table source.
*/
unsigned int i = h->hashfn(k);
i += ~(i << 9);
i ^= ((i >> 14) | (i << 18)); /* >>> */
i += (i << 4);
i ^= ((i >> 10) | (i << 22)); /* >>> */
return i;
}
static unsigned int index_for(unsigned int tablelength, unsigned int hashvalue) {
return (hashvalue % tablelength);
}
arg_hashtable_t* arg_hashtable_create(unsigned int minsize, unsigned int (*hashfn)(const void*), int (*eqfn)(const void*, const void*)) {
arg_hashtable_t* h;
unsigned int pindex;
unsigned int size = primes[0];
/* Check requested hash table isn't too large */
if (minsize > (1u << 30))
return NULL;
/*
* Enforce size as prime. The reason is to avoid clustering of values
* into a small number of buckets (yes, distribution). A more even
* distributed hash table will perform more consistently.
*/
for (pindex = 0; pindex < prime_table_length; pindex++) {
if (primes[pindex] > minsize) {
size = primes[pindex];
break;
}
}
h = (arg_hashtable_t*)xmalloc(sizeof(arg_hashtable_t));
h->table = (struct arg_hashtable_entry**)xmalloc(sizeof(struct arg_hashtable_entry*) * size);
memset(h->table, 0, size * sizeof(struct arg_hashtable_entry*));
h->tablelength = size;
h->primeindex = pindex;
h->entrycount = 0;
h->hashfn = hashfn;
h->eqfn = eqfn;
h->loadlimit = (unsigned int)ceil(size * (double)max_load_factor);
return h;
}
static int arg_hashtable_expand(arg_hashtable_t* h) {
/* Double the size of the table to accommodate more entries */
struct arg_hashtable_entry** newtable;
struct arg_hashtable_entry* e;
unsigned int newsize;
unsigned int i;
unsigned int index;
/* Check we're not hitting max capacity */
if (h->primeindex == (prime_table_length - 1))
return 0;
newsize = primes[++(h->primeindex)];
newtable = (struct arg_hashtable_entry**)xmalloc(sizeof(struct arg_hashtable_entry*) * newsize);
memset(newtable, 0, newsize * sizeof(struct arg_hashtable_entry*));
/*
* This algorithm is not 'stable': it reverses the list
* when it transfers entries between the tables
*/
for (i = 0; i < h->tablelength; i++) {
while (NULL != (e = h->table[i])) {
h->table[i] = e->next;
index = index_for(newsize, e->h);
e->next = newtable[index];
newtable[index] = e;
}
}
xfree(h->table);
h->table = newtable;
h->tablelength = newsize;
h->loadlimit = (unsigned int)ceil(newsize * (double)max_load_factor);
return -1;
}
unsigned int arg_hashtable_count(arg_hashtable_t* h) {
return h->entrycount;
}
void arg_hashtable_insert(arg_hashtable_t* h, void* k, void* v) {
/* This method allows duplicate keys - but they shouldn't be used */
unsigned int index;
struct arg_hashtable_entry* e;
if ((h->entrycount + 1) > h->loadlimit) {
/*
* Ignore the return value. If expand fails, we should
* still try cramming just this value into the existing table
* -- we may not have memory for a larger table, but one more
* element may be ok. Next time we insert, we'll try expanding again.
*/
arg_hashtable_expand(h);
}
e = (struct arg_hashtable_entry*)xmalloc(sizeof(struct arg_hashtable_entry));
e->h = enhanced_hash(h, k);
index = index_for(h->tablelength, e->h);
e->k = k;
e->v = v;
e->next = h->table[index];
h->table[index] = e;
h->entrycount++;
}
void* arg_hashtable_search(arg_hashtable_t* h, const void* k) {
struct arg_hashtable_entry* e;
unsigned int hashvalue;
unsigned int index;
hashvalue = enhanced_hash(h, k);
index = index_for(h->tablelength, hashvalue);
e = h->table[index];
while (e != NULL) {
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
return e->v;
e = e->next;
}
return NULL;
}
void arg_hashtable_remove(arg_hashtable_t* h, const void* k) {
/*
* TODO: consider compacting the table when the load factor drops enough,
* or provide a 'compact' method.
*/
struct arg_hashtable_entry* e;
struct arg_hashtable_entry** pE;
unsigned int hashvalue;
unsigned int index;
hashvalue = enhanced_hash(h, k);
index = index_for(h->tablelength, hashvalue);
pE = &(h->table[index]);
e = *pE;
while (NULL != e) {
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
*pE = e->next;
h->entrycount--;
xfree(e->k);
xfree(e->v);
xfree(e);
return;
}
pE = &(e->next);
e = e->next;
}
}
void arg_hashtable_destroy(arg_hashtable_t* h, int free_values) {
unsigned int i;
struct arg_hashtable_entry *e, *f;
struct arg_hashtable_entry** table = h->table;
if (free_values) {
for (i = 0; i < h->tablelength; i++) {
e = table[i];
while (NULL != e) {
f = e;
e = e->next;
xfree(f->k);
xfree(f->v);
xfree(f);
}
}
} else {
for (i = 0; i < h->tablelength; i++) {
e = table[i];
while (NULL != e) {
f = e;
e = e->next;
xfree(f->k);
xfree(f);
}
}
}
xfree(h->table);
xfree(h);
}
arg_hashtable_itr_t* arg_hashtable_itr_create(arg_hashtable_t* h) {
unsigned int i;
unsigned int tablelength;
arg_hashtable_itr_t* itr = (arg_hashtable_itr_t*)xmalloc(sizeof(arg_hashtable_itr_t));
itr->h = h;
itr->e = NULL;
itr->parent = NULL;
tablelength = h->tablelength;
itr->index = tablelength;
if (0 == h->entrycount)
return itr;
for (i = 0; i < tablelength; i++) {
if (h->table[i] != NULL) {
itr->e = h->table[i];
itr->index = i;
break;
}
}
return itr;
}
void arg_hashtable_itr_destroy(arg_hashtable_itr_t* itr) {
xfree(itr);
}
void* arg_hashtable_itr_key(arg_hashtable_itr_t* i) {
return i->e->k;
}
void* arg_hashtable_itr_value(arg_hashtable_itr_t* i) {
return i->e->v;
}
int arg_hashtable_itr_advance(arg_hashtable_itr_t* itr) {
unsigned int j;
unsigned int tablelength;
struct arg_hashtable_entry** table;
struct arg_hashtable_entry* next;
if (itr->e == NULL)
return 0; /* stupidity check */
next = itr->e->next;
if (NULL != next) {
itr->parent = itr->e;
itr->e = next;
return -1;
}
tablelength = itr->h->tablelength;
itr->parent = NULL;
if (tablelength <= (j = ++(itr->index))) {
itr->e = NULL;
return 0;
}
table = itr->h->table;
while (NULL == (next = table[j])) {
if (++j >= tablelength) {
itr->index = tablelength;
itr->e = NULL;
return 0;
}
}
itr->index = j;
itr->e = next;
return -1;
}
int arg_hashtable_itr_remove(arg_hashtable_itr_t* itr) {
struct arg_hashtable_entry* remember_e;
struct arg_hashtable_entry* remember_parent;
int ret;
/* Do the removal */
if ((itr->parent) == NULL) {
/* element is head of a chain */
itr->h->table[itr->index] = itr->e->next;
} else {
/* element is mid-chain */
itr->parent->next = itr->e->next;
}
/* itr->e is now outside the hashtable */
remember_e = itr->e;
itr->h->entrycount--;
xfree(remember_e->k);
xfree(remember_e->v);
/* Advance the iterator, correcting the parent */
remember_parent = itr->parent;
ret = arg_hashtable_itr_advance(itr);
if (itr->parent == remember_e) {
itr->parent = remember_parent;
}
xfree(remember_e);
return ret;
}
int arg_hashtable_itr_search(arg_hashtable_itr_t* itr, arg_hashtable_t* h, void* k) {
struct arg_hashtable_entry* e;
struct arg_hashtable_entry* parent;
unsigned int hashvalue;
unsigned int index;
hashvalue = enhanced_hash(h, k);
index = index_for(h->tablelength, hashvalue);
e = h->table[index];
parent = NULL;
while (e != NULL) {
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
itr->index = index;
itr->e = e;
itr->parent = parent;
itr->h = h;
return -1;
}
parent = e;
e = e->next;
}
return 0;
}
int arg_hashtable_change(arg_hashtable_t* h, void* k, void* v) {
struct arg_hashtable_entry* e;
unsigned int hashvalue;
unsigned int index;
hashvalue = enhanced_hash(h, k);
index = index_for(h->tablelength, hashvalue);
e = h->table[index];
while (e != NULL) {
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
xfree(e->v);
e->v = v;
return -1;
}
e = e->next;
}
return 0;
}

View File

@ -0,0 +1,294 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_int: Implements the int command-line option
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
* <sheitmann@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
static void arg_int_resetfn(struct arg_int* parent) {
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
/* strtol0x() is like strtol() except that the numeric string is */
/* expected to be prefixed by "0X" where X is a user supplied char. */
/* The string may optionally be prefixed by white space and + or - */
/* as in +0X123 or -0X123. */
/* Once the prefix has been scanned, the remainder of the numeric */
/* string is converted using strtol() with the given base. */
/* eg: to parse hex str="-0X12324", specify X='X' and base=16. */
/* eg: to parse oct str="+0o12324", specify X='O' and base=8. */
/* eg: to parse bin str="-0B01010", specify X='B' and base=2. */
/* Failure of conversion is indicated by result where *endptr==str. */
static long int strtol0X(const char* str, const char** endptr, char X, int base) {
long int val; /* stores result */
int s = 1; /* sign is +1 or -1 */
const char* ptr = str; /* ptr to current position in str */
/* skip leading whitespace */
while (isspace((int)(*ptr)))
ptr++;
/* printf("1) %s\n",ptr); */
/* scan optional sign character */
switch (*ptr) {
case '+':
ptr++;
s = 1;
break;
case '-':
ptr++;
s = -1;
break;
default:
s = 1;
break;
}
/* printf("2) %s\n",ptr); */
/* '0X' prefix */
if ((*ptr++) != '0') {
/* printf("failed to detect '0'\n"); */
*endptr = str;
return 0;
}
/* printf("3) %s\n",ptr); */
if (toupper(*ptr++) != toupper(X)) {
/* printf("failed to detect '%c'\n",X); */
*endptr = str;
return 0;
}
/* printf("4) %s\n",ptr); */
/* attempt conversion on remainder of string using strtol() */
val = strtol(ptr, (char**)endptr, base);
if (*endptr == ptr) {
/* conversion failed */
*endptr = str;
return 0;
}
/* success */
return s * val;
}
/* Returns 1 if str matches suffix (case insensitive). */
/* Str may contain trailing whitespace, but nothing else. */
static int detectsuffix(const char* str, const char* suffix) {
/* scan pairwise through strings until mismatch detected */
while (toupper(*str) == toupper(*suffix)) {
/* printf("'%c' '%c'\n", *str, *suffix); */
/* return 1 (success) if match persists until the string terminator */
if (*str == '\0')
return 1;
/* next chars */
str++;
suffix++;
}
/* printf("'%c' '%c' mismatch\n", *str, *suffix); */
/* return 0 (fail) if the matching did not consume the entire suffix */
if (*suffix != 0)
return 0; /* failed to consume entire suffix */
/* skip any remaining whitespace in str */
while (isspace((int)(*str)))
str++;
/* return 1 (success) if we have reached end of str else return 0 (fail) */
return (*str == '\0') ? 1 : 0;
}
static int arg_int_scanfn(struct arg_int* parent, const char* argval) {
int errorcode = 0;
if (parent->count == parent->hdr.maxcount) {
/* maximum number of arguments exceeded */
errorcode = ARG_ERR_MAXCOUNT;
} else if (!argval) {
/* a valid argument with no argument value was given. */
/* This happens when an optional argument value was invoked. */
/* leave parent arguiment value unaltered but still count the argument. */
parent->count++;
} else {
long int val;
const char* end;
/* attempt to extract hex integer (eg: +0x123) from argval into val conversion */
val = strtol0X(argval, &end, 'X', 16);
if (end == argval) {
/* hex failed, attempt octal conversion (eg +0o123) */
val = strtol0X(argval, &end, 'O', 8);
if (end == argval) {
/* octal failed, attempt binary conversion (eg +0B101) */
val = strtol0X(argval, &end, 'B', 2);
if (end == argval) {
/* binary failed, attempt decimal conversion with no prefix (eg 1234) */
val = strtol(argval, (char**)&end, 10);
if (end == argval) {
/* all supported number formats failed */
return ARG_ERR_BADINT;
}
}
}
}
/* Safety check for integer overflow. WARNING: this check */
/* achieves nothing on machines where size(int)==size(long). */
if (val > INT_MAX || val < INT_MIN)
errorcode = ARG_ERR_OVERFLOW;
/* Detect any suffixes (KB,MB,GB) and multiply argument value appropriately. */
/* We need to be mindful of integer overflows when using such big numbers. */
if (detectsuffix(end, "KB")) /* kilobytes */
{
if (val > (INT_MAX / 1024) || val < (INT_MIN / 1024))
errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */
else
val *= 1024; /* 1KB = 1024 */
} else if (detectsuffix(end, "MB")) /* megabytes */
{
if (val > (INT_MAX / 1048576) || val < (INT_MIN / 1048576))
errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */
else
val *= 1048576; /* 1MB = 1024*1024 */
} else if (detectsuffix(end, "GB")) /* gigabytes */
{
if (val > (INT_MAX / 1073741824) || val < (INT_MIN / 1073741824))
errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */
else
val *= 1073741824; /* 1GB = 1024*1024*1024 */
} else if (!detectsuffix(end, ""))
errorcode = ARG_ERR_BADINT; /* invalid suffix detected */
/* if success then store result in parent->ival[] array */
if (errorcode == 0)
parent->ival[parent->count++] = (int)val;
}
/* printf("%s:scanfn(%p,%p) returns %d\n",__FILE__,parent,argval,errorcode); */
return errorcode;
}
static int arg_int_checkfn(struct arg_int* parent) {
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
/*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/
return errorcode;
}
static void arg_int_errorfn(struct arg_int* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
/* make argval NULL safe */
argval = argval ? argval : "";
arg_dstr_catf(ds, "%s: ", progname);
switch (errorcode) {
case ARG_ERR_MINCOUNT:
arg_dstr_cat(ds, "missing option ");
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
case ARG_ERR_MAXCOUNT:
arg_dstr_cat(ds, "excess option ");
arg_print_option_ds(ds, shortopts, longopts, argval, "\n");
break;
case ARG_ERR_BADINT:
arg_dstr_catf(ds, "invalid argument \"%s\" to option ", argval);
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
case ARG_ERR_OVERFLOW:
arg_dstr_cat(ds, "integer overflow at option ");
arg_print_option_ds(ds, shortopts, longopts, datatype, " ");
arg_dstr_catf(ds, "(%s is too large)\n", argval);
break;
}
}
struct arg_int* arg_int0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_intn(shortopts, longopts, datatype, 0, 1, glossary);
}
struct arg_int* arg_int1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_intn(shortopts, longopts, datatype, 1, 1, glossary);
}
struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) {
size_t nbytes;
struct arg_int* result;
/* foolproof things by ensuring maxcount is not less than mincount */
maxcount = (maxcount < mincount) ? mincount : maxcount;
nbytes = sizeof(struct arg_int) /* storage for struct arg_int */
+ (size_t)maxcount * sizeof(int); /* storage for ival[maxcount] array */
result = (struct arg_int*)xmalloc(nbytes);
/* init the arg_hdr struct */
result->hdr.flag = ARG_HASVALUE;
result->hdr.shortopts = shortopts;
result->hdr.longopts = longopts;
result->hdr.datatype = datatype ? datatype : "<int>";
result->hdr.glossary = glossary;
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_int_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_int_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_int_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_int_errorfn;
/* store the ival[maxcount] array immediately after the arg_int struct */
result->ival = (int*)(result + 1);
result->count = 0;
ARG_TRACE(("arg_intn() returns %p\n", result));
return result;
}

View File

@ -0,0 +1,124 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_lit: Implements the literature command-line option
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
* <sheitmann@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdlib.h>
static void arg_lit_resetfn(struct arg_lit* parent) {
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
static int arg_lit_scanfn(struct arg_lit* parent, const char* argval) {
int errorcode = 0;
if (parent->count < parent->hdr.maxcount)
parent->count++;
else
errorcode = ARG_ERR_MAXCOUNT;
ARG_TRACE(("%s:scanfn(%p,%s) returns %d\n", __FILE__, parent, argval, errorcode));
return errorcode;
}
static int arg_lit_checkfn(struct arg_lit* parent) {
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static void arg_lit_errorfn(struct arg_lit* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
switch (errorcode) {
case ARG_ERR_MINCOUNT:
arg_dstr_catf(ds, "%s: missing option ", progname);
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
arg_dstr_cat(ds, "\n");
break;
case ARG_ERR_MAXCOUNT:
arg_dstr_catf(ds, "%s: extraneous option ", progname);
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
}
ARG_TRACE(("%s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, ds, errorcode, argval, progname));
}
struct arg_lit* arg_lit0(const char* shortopts, const char* longopts, const char* glossary) {
return arg_litn(shortopts, longopts, 0, 1, glossary);
}
struct arg_lit* arg_lit1(const char* shortopts, const char* longopts, const char* glossary) {
return arg_litn(shortopts, longopts, 1, 1, glossary);
}
struct arg_lit* arg_litn(const char* shortopts, const char* longopts, int mincount, int maxcount, const char* glossary) {
struct arg_lit* result;
/* foolproof things by ensuring maxcount is not less than mincount */
maxcount = (maxcount < mincount) ? mincount : maxcount;
result = (struct arg_lit*)xmalloc(sizeof(struct arg_lit));
/* init the arg_hdr struct */
result->hdr.flag = 0;
result->hdr.shortopts = shortopts;
result->hdr.longopts = longopts;
result->hdr.datatype = NULL;
result->hdr.glossary = glossary;
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_lit_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_lit_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_lit_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_lit_errorfn;
/* init local variables */
result->count = 0;
ARG_TRACE(("arg_litn() returns %p\n", result));
return result;
}

View File

@ -0,0 +1,64 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_rem: Implements the rem command-line option
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
* <sheitmann@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdlib.h>
struct arg_rem* arg_rem(const char* datatype, const char* glossary) {
struct arg_rem* result = (struct arg_rem*)xmalloc(sizeof(struct arg_rem));
result->hdr.flag = 0;
result->hdr.shortopts = NULL;
result->hdr.longopts = NULL;
result->hdr.datatype = datatype;
result->hdr.glossary = glossary;
result->hdr.mincount = 1;
result->hdr.maxcount = 1;
result->hdr.parent = result;
result->hdr.resetfn = NULL;
result->hdr.scanfn = NULL;
result->hdr.checkfn = NULL;
result->hdr.errorfn = NULL;
ARG_TRACE(("arg_rem() returns %p\n", result));
return result;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,151 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_str: Implements the str command-line option
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
* <sheitmann@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdlib.h>
static void arg_str_resetfn(struct arg_str* parent) {
int i;
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
for (i = 0; i < parent->count; i++) {
parent->sval[i] = "";
}
parent->count = 0;
}
static int arg_str_scanfn(struct arg_str* parent, const char* argval) {
int errorcode = 0;
if (parent->count == parent->hdr.maxcount) {
/* maximum number of arguments exceeded */
errorcode = ARG_ERR_MAXCOUNT;
} else if (!argval) {
/* a valid argument with no argument value was given. */
/* This happens when an optional argument value was invoked. */
/* leave parent argument value unaltered but still count the argument. */
parent->count++;
} else {
parent->sval[parent->count++] = argval;
}
ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static int arg_str_checkfn(struct arg_str* parent) {
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}
static void arg_str_errorfn(struct arg_str* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
/* make argval NULL safe */
argval = argval ? argval : "";
arg_dstr_catf(ds, "%s: ", progname);
switch (errorcode) {
case ARG_ERR_MINCOUNT:
arg_dstr_cat(ds, "missing option ");
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
case ARG_ERR_MAXCOUNT:
arg_dstr_cat(ds, "excess option ");
arg_print_option_ds(ds, shortopts, longopts, argval, "\n");
break;
}
}
struct arg_str* arg_str0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_strn(shortopts, longopts, datatype, 0, 1, glossary);
}
struct arg_str* arg_str1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_strn(shortopts, longopts, datatype, 1, 1, glossary);
}
struct arg_str* arg_strn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) {
size_t nbytes;
struct arg_str* result;
int i;
/* should not allow this stupid error */
/* we should return an error code warning this logic error */
/* foolproof things by ensuring maxcount is not less than mincount */
maxcount = (maxcount < mincount) ? mincount : maxcount;
nbytes = sizeof(struct arg_str) /* storage for struct arg_str */
+ (size_t)maxcount * sizeof(char*); /* storage for sval[maxcount] array */
result = (struct arg_str*)xmalloc(nbytes);
/* init the arg_hdr struct */
result->hdr.flag = ARG_HASVALUE;
result->hdr.shortopts = shortopts;
result->hdr.longopts = longopts;
result->hdr.datatype = datatype ? datatype : "<string>";
result->hdr.glossary = glossary;
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_str_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_str_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_str_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_str_errorfn;
/* store the sval[maxcount] array immediately after the arg_str struct */
result->sval = (const char**)(result + 1);
result->count = 0;
/* foolproof the string pointers by initializing them to reference empty strings */
for (i = 0; i < maxcount; i++)
result->sval[i] = "";
ARG_TRACE(("arg_strn() returns %p\n", result));
return result;
}

View File

@ -0,0 +1,183 @@
/*
* SPDX-FileCopyrightText: 2013-2019 Tom G. Huang
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* arg_utils: Implements memory, panic, and other utility functions
*
* This file is part of the argtable3 library.
*
* Copyright (C) 2013-2019 Tom G. Huang
* <tomghuang@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void panic(const char* fmt, ...);
static arg_panicfn* s_panic = panic;
void dbg_printf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
static void panic(const char* fmt, ...) {
va_list args;
char* s;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
s = getenv("EF_DUMPCORE");
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
if (s != NULL && *s != '\0') {
abort();
} else {
exit(EXIT_FAILURE);
}
}
void arg_set_panic(arg_panicfn* proc) {
s_panic = proc;
}
void* xmalloc(size_t size) {
void* ret = malloc(size);
if (!ret) {
s_panic("Out of memory!\n");
}
return ret;
}
void* xcalloc(size_t count, size_t size) {
size_t allocated_count = count && size ? count : 1;
size_t allocated_size = count && size ? size : 1;
void* ret = calloc(allocated_count, allocated_size);
if (!ret) {
s_panic("Out of memory!\n");
}
return ret;
}
void* xrealloc(void* ptr, size_t size) {
size_t allocated_size = size ? size : 1;
void* ret = realloc(ptr, allocated_size);
if (!ret) {
s_panic("Out of memory!\n");
}
return ret;
}
void xfree(void* ptr) {
free(ptr);
}
static void merge(void* data, int esize, int i, int j, int k, arg_comparefn* comparefn) {
char* a = (char*)data;
char* m;
int ipos, jpos, mpos;
/* Initialize the counters used in merging. */
ipos = i;
jpos = j + 1;
mpos = 0;
/* Allocate storage for the merged elements. */
m = (char*)xmalloc((size_t)(esize * ((k - i) + 1)));
/* Continue while either division has elements to merge. */
while (ipos <= j || jpos <= k) {
if (ipos > j) {
/* The left division has no more elements to merge. */
while (jpos <= k) {
memcpy(&m[mpos * esize], &a[jpos * esize], (size_t)esize);
jpos++;
mpos++;
}
continue;
} else if (jpos > k) {
/* The right division has no more elements to merge. */
while (ipos <= j) {
memcpy(&m[mpos * esize], &a[ipos * esize], (size_t)esize);
ipos++;
mpos++;
}
continue;
}
/* Append the next ordered element to the merged elements. */
if (comparefn(&a[ipos * esize], &a[jpos * esize]) < 0) {
memcpy(&m[mpos * esize], &a[ipos * esize], (size_t)esize);
ipos++;
mpos++;
} else {
memcpy(&m[mpos * esize], &a[jpos * esize], (size_t)esize);
jpos++;
mpos++;
}
}
/* Prepare to pass back the merged data. */
memcpy(&a[i * esize], m, (size_t)(esize * ((k - i) + 1)));
xfree(m);
}
void arg_mgsort(void* data, int size, int esize, int i, int k, arg_comparefn* comparefn) {
int j;
/* Stop the recursion when no more divisions can be made. */
if (i < k) {
/* Determine where to divide the elements. */
j = (int)(((i + k - 1)) / 2);
/* Recursively sort the two divisions. */
arg_mgsort(data, size, esize, i, j, comparefn);
arg_mgsort(data, size, esize, j + 1, k, comparefn);
merge(data, esize, i, j, k, comparefn);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,11 @@
/*
* SPDX-FileCopyrightText: 1998-2001,2003-2011,2013 Stewart Heitmann
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* argtable3: Declares the main interfaces of the library
*
* This file is part of the argtable3 library.
*
* Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
@ -31,274 +38,240 @@
#ifndef ARGTABLE3
#define ARGTABLE3
#include <stdio.h> /* FILE */
#include <time.h> /* struct tm */
#include <stdio.h> /* FILE */
#include <time.h> /* struct tm */
#ifdef __cplusplus
extern "C" {
#endif
#define ARG_REX_ICASE 1
#define ARG_DSTR_SIZE 200
#define ARG_CMD_NAME_LEN 100
#define ARG_CMD_DESCRIPTION_LEN 256
#ifndef ARG_REPLACE_GETOPT
#define ARG_REPLACE_GETOPT 0 /* ESP-IDF-specific: use newlib-provided getopt instead of the embedded one */
#endif /* ARG_REPLACE_GETOPT */
/* bit masks for arg_hdr.flag */
enum
{
ARG_TERMINATOR=0x1,
ARG_HASVALUE=0x2,
ARG_HASOPTVALUE=0x4
};
enum { ARG_TERMINATOR = 0x1, ARG_HASVALUE = 0x2, ARG_HASOPTVALUE = 0x4 };
typedef void (arg_resetfn)(void *parent);
typedef int (arg_scanfn)(void *parent, const char *argval);
typedef int (arg_checkfn)(void *parent);
typedef void (arg_errorfn)(void *parent, FILE *fp, int error, const char *argval, const char *progname);
#if defined(_WIN32)
#if defined(argtable3_EXPORTS)
#define ARG_EXTERN __declspec(dllexport)
#elif defined(argtable3_IMPORTS)
#define ARG_EXTERN __declspec(dllimport)
#else
#define ARG_EXTERN
#endif
#else
#define ARG_EXTERN
#endif
typedef struct _internal_arg_dstr* arg_dstr_t;
typedef void* arg_cmd_itr_t;
typedef void(arg_resetfn)(void* parent);
typedef int(arg_scanfn)(void* parent, const char* argval);
typedef int(arg_checkfn)(void* parent);
typedef void(arg_errorfn)(void* parent, arg_dstr_t ds, int error, const char* argval, const char* progname);
typedef void(arg_dstr_freefn)(char* buf);
typedef int(arg_cmdfn)(int argc, char* argv[], arg_dstr_t res);
typedef int(arg_comparefn)(const void* k1, const void* k2);
/*
* The arg_hdr struct defines properties that are common to all arg_xxx structs.
* The argtable library requires each arg_xxx struct to have an arg_hdr
* struct as its first data member.
* The argtable library functions then use this data to identify the
* properties of the command line option, such as its option tags,
* datatype string, and glossary strings, and so on.
* Moreover, the arg_hdr struct contains pointers to custom functions that
* are provided by each arg_xxx struct which perform the tasks of parsing
* that particular arg_xxx arguments, performing post-parse checks, and
* reporting errors.
* These functions are private to the individual arg_xxx source code
* and are the pointer to them are initiliased by that arg_xxx struct's
* constructor function. The user could alter them after construction
* if desired, but the original intention is for them to be set by the
* constructor and left unaltered.
*/
struct arg_hdr
{
char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */
const char *shortopts; /* String defining the short options */
const char *longopts; /* String defiing the long options */
const char *datatype; /* Description of the argument data type */
const char *glossary; /* Description of the option as shown by arg_print_glossary function */
int mincount; /* Minimum number of occurences of this option accepted */
int maxcount; /* Maximum number of occurences if this option accepted */
void *parent; /* Pointer to parent arg_xxx struct */
arg_resetfn *resetfn; /* Pointer to parent arg_xxx reset function */
arg_scanfn *scanfn; /* Pointer to parent arg_xxx scan function */
arg_checkfn *checkfn; /* Pointer to parent arg_xxx check function */
arg_errorfn *errorfn; /* Pointer to parent arg_xxx error function */
void *priv; /* Pointer to private header data for use by arg_xxx functions */
};
* The arg_hdr struct defines properties that are common to all arg_xxx structs.
* The argtable library requires each arg_xxx struct to have an arg_hdr
* struct as its first data member.
* The argtable library functions then use this data to identify the
* properties of the command line option, such as its option tags,
* datatype string, and glossary strings, and so on.
* Moreover, the arg_hdr struct contains pointers to custom functions that
* are provided by each arg_xxx struct which perform the tasks of parsing
* that particular arg_xxx arguments, performing post-parse checks, and
* reporting errors.
* These functions are private to the individual arg_xxx source code
* and are the pointer to them are initiliased by that arg_xxx struct's
* constructor function. The user could alter them after construction
* if desired, but the original intention is for them to be set by the
* constructor and left unaltered.
*/
typedef struct arg_hdr {
char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */
const char* shortopts; /* String defining the short options */
const char* longopts; /* String defiing the long options */
const char* datatype; /* Description of the argument data type */
const char* glossary; /* Description of the option as shown by arg_print_glossary function */
int mincount; /* Minimum number of occurences of this option accepted */
int maxcount; /* Maximum number of occurences if this option accepted */
void* parent; /* Pointer to parent arg_xxx struct */
arg_resetfn* resetfn; /* Pointer to parent arg_xxx reset function */
arg_scanfn* scanfn; /* Pointer to parent arg_xxx scan function */
arg_checkfn* checkfn; /* Pointer to parent arg_xxx check function */
arg_errorfn* errorfn; /* Pointer to parent arg_xxx error function */
void* priv; /* Pointer to private header data for use by arg_xxx functions */
} arg_hdr_t;
struct arg_rem
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
};
typedef struct arg_rem {
struct arg_hdr hdr; /* The mandatory argtable header struct */
} arg_rem_t;
struct arg_lit
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
};
typedef struct arg_lit {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
} arg_lit_t;
struct arg_int
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
int *ival; /* Array of parsed argument values */
};
typedef struct arg_int {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
int* ival; /* Array of parsed argument values */
} arg_int_t;
struct arg_dbl
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
double *dval; /* Array of parsed argument values */
};
typedef struct arg_dbl {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
double* dval; /* Array of parsed argument values */
} arg_dbl_t;
struct arg_str
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
const char **sval; /* Array of parsed argument values */
};
typedef struct arg_str {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
const char** sval; /* Array of parsed argument values */
} arg_str_t;
struct arg_rex
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
const char **sval; /* Array of parsed argument values */
};
typedef struct arg_rex {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
const char** sval; /* Array of parsed argument values */
} arg_rex_t;
struct arg_file
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args*/
const char **filename; /* Array of parsed filenames (eg: /home/foo.bar) */
const char **basename; /* Array of parsed basenames (eg: foo.bar) */
const char **extension; /* Array of parsed extensions (eg: .bar) */
};
typedef struct arg_file {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args*/
const char** filename; /* Array of parsed filenames (eg: /home/foo.bar) */
const char** basename; /* Array of parsed basenames (eg: foo.bar) */
const char** extension; /* Array of parsed extensions (eg: .bar) */
} arg_file_t;
struct arg_date
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
const char *format; /* strptime format string used to parse the date */
int count; /* Number of matching command line args */
struct tm *tmval; /* Array of parsed time values */
};
typedef struct arg_date {
struct arg_hdr hdr; /* The mandatory argtable header struct */
const char* format; /* strptime format string used to parse the date */
int count; /* Number of matching command line args */
struct tm* tmval; /* Array of parsed time values */
} arg_date_t;
enum {ARG_ELIMIT=1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG};
struct arg_end
{
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of errors encountered */
int *error; /* Array of error codes */
void **parent; /* Array of pointers to offending arg_xxx struct */
const char **argval; /* Array of pointers to offending argv[] string */
};
enum { ARG_ELIMIT = 1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG };
typedef struct arg_end {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of errors encountered */
int* error; /* Array of error codes */
void** parent; /* Array of pointers to offending arg_xxx struct */
const char** argval; /* Array of pointers to offending argv[] string */
} arg_end_t;
typedef struct arg_cmd_info {
char name[ARG_CMD_NAME_LEN];
char description[ARG_CMD_DESCRIPTION_LEN];
arg_cmdfn* proc;
} arg_cmd_info_t;
/**** arg_xxx constructor functions *********************************/
struct arg_rem* arg_rem(const char* datatype, const char* glossary);
ARG_EXTERN struct arg_rem* arg_rem(const char* datatype, const char* glossary);
struct arg_lit* arg_lit0(const char* shortopts,
const char* longopts,
const char* glossary);
struct arg_lit* arg_lit1(const char* shortopts,
const char* longopts,
const char *glossary);
struct arg_lit* arg_litn(const char* shortopts,
const char* longopts,
int mincount,
int maxcount,
const char *glossary);
ARG_EXTERN struct arg_lit* arg_lit0(const char* shortopts, const char* longopts, const char* glossary);
ARG_EXTERN struct arg_lit* arg_lit1(const char* shortopts, const char* longopts, const char* glossary);
ARG_EXTERN struct arg_lit* arg_litn(const char* shortopts, const char* longopts, int mincount, int maxcount, const char* glossary);
struct arg_key* arg_key0(const char* keyword,
int flags,
const char* glossary);
struct arg_key* arg_key1(const char* keyword,
int flags,
const char* glossary);
struct arg_key* arg_keyn(const char* keyword,
int flags,
int mincount,
int maxcount,
const char* glossary);
ARG_EXTERN struct arg_int* arg_int0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_int* arg_int1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary);
struct arg_int* arg_int0(const char* shortopts,
const char* longopts,
const char* datatype,
const char* glossary);
struct arg_int* arg_int1(const char* shortopts,
const char* longopts,
const char* datatype,
const char *glossary);
struct arg_int* arg_intn(const char* shortopts,
const char* longopts,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
ARG_EXTERN struct arg_dbl* arg_dbl0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_dbl* arg_dbl1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_dbl* arg_dbln(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary);
struct arg_dbl* arg_dbl0(const char* shortopts,
const char* longopts,
const char* datatype,
const char* glossary);
struct arg_dbl* arg_dbl1(const char* shortopts,
const char* longopts,
const char* datatype,
const char *glossary);
struct arg_dbl* arg_dbln(const char* shortopts,
const char* longopts,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
ARG_EXTERN struct arg_str* arg_str0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_str* arg_str1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_str* arg_strn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary);
struct arg_str* arg_str0(const char* shortopts,
const char* longopts,
const char* datatype,
const char* glossary);
struct arg_str* arg_str1(const char* shortopts,
const char* longopts,
const char* datatype,
const char *glossary);
struct arg_str* arg_strn(const char* shortopts,
const char* longopts,
const char* datatype,
int mincount,
int maxcount,
const char *glossary);
ARG_EXTERN struct arg_rex* arg_rex0(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary);
ARG_EXTERN struct arg_rex* arg_rex1(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary);
ARG_EXTERN struct arg_rex* arg_rexn(const char* shortopts,
const char* longopts,
const char* pattern,
const char* datatype,
int mincount,
int maxcount,
int flags,
const char* glossary);
struct arg_rex* arg_rex0(const char* shortopts,
const char* longopts,
const char* pattern,
const char* datatype,
int flags,
const char* glossary);
struct arg_rex* arg_rex1(const char* shortopts,
const char* longopts,
const char* pattern,
const char* datatype,
int flags,
const char *glossary);
struct arg_rex* arg_rexn(const char* shortopts,
const char* longopts,
const char* pattern,
const char* datatype,
int mincount,
int maxcount,
int flags,
const char *glossary);
ARG_EXTERN struct arg_file* arg_file0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_file* arg_file1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_file* arg_filen(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary);
struct arg_file* arg_file0(const char* shortopts,
const char* longopts,
const char* datatype,
const char* glossary);
struct arg_file* arg_file1(const char* shortopts,
const char* longopts,
const char* datatype,
const char *glossary);
struct arg_file* arg_filen(const char* shortopts,
const char* longopts,
const char* datatype,
int mincount,
int maxcount,
const char *glossary);
ARG_EXTERN struct arg_date* arg_date0(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_date* arg_date1(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary);
ARG_EXTERN struct arg_date* arg_daten(const char* shortopts, const char* longopts, const char* format, const char* datatype, int mincount, int maxcount, const char* glossary);
struct arg_date* arg_date0(const char* shortopts,
const char* longopts,
const char* format,
const char* datatype,
const char* glossary);
struct arg_date* arg_date1(const char* shortopts,
const char* longopts,
const char* format,
const char* datatype,
const char *glossary);
struct arg_date* arg_daten(const char* shortopts,
const char* longopts,
const char* format,
const char* datatype,
int mincount,
int maxcount,
const char *glossary);
struct arg_end* arg_end(int maxerrors);
ARG_EXTERN struct arg_end* arg_end(int maxcount);
#define ARG_DSTR_STATIC ((arg_dstr_freefn*)0)
#define ARG_DSTR_VOLATILE ((arg_dstr_freefn*)1)
#define ARG_DSTR_DYNAMIC ((arg_dstr_freefn*)3)
/**** other functions *******************************************/
int arg_nullcheck(void **argtable);
int arg_parse(int argc, char **argv, void **argtable);
void arg_print_option(FILE *fp, const char *shortopts, const char *longopts, const char *datatype, const char *suffix);
void arg_print_syntax(FILE *fp, void **argtable, const char *suffix);
void arg_print_syntaxv(FILE *fp, void **argtable, const char *suffix);
void arg_print_glossary(FILE *fp, void **argtable, const char *format);
void arg_print_glossary_gnu(FILE *fp, void **argtable);
void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname);
void arg_freetable(void **argtable, size_t n);
void arg_print_formatted(FILE *fp, const unsigned lmargin, const unsigned rmargin, const char *text);
ARG_EXTERN int arg_nullcheck(void** argtable);
ARG_EXTERN int arg_parse(int argc, char** argv, void** argtable);
ARG_EXTERN void arg_print_option(FILE* fp, const char* shortopts, const char* longopts, const char* datatype, const char* suffix);
ARG_EXTERN void arg_print_syntax(FILE* fp, void** argtable, const char* suffix);
ARG_EXTERN void arg_print_syntaxv(FILE* fp, void** argtable, const char* suffix);
ARG_EXTERN void arg_print_glossary(FILE* fp, void** argtable, const char* format);
ARG_EXTERN void arg_print_glossary_gnu(FILE* fp, void** argtable);
ARG_EXTERN void arg_print_formatted(FILE *fp, const unsigned lmargin, const unsigned rmargin, const char *text);
ARG_EXTERN void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname);
ARG_EXTERN void arg_print_option_ds(arg_dstr_t ds, const char* shortopts, const char* longopts, const char* datatype, const char* suffix);
ARG_EXTERN void arg_print_syntax_ds(arg_dstr_t ds, void** argtable, const char* suffix);
ARG_EXTERN void arg_print_syntaxv_ds(arg_dstr_t ds, void** argtable, const char* suffix);
ARG_EXTERN void arg_print_glossary_ds(arg_dstr_t ds, void** argtable, const char* format);
ARG_EXTERN void arg_print_glossary_gnu_ds(arg_dstr_t ds, void** argtable);
ARG_EXTERN void arg_print_errors_ds(arg_dstr_t ds, struct arg_end* end, const char* progname);
ARG_EXTERN void arg_freetable(void** argtable, size_t n);
ARG_EXTERN arg_dstr_t arg_dstr_create(void);
ARG_EXTERN void arg_dstr_destroy(arg_dstr_t ds);
ARG_EXTERN void arg_dstr_reset(arg_dstr_t ds);
ARG_EXTERN void arg_dstr_free(arg_dstr_t ds);
ARG_EXTERN void arg_dstr_set(arg_dstr_t ds, char* str, arg_dstr_freefn* free_proc);
ARG_EXTERN void arg_dstr_cat(arg_dstr_t ds, const char* str);
ARG_EXTERN void arg_dstr_catc(arg_dstr_t ds, char c);
ARG_EXTERN void arg_dstr_catf(arg_dstr_t ds, const char* fmt, ...);
ARG_EXTERN char* arg_dstr_cstr(arg_dstr_t ds);
ARG_EXTERN void arg_cmd_init(void);
ARG_EXTERN void arg_cmd_uninit(void);
ARG_EXTERN void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description);
ARG_EXTERN void arg_cmd_unregister(const char* name);
ARG_EXTERN int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res);
ARG_EXTERN unsigned int arg_cmd_count(void);
ARG_EXTERN arg_cmd_info_t* arg_cmd_info(const char* name);
ARG_EXTERN arg_cmd_itr_t arg_cmd_itr_create(void);
ARG_EXTERN void arg_cmd_itr_destroy(arg_cmd_itr_t itr);
ARG_EXTERN int arg_cmd_itr_advance(arg_cmd_itr_t itr);
ARG_EXTERN char* arg_cmd_itr_key(arg_cmd_itr_t itr);
ARG_EXTERN arg_cmd_info_t* arg_cmd_itr_value(arg_cmd_itr_t itr);
ARG_EXTERN int arg_cmd_itr_search(arg_cmd_itr_t itr, void* k);
ARG_EXTERN void arg_mgsort(void* data, int size, int esize, int i, int k, arg_comparefn* comparefn);
ARG_EXTERN void arg_make_get_help_msg(arg_dstr_t res);
ARG_EXTERN void arg_make_help_msg(arg_dstr_t ds, char* cmd_name, void** argtable);
ARG_EXTERN void arg_make_syntax_err_msg(arg_dstr_t ds, void** argtable, struct arg_end* end);
ARG_EXTERN int arg_make_syntax_err_help_msg(arg_dstr_t ds, char* name, int help, int nerrors, void** argtable, struct arg_end* end, int* exitcode);
ARG_EXTERN void arg_set_module_name(const char* name);
ARG_EXTERN void arg_set_module_version(int major, int minor, int patch, const char* tag);
/**** deprecated functions, for back-compatibility only ********/
void arg_free(void **argtable);
ARG_EXTERN void arg_free(void** argtable);
#ifdef __cplusplus
}

View File

@ -0,0 +1,245 @@
/*
* SPDX-FileCopyrightText: 2013-2019 Tom G. Huang
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*******************************************************************************
* argtable3_private: Declares private types, constants, and interfaces
*
* This file is part of the argtable3 library.
*
* Copyright (C) 2013-2019 Tom G. Huang
* <tomghuang@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef ARG_UTILS_H
#define ARG_UTILS_H
#include <stdlib.h>
#define ARG_ENABLE_TRACE 0
#define ARG_ENABLE_LOG 0
#ifdef __cplusplus
extern "C" {
#endif
enum { ARG_ERR_MINCOUNT = 1, ARG_ERR_MAXCOUNT, ARG_ERR_BADINT, ARG_ERR_OVERFLOW, ARG_ERR_BADDOUBLE, ARG_ERR_BADDATE, ARG_ERR_REGNOMATCH };
typedef void(arg_panicfn)(const char* fmt, ...);
#if defined(_MSC_VER)
#define ARG_TRACE(x) \
__pragma(warning(push)) __pragma(warning(disable : 4127)) do { \
if (ARG_ENABLE_TRACE) \
dbg_printf x; \
} \
while (0) \
__pragma(warning(pop))
#define ARG_LOG(x) \
__pragma(warning(push)) __pragma(warning(disable : 4127)) do { \
if (ARG_ENABLE_LOG) \
dbg_printf x; \
} \
while (0) \
__pragma(warning(pop))
#else
#define ARG_TRACE(x) \
do { \
if (ARG_ENABLE_TRACE) \
dbg_printf x; \
} while (0)
#define ARG_LOG(x) \
do { \
if (ARG_ENABLE_LOG) \
dbg_printf x; \
} while (0)
#endif
/*
* Rename a few generic names to unique names.
* They can be a problem for the platforms like NuttX, where
* the namespace is flat for everything including apps and libraries.
*/
#define xmalloc argtable3_xmalloc
#define xcalloc argtable3_xcalloc
#define xrealloc argtable3_xrealloc
#define xfree argtable3_xfree
extern void dbg_printf(const char* fmt, ...);
extern void arg_set_panic(arg_panicfn* proc);
extern void* xmalloc(size_t size);
extern void* xcalloc(size_t count, size_t size);
extern void* xrealloc(void* ptr, size_t size);
extern void xfree(void* ptr);
struct arg_hashtable_entry {
void *k, *v;
unsigned int h;
struct arg_hashtable_entry* next;
};
typedef struct arg_hashtable {
unsigned int tablelength;
struct arg_hashtable_entry** table;
unsigned int entrycount;
unsigned int loadlimit;
unsigned int primeindex;
unsigned int (*hashfn)(const void* k);
int (*eqfn)(const void* k1, const void* k2);
} arg_hashtable_t;
/**
* @brief Create a hash table.
*
* @param minsize minimum initial size of hash table
* @param hashfn function for hashing keys
* @param eqfn function for determining key equality
* @return newly created hash table or NULL on failure
*/
arg_hashtable_t* arg_hashtable_create(unsigned int minsize, unsigned int (*hashfn)(const void*), int (*eqfn)(const void*, const void*));
/**
* @brief This function will cause the table to expand if the insertion would take
* the ratio of entries to table size over the maximum load factor.
*
* This function does not check for repeated insertions with a duplicate key.
* The value returned when using a duplicate key is undefined -- when
* the hash table changes size, the order of retrieval of duplicate key
* entries is reversed.
* If in doubt, remove before insert.
*
* @param h the hash table to insert into
* @param k the key - hash table claims ownership and will free on removal
* @param v the value - does not claim ownership
* @return non-zero for successful insertion
*/
void arg_hashtable_insert(arg_hashtable_t* h, void* k, void* v);
#define ARG_DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
int fnname(arg_hashtable_t* h, keytype* k, valuetype* v) { return arg_hashtable_insert(h, k, v); }
/**
* @brief Search the specified key in the hash table.
*
* @param h the hash table to search
* @param k the key to search for - does not claim ownership
* @return the value associated with the key, or NULL if none found
*/
void* arg_hashtable_search(arg_hashtable_t* h, const void* k);
#define ARG_DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
valuetype* fnname(arg_hashtable_t* h, keytype* k) { return (valuetype*)(arg_hashtable_search(h, k)); }
/**
* @brief Remove the specified key from the hash table.
*
* @param h the hash table to remove the item from
* @param k the key to search for - does not claim ownership
*/
void arg_hashtable_remove(arg_hashtable_t* h, const void* k);
#define ARG_DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
void fnname(arg_hashtable_t* h, keytype* k) { arg_hashtable_remove(h, k); }
/**
* @brief Return the number of keys in the hash table.
*
* @param h the hash table
* @return the number of items stored in the hash table
*/
unsigned int arg_hashtable_count(arg_hashtable_t* h);
/**
* @brief Change the value associated with the key.
*
* function to change the value associated with a key, where there already
* exists a value bound to the key in the hash table.
* Source due to Holger Schemel.
*
* @name hashtable_change
* @param h the hash table
* @param key
* @param value
*/
int arg_hashtable_change(arg_hashtable_t* h, void* k, void* v);
/**
* @brief Free the hash table and the memory allocated for each key-value pair.
*
* @param h the hash table
* @param free_values whether to call 'free' on the remaining values
*/
void arg_hashtable_destroy(arg_hashtable_t* h, int free_values);
typedef struct arg_hashtable_itr {
arg_hashtable_t* h;
struct arg_hashtable_entry* e;
struct arg_hashtable_entry* parent;
unsigned int index;
} arg_hashtable_itr_t;
arg_hashtable_itr_t* arg_hashtable_itr_create(arg_hashtable_t* h);
void arg_hashtable_itr_destroy(arg_hashtable_itr_t* itr);
/**
* @brief Return the value of the (key,value) pair at the current position.
*/
extern void* arg_hashtable_itr_key(arg_hashtable_itr_t* i);
/**
* @brief Return the value of the (key,value) pair at the current position.
*/
extern void* arg_hashtable_itr_value(arg_hashtable_itr_t* i);
/**
* @brief Advance the iterator to the next element. Returns zero if advanced to end of table.
*/
int arg_hashtable_itr_advance(arg_hashtable_itr_t* itr);
/**
* @brief Remove current element and advance the iterator to the next element.
*/
int arg_hashtable_itr_remove(arg_hashtable_itr_t* itr);
/**
* @brief Search and overwrite the supplied iterator, to point to the entry matching the supplied key.
*
* @return Zero if not found.
*/
int arg_hashtable_itr_search(arg_hashtable_itr_t* itr, arg_hashtable_t* h, void* k);
#define ARG_DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
int fnname(arg_hashtable_itr_t* i, arg_hashtable_t* h, keytype* k) { return (arg_hashtable_iterator_search(i, h, k)); }
#ifdef __cplusplus
}
#endif
#endif

View File

@ -29,7 +29,11 @@ These third party libraries can be included into the application (firmware) prod
* `FreeBSD net80211`_ Copyright (c) 2004-2008 Sam Leffler, Errno Consulting and licensed under the BSD license.
* `argtable3`_ argument parsing library Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann and licensed under 3-clause BSD license.
* `argtable3`_ argument parsing library Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann and licensed under 3-clause BSD license. argtable3 also includes the following software components. For details, please see argtable3 :component_file:`LICENSE file<console/argtable3/LICENSE>`.
* C Hash Table library, Copyright (c) 2002, Christopher Clark and licensed under 3-clause BSD license.
* The Better String library, Copyright (c) 2014, Paul Hsieh and licensed under 3-clause BSD license.
* TCL library, Copyright the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties, and licensed under TCL/TK License.
* `linenoise`_ line editing library Copyright (c) 2010-2014 Salvatore Sanfilippo, Copyright (c) 2010-2013 Pieter Noordhuis, licensed under 2-clause BSD license.

View File

@ -112,6 +112,13 @@ sdmmc:
- Apache-2.0
- ISC
argtable3:
include:
- 'components/console/argtable3/'
allowed_licenses:
- BSD-3-Clause
- Apache-2.0
# files matching this section do not perform the check
# file patterns starting with ! are negated, meaning files matching them won't match the section.
ignore:

View File

@ -396,8 +396,6 @@ components/bt/host/bluedroid/stack/smp/smp_keys.c
components/bt/host/bluedroid/stack/smp/smp_l2c.c
components/bt/host/bluedroid/stack/smp/smp_main.c
components/bt/host/bluedroid/stack/smp/smp_utils.c
components/console/argtable3/argtable3.c
components/console/argtable3/argtable3.h
components/console/linenoise/linenoise.c
components/console/linenoise/linenoise.h
components/driver/include/driver/usb_serial_jtag.h