Branch data Line data Source code
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 <zephyr/sys/sys_getopt.h>
34 : : #include "getopt_common.h"
35 : :
36 : : #include <zephyr/logging/log.h>
37 : : LOG_MODULE_REGISTER(sys_getopt);
38 : :
39 : : #define BADCH ((int)'?')
40 : : #define BADARG ((int)':')
41 : : #define EMSG ""
42 : :
43 : 0 : void sys_getopt_init(void)
44 : : {
45 : 0 : struct sys_getopt_state *state;
46 : :
47 : 0 : state = sys_getopt_state_get();
48 : :
49 : 0 : state->opterr = 1;
50 : 0 : state->optind = 1;
51 : 0 : state->optopt = 0;
52 : 0 : state->optreset = 0;
53 : 0 : state->optarg = NULL;
54 : :
55 : 0 : state->place = ""; /* EMSG */
56 : :
57 : : #if CONFIG_GETOPT_LONG
58 : : state->nonopt_start = -1; /* first non option argument (for permute) */
59 : : state->nonopt_end = -1; /* first option after non options (for permute) */
60 : : #endif
61 : :
62 : 0 : sys_getopt_opterr = 1;
63 : 0 : sys_getopt_optind = 1;
64 : 0 : sys_getopt_optopt = 0;
65 : 0 : sys_getopt_optreset = 0;
66 : 0 : sys_getopt_optarg = NULL;
67 : 0 : }
68 : :
69 : : /*
70 : : * getopt --
71 : : * Parse argc/argv argument vector.
72 : : */
73 : 0 : int sys_getopt(int nargc, char *const nargv[], const char *ostr)
74 : : {
75 : 0 : struct sys_getopt_state *state;
76 : 0 : char *oli; /* option letter list index */
77 : :
78 : : /* get getopt state of the current thread */
79 : 0 : state = sys_getopt_state_get();
80 : :
81 [ # # # # ]: 0 : if (state->optreset || *state->place == 0) { /* update scanning pointer */
82 : 0 : state->optreset = 0;
83 : 0 : state->place = nargv[state->optind];
84 [ # # # # ]: 0 : if (state->optind >= nargc || *state->place++ != '-') {
85 : : /* Argument is absent or is not an option */
86 : 0 : state->place = EMSG;
87 : 0 : z_getopt_global_state_update(state);
88 : 0 : return -1;
89 : : }
90 : 0 : state->optopt = *state->place++;
91 [ # # # # ]: 0 : if (state->optopt == '-' && *state->place == 0) {
92 : : /* "--" => end of options */
93 : 0 : ++state->optind;
94 : 0 : state->place = EMSG;
95 : 0 : z_getopt_global_state_update(state);
96 : 0 : return -1;
97 : : }
98 [ # # ]: 0 : if (state->optopt == 0) {
99 : : /* Solitary '-', treat as a '-' option
100 : : * if the program (eg su) is looking for it.
101 : : */
102 : 0 : state->place = EMSG;
103 [ # # ]: 0 : if (strchr(ostr, '-') == NULL) {
104 : 0 : z_getopt_global_state_update(state);
105 : 0 : return -1;
106 : : }
107 : 0 : state->optopt = '-';
108 : : }
109 : : } else {
110 : 0 : state->optopt = *state->place++;
111 : : }
112 : :
113 : : /* See if option letter is one the caller wanted... */
114 : 0 : oli = strchr(ostr, state->optopt);
115 [ # # # # ]: 0 : if (state->optopt == ':' || oli == NULL) {
116 [ # # ]: 0 : if (*state->place == 0) {
117 : 0 : ++state->optind;
118 : : }
119 : 0 : if (state->opterr && *ostr != ':') {
120 : 0 : LOG_DBG("illegal option -- %c", state->optopt);
121 : : }
122 : 0 : z_getopt_global_state_update(state);
123 : 0 : return BADCH;
124 : : }
125 : :
126 : : /* Does this option need an argument? */
127 [ # # ]: 0 : if (oli[1] != ':') {
128 : : /* don't need argument */
129 : 0 : state->optarg = NULL;
130 [ # # ]: 0 : if (*state->place == 0) {
131 : 0 : ++state->optind;
132 : : }
133 : : } else {
134 : : /* Option-argument is either the rest of this argument or the
135 : : * entire next argument.
136 : : */
137 [ # # ]: 0 : if (*state->place) {
138 : 0 : state->optarg = state->place;
139 [ # # ]: 0 : } else if (nargc > ++state->optind) {
140 : 0 : state->optarg = nargv[state->optind];
141 : : } else {
142 : : /* option-argument absent */
143 : 0 : state->place = EMSG;
144 [ # # ]: 0 : if (*ostr == ':') {
145 : 0 : z_getopt_global_state_update(state);
146 : 0 : return BADARG;
147 : : }
148 : 0 : if (state->opterr) {
149 : 0 : LOG_DBG("option requires an argument -- %c", state->optopt);
150 : : }
151 : 0 : z_getopt_global_state_update(state);
152 : 0 : return BADCH;
153 : : }
154 : 0 : state->place = EMSG;
155 : 0 : ++state->optind;
156 : : }
157 : 0 : z_getopt_global_state_update(state);
158 : 0 : return state->optopt; /* return option letter */
159 : : }
|