mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/upgrade_argtable_3_2_2_files_v4.4' into 'release/v4.4'
console: argtable3: upgrade to v3.2.2 (v4.4) See merge request espressif/esp-idf!21015
This commit is contained in:
commit
2d9d9e52bf
@ -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()
|
||||
|
@ -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.
|
||||
|
285
components/console/argtable3/arg_cmd.c
Normal file
285
components/console/argtable3/arg_cmd.c
Normal 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;
|
||||
}
|
575
components/console/argtable3/arg_date.c
Normal file
575
components/console/argtable3/arg_date.c
Normal 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);
|
||||
}
|
164
components/console/argtable3/arg_dbl.c
Normal file
164
components/console/argtable3/arg_dbl.c
Normal 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;
|
||||
}
|
344
components/console/argtable3/arg_dstr.c
Normal file
344
components/console/argtable3/arg_dstr.c
Normal 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
|
135
components/console/argtable3/arg_end.c
Normal file
135
components/console/argtable3/arg_end.c
Normal 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);
|
||||
}
|
213
components/console/argtable3/arg_file.c
Normal file
213
components/console/argtable3/arg_file.c
Normal 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;
|
||||
}
|
428
components/console/argtable3/arg_hashtable.c
Normal file
428
components/console/argtable3/arg_hashtable.c
Normal 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;
|
||||
}
|
294
components/console/argtable3/arg_int.c
Normal file
294
components/console/argtable3/arg_int.c
Normal 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;
|
||||
}
|
124
components/console/argtable3/arg_lit.c
Normal file
124
components/console/argtable3/arg_lit.c
Normal 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;
|
||||
}
|
64
components/console/argtable3/arg_rem.c
Normal file
64
components/console/argtable3/arg_rem.c
Normal 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;
|
||||
}
|
1014
components/console/argtable3/arg_rex.c
Normal file
1014
components/console/argtable3/arg_rex.c
Normal file
File diff suppressed because it is too large
Load Diff
151
components/console/argtable3/arg_str.c
Normal file
151
components/console/argtable3/arg_str.c
Normal 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;
|
||||
}
|
183
components/console/argtable3/arg_utils.c
Normal file
183
components/console/argtable3/arg_utils.c
Normal 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
@ -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
|
||||
}
|
||||
|
245
components/console/argtable3/argtable3_private.h
Normal file
245
components/console/argtable3/argtable3_private.h
Normal 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
|
@ -1,4 +1,2 @@
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
COMPONENT_SRCDIRS := linenoise argtable3 .
|
||||
|
||||
argtable3/argtable3.o: CFLAGS += -Wno-clobbered
|
||||
|
@ -29,7 +29,11 @@ These third party libraries can be included into the application (firmware) prod
|
||||
|
||||
* `JSMN`_ JSON Parser (components/jsmn) Copyright (c) 2010 Serge A. Zaitsev and licensed under the MIT 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.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user