lib: add freebsd getopt library
This library is going to be used by the shell module. Some shell users are not satisfied with subcommands alone and need to use the options for commands as well. Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
This commit is contained in:
parent
72dd5a5c68
commit
ddb07f57ec
7 changed files with 261 additions and 0 deletions
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
add_subdirectory_ifdef(CONFIG_FNMATCH fnmatch)
|
||||
add_subdirectory_ifdef(CONFIG_GETOPT getopt)
|
||||
|
|
|
@ -6,4 +6,6 @@ menu "Util libraries"
|
|||
|
||||
source "lib/util/fnmatch/Kconfig"
|
||||
|
||||
source "lib/util/getopt/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
14
lib/util/getopt/CMakeLists.txt
Normal file
14
lib/util/getopt/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Copyright (c) 2021 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
zephyr_include_directories_ifdef(
|
||||
CONFIG_GETOPT
|
||||
.
|
||||
)
|
||||
|
||||
zephyr_sources_ifdef(
|
||||
CONFIG_GETOPT
|
||||
getopt.c
|
||||
)
|
7
lib/util/getopt/Kconfig
Normal file
7
lib/util/getopt/Kconfig
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Copyright (c) 2021 Nordic Semiconductor
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config GETOPT
|
||||
bool "GetOpt Support"
|
||||
help
|
||||
This option enables the getopt library
|
58
lib/util/getopt/README
Normal file
58
lib/util/getopt/README
Normal file
|
@ -0,0 +1,58 @@
|
|||
[GetOpt]
|
||||
#####################
|
||||
|
||||
Origin:
|
||||
[Lattera FreeBSD]
|
||||
[https://github.com/lattera/freebsd/blob/master/lib/libc/stdlib/getopt.c]
|
||||
|
||||
Status:
|
||||
[So far Zephyr samples were using getopt implementation from: argtable3.c.]
|
||||
|
||||
Purpose:
|
||||
[Shell users would like to parse options passed to the command handler.]
|
||||
|
||||
Description:
|
||||
[This library is going to be used by the shell module. Some shell users
|
||||
are not satisfied with subcommands alone and need to use the options for
|
||||
commands as well. A library is needed that allows the developer to parse
|
||||
the arguments string, looking for supported options. Typically, this task
|
||||
is accomplished by the getopt function.
|
||||
|
||||
For this purpose I decided to port the getopt library available
|
||||
in the FreeBSD project. I had to modify it so that it could be used
|
||||
by all instances of the shell at the same time.
|
||||
|
||||
Originally this function was using global variables which were defining
|
||||
its state. In my implementation I put those variables in a structure
|
||||
and a pointer to that structure is passed as an additional parameter
|
||||
to getopt function. In proposed implementation each shell backend has its
|
||||
own getopt function state structure which it uses.
|
||||
|
||||
This module is intended to be used inside the shell command handler
|
||||
by the abstraction layer "SHELL_GETOPT". For example:
|
||||
while ((char c = shell_getopt(shell, argc, argv, "abhc:")) != -1) {
|
||||
/* some code */
|
||||
}
|
||||
]
|
||||
|
||||
Dependencies:
|
||||
[This package does not depend on any other component.
|
||||
|
||||
Zephyr project will only need this component if the user configures a shell
|
||||
module: SHELL_GETOPT.]
|
||||
|
||||
URL:
|
||||
[https://github.com/lattera/freebsd]
|
||||
|
||||
commit:
|
||||
[324e4c082c14aebf00f8dbee0fb7ad285393756a]
|
||||
|
||||
Maintained-by:
|
||||
[External]
|
||||
|
||||
License:
|
||||
[BSD 3-Clause "New" or "Revised" License]
|
||||
|
||||
License Link:
|
||||
[BSD 3-Clause used in getopt: https://spdx.org/licenses/BSD-3-Clause.html]
|
||||
[Project license: https://github.com/lattera/freebsd/blob/master/COPYRIGHT]
|
138
lib/util/getopt/getopt.c
Normal file
138
lib/util/getopt/getopt.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 1987, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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 <string.h>
|
||||
#include "getopt.h"
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(getopt);
|
||||
|
||||
#define BADCH ((int)'?')
|
||||
#define BADARG ((int)':')
|
||||
#define EMSG ""
|
||||
|
||||
void getopt_init(struct getopt_state *state)
|
||||
{
|
||||
state->opterr = 1;
|
||||
state->optind = 1;
|
||||
state->optopt = 0;
|
||||
state->optreset = 0;
|
||||
state->optarg = NULL;
|
||||
|
||||
state->place = ""; /* EMSG */
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt(state, nargc, nargv, ostr)
|
||||
struct getopt_state *state;
|
||||
int nargc;
|
||||
char *const nargv[];
|
||||
const char *ostr;
|
||||
{
|
||||
char *oli; /* option letter list index */
|
||||
|
||||
if (state->optreset || *state->place == 0) { /* update scanning pointer */
|
||||
state->optreset = 0;
|
||||
state->place = nargv[state->optind];
|
||||
if (state->optind >= nargc || *state->place++ != '-') {
|
||||
/* Argument is absent or is not an option */
|
||||
state->place = EMSG;
|
||||
return -1;
|
||||
}
|
||||
state->optopt = *state->place++;
|
||||
if (state->optopt == '-' && *state->place == 0) {
|
||||
/* "--" => end of options */
|
||||
++state->optind;
|
||||
state->place = EMSG;
|
||||
return -1;
|
||||
}
|
||||
if (state->optopt == 0) {
|
||||
/* Solitary '-', treat as a '-' option
|
||||
* if the program (eg su) is looking for it.
|
||||
*/
|
||||
state->place = EMSG;
|
||||
if (strchr(ostr, '-') == NULL) {
|
||||
return -1;
|
||||
}
|
||||
state->optopt = '-';
|
||||
}
|
||||
} else {
|
||||
state->optopt = *state->place++;
|
||||
}
|
||||
|
||||
/* See if option letter is one the caller wanted... */
|
||||
oli = strchr(ostr, state->optopt);
|
||||
if (state->optopt == ':' || oli == NULL) {
|
||||
if (*state->place == 0) {
|
||||
++state->optind;
|
||||
}
|
||||
if (state->opterr && *ostr != ':') {
|
||||
LOG_ERR("illegal option -- %c", state->optopt);
|
||||
}
|
||||
return BADCH;
|
||||
}
|
||||
|
||||
/* Does this option need an argument? */
|
||||
if (oli[1] != ':') {
|
||||
/* don't need argument */
|
||||
state->optarg = NULL;
|
||||
if (*state->place == 0) {
|
||||
++state->optind;
|
||||
}
|
||||
} else {
|
||||
/* Option-argument is either the rest of this argument or the
|
||||
* entire next argument.
|
||||
*/
|
||||
if (*state->place) {
|
||||
state->optarg = state->place;
|
||||
} else if (nargc > ++state->optind) {
|
||||
state->optarg = nargv[state->optind];
|
||||
} else {
|
||||
/* option-argument absent */
|
||||
state->place = EMSG;
|
||||
if (*ostr == ':') {
|
||||
return BADARG;
|
||||
}
|
||||
if (state->opterr) {
|
||||
LOG_ERR("option requires an argument -- %c",
|
||||
state->optopt);
|
||||
}
|
||||
return BADCH;
|
||||
}
|
||||
state->place = EMSG;
|
||||
++state->optind;
|
||||
}
|
||||
return state->optopt; /* return option letter */
|
||||
}
|
41
lib/util/getopt/getopt.h
Normal file
41
lib/util/getopt/getopt.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _GETOPT_H__
|
||||
#define _GETOPT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
struct getopt_state {
|
||||
int opterr; /* if error message should be printed */
|
||||
int optind; /* index into parent argv vector */
|
||||
int optopt; /* character checked for validity */
|
||||
int optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
|
||||
char *place; /* option letter processing */
|
||||
};
|
||||
|
||||
/* Function intializes getopt_state structure */
|
||||
void getopt_init(struct getopt_state *state);
|
||||
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int getopt(struct getopt_state *const state, int nargc,
|
||||
char *const nargv[], const char *ostr);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GETOPT_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue