Skip to content

Commit ddb07f5

Browse files
Jakub Rzeszutkonashif
authored andcommitted
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 <[email protected]>
1 parent 72dd5a5 commit ddb07f5

File tree

7 files changed

+261
-0
lines changed

7 files changed

+261
-0
lines changed

lib/util/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
add_subdirectory_ifdef(CONFIG_FNMATCH fnmatch)
4+
add_subdirectory_ifdef(CONFIG_GETOPT getopt)

lib/util/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ menu "Util libraries"
66

77
source "lib/util/fnmatch/Kconfig"
88

9+
source "lib/util/getopt/Kconfig"
10+
911
endmenu

lib/util/getopt/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright (c) 2021 Nordic Semiconductor
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
6+
zephyr_include_directories_ifdef(
7+
CONFIG_GETOPT
8+
.
9+
)
10+
11+
zephyr_sources_ifdef(
12+
CONFIG_GETOPT
13+
getopt.c
14+
)

lib/util/getopt/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) 2021 Nordic Semiconductor
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config GETOPT
5+
bool "GetOpt Support"
6+
help
7+
This option enables the getopt library

lib/util/getopt/README

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[GetOpt]
2+
#####################
3+
4+
Origin:
5+
[Lattera FreeBSD]
6+
[https://github.com/lattera/freebsd/blob/master/lib/libc/stdlib/getopt.c]
7+
8+
Status:
9+
[So far Zephyr samples were using getopt implementation from: argtable3.c.]
10+
11+
Purpose:
12+
[Shell users would like to parse options passed to the command handler.]
13+
14+
Description:
15+
[This library is going to be used by the shell module. Some shell users
16+
are not satisfied with subcommands alone and need to use the options for
17+
commands as well. A library is needed that allows the developer to parse
18+
the arguments string, looking for supported options. Typically, this task
19+
is accomplished by the getopt function.
20+
21+
For this purpose I decided to port the getopt library available
22+
in the FreeBSD project. I had to modify it so that it could be used
23+
by all instances of the shell at the same time.
24+
25+
Originally this function was using global variables which were defining
26+
its state. In my implementation I put those variables in a structure
27+
and a pointer to that structure is passed as an additional parameter
28+
to getopt function. In proposed implementation each shell backend has its
29+
own getopt function state structure which it uses.
30+
31+
This module is intended to be used inside the shell command handler
32+
by the abstraction layer "SHELL_GETOPT". For example:
33+
while ((char c = shell_getopt(shell, argc, argv, "abhc:")) != -1) {
34+
/* some code */
35+
}
36+
]
37+
38+
Dependencies:
39+
[This package does not depend on any other component.
40+
41+
Zephyr project will only need this component if the user configures a shell
42+
module: SHELL_GETOPT.]
43+
44+
URL:
45+
[https://github.com/lattera/freebsd]
46+
47+
commit:
48+
[324e4c082c14aebf00f8dbee0fb7ad285393756a]
49+
50+
Maintained-by:
51+
[External]
52+
53+
License:
54+
[BSD 3-Clause "New" or "Revised" License]
55+
56+
License Link:
57+
[BSD 3-Clause used in getopt: https://spdx.org/licenses/BSD-3-Clause.html]
58+
[Project license: https://github.com/lattera/freebsd/blob/master/COPYRIGHT]

lib/util/getopt/getopt.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */
2+
/* SPDX-License-Identifier: BSD-3-Clause */
3+
/*
4+
* Copyright (c) 1987, 1993, 1994
5+
* The Regents of the University of California. All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions
9+
* are met:
10+
* 1. Redistributions of source code must retain the above copyright
11+
* notice, this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
* 3. Neither the name of the University nor the names of its contributors
16+
* may be used to endorse or promote products derived from this software
17+
* without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29+
* SUCH DAMAGE.
30+
*/
31+
32+
#include <string.h>
33+
#include "getopt.h"
34+
35+
#include <logging/log.h>
36+
LOG_MODULE_REGISTER(getopt);
37+
38+
#define BADCH ((int)'?')
39+
#define BADARG ((int)':')
40+
#define EMSG ""
41+
42+
void getopt_init(struct getopt_state *state)
43+
{
44+
state->opterr = 1;
45+
state->optind = 1;
46+
state->optopt = 0;
47+
state->optreset = 0;
48+
state->optarg = NULL;
49+
50+
state->place = ""; /* EMSG */
51+
}
52+
53+
/*
54+
* getopt --
55+
* Parse argc/argv argument vector.
56+
*/
57+
int
58+
getopt(state, nargc, nargv, ostr)
59+
struct getopt_state *state;
60+
int nargc;
61+
char *const nargv[];
62+
const char *ostr;
63+
{
64+
char *oli; /* option letter list index */
65+
66+
if (state->optreset || *state->place == 0) { /* update scanning pointer */
67+
state->optreset = 0;
68+
state->place = nargv[state->optind];
69+
if (state->optind >= nargc || *state->place++ != '-') {
70+
/* Argument is absent or is not an option */
71+
state->place = EMSG;
72+
return -1;
73+
}
74+
state->optopt = *state->place++;
75+
if (state->optopt == '-' && *state->place == 0) {
76+
/* "--" => end of options */
77+
++state->optind;
78+
state->place = EMSG;
79+
return -1;
80+
}
81+
if (state->optopt == 0) {
82+
/* Solitary '-', treat as a '-' option
83+
* if the program (eg su) is looking for it.
84+
*/
85+
state->place = EMSG;
86+
if (strchr(ostr, '-') == NULL) {
87+
return -1;
88+
}
89+
state->optopt = '-';
90+
}
91+
} else {
92+
state->optopt = *state->place++;
93+
}
94+
95+
/* See if option letter is one the caller wanted... */
96+
oli = strchr(ostr, state->optopt);
97+
if (state->optopt == ':' || oli == NULL) {
98+
if (*state->place == 0) {
99+
++state->optind;
100+
}
101+
if (state->opterr && *ostr != ':') {
102+
LOG_ERR("illegal option -- %c", state->optopt);
103+
}
104+
return BADCH;
105+
}
106+
107+
/* Does this option need an argument? */
108+
if (oli[1] != ':') {
109+
/* don't need argument */
110+
state->optarg = NULL;
111+
if (*state->place == 0) {
112+
++state->optind;
113+
}
114+
} else {
115+
/* Option-argument is either the rest of this argument or the
116+
* entire next argument.
117+
*/
118+
if (*state->place) {
119+
state->optarg = state->place;
120+
} else if (nargc > ++state->optind) {
121+
state->optarg = nargv[state->optind];
122+
} else {
123+
/* option-argument absent */
124+
state->place = EMSG;
125+
if (*ostr == ':') {
126+
return BADARG;
127+
}
128+
if (state->opterr) {
129+
LOG_ERR("option requires an argument -- %c",
130+
state->optopt);
131+
}
132+
return BADCH;
133+
}
134+
state->place = EMSG;
135+
++state->optind;
136+
}
137+
return state->optopt; /* return option letter */
138+
}

lib/util/getopt/getopt.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2021 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef _GETOPT_H__
8+
#define _GETOPT_H__
9+
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
#include <zephyr.h>
15+
16+
struct getopt_state {
17+
int opterr; /* if error message should be printed */
18+
int optind; /* index into parent argv vector */
19+
int optopt; /* character checked for validity */
20+
int optreset; /* reset getopt */
21+
char *optarg; /* argument associated with option */
22+
23+
char *place; /* option letter processing */
24+
};
25+
26+
/* Function intializes getopt_state structure */
27+
void getopt_init(struct getopt_state *state);
28+
29+
/*
30+
* getopt --
31+
* Parse argc/argv argument vector.
32+
*/
33+
int getopt(struct getopt_state *const state, int nargc,
34+
char *const nargv[], const char *ostr);
35+
36+
37+
#ifdef __cplusplus
38+
}
39+
#endif
40+
41+
#endif /* _GETOPT_H__ */

0 commit comments

Comments
 (0)