xref: /freebsd/contrib/bc/include/opt.h (revision a970610a3af63b3f4df5b69d91c6b4093a00ed8f)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
6*a970610aSStefan Eßer  * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7252884aeSStefan Eßer  *
8252884aeSStefan Eßer  * Redistribution and use in source and binary forms, with or without
9252884aeSStefan Eßer  * modification, are permitted provided that the following conditions are met:
10252884aeSStefan Eßer  *
11252884aeSStefan Eßer  * * Redistributions of source code must retain the above copyright notice, this
12252884aeSStefan Eßer  *   list of conditions and the following disclaimer.
13252884aeSStefan Eßer  *
14252884aeSStefan Eßer  * * Redistributions in binary form must reproduce the above copyright notice,
15252884aeSStefan Eßer  *   this list of conditions and the following disclaimer in the documentation
16252884aeSStefan Eßer  *   and/or other materials provided with the distribution.
17252884aeSStefan Eßer  *
18252884aeSStefan Eßer  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19252884aeSStefan Eßer  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20252884aeSStefan Eßer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21252884aeSStefan Eßer  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22252884aeSStefan Eßer  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23252884aeSStefan Eßer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24252884aeSStefan Eßer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25252884aeSStefan Eßer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26252884aeSStefan Eßer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27252884aeSStefan Eßer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28252884aeSStefan Eßer  * POSSIBILITY OF SUCH DAMAGE.
29252884aeSStefan Eßer  *
30252884aeSStefan Eßer  * *****************************************************************************
31252884aeSStefan Eßer  *
32252884aeSStefan Eßer  * Adapted from https://github.com/skeeto/optparse
33252884aeSStefan Eßer  *
34252884aeSStefan Eßer  * *****************************************************************************
35252884aeSStefan Eßer  *
36252884aeSStefan Eßer  * Definitions for getopt_long() replacement.
37252884aeSStefan Eßer  *
38252884aeSStefan Eßer  */
39252884aeSStefan Eßer 
40252884aeSStefan Eßer #ifndef BC_OPT_H
41252884aeSStefan Eßer #define BC_OPT_H
42252884aeSStefan Eßer 
43252884aeSStefan Eßer #include <stdbool.h>
4444d4804dSStefan Eßer #include <stdlib.h>
45252884aeSStefan Eßer 
4644d4804dSStefan Eßer /// The data required to parse command-line arguments.
4778bc019dSStefan Eßer typedef struct BcOpt
4878bc019dSStefan Eßer {
4944d4804dSStefan Eßer 	/// The array of arguments.
50252884aeSStefan Eßer 	char** argv;
5144d4804dSStefan Eßer 
5244d4804dSStefan Eßer 	/// The index of the current argument.
53252884aeSStefan Eßer 	size_t optind;
5444d4804dSStefan Eßer 
5544d4804dSStefan Eßer 	/// The actual parse option character.
56252884aeSStefan Eßer 	int optopt;
5744d4804dSStefan Eßer 
5844d4804dSStefan Eßer 	/// Where in the option we are for multi-character single-character options.
59252884aeSStefan Eßer 	int subopt;
6044d4804dSStefan Eßer 
6144d4804dSStefan Eßer 	/// The option argument.
62252884aeSStefan Eßer 	char* optarg;
6344d4804dSStefan Eßer 
64252884aeSStefan Eßer } BcOpt;
65252884aeSStefan Eßer 
6644d4804dSStefan Eßer /// The types of arguments. This is specially adapted for bc.
6778bc019dSStefan Eßer typedef enum BcOptType
6878bc019dSStefan Eßer {
6944d4804dSStefan Eßer 	/// No argument required.
70252884aeSStefan Eßer 	BC_OPT_NONE,
7144d4804dSStefan Eßer 
7244d4804dSStefan Eßer 	/// An argument required.
73252884aeSStefan Eßer 	BC_OPT_REQUIRED,
7444d4804dSStefan Eßer 
7544d4804dSStefan Eßer 	/// An option that is bc-only.
76252884aeSStefan Eßer 	BC_OPT_BC_ONLY,
7744d4804dSStefan Eßer 
7844d4804dSStefan Eßer 	/// An option that is bc-only that requires an argument.
7944d4804dSStefan Eßer 	BC_OPT_REQUIRED_BC_ONLY,
8044d4804dSStefan Eßer 
8144d4804dSStefan Eßer 	/// An option that is dc-only.
82252884aeSStefan Eßer 	BC_OPT_DC_ONLY,
8344d4804dSStefan Eßer 
84252884aeSStefan Eßer } BcOptType;
85252884aeSStefan Eßer 
8644d4804dSStefan Eßer /// A struct to hold const data for long options.
8778bc019dSStefan Eßer typedef struct BcOptLong
8878bc019dSStefan Eßer {
8944d4804dSStefan Eßer 	/// The name of the option.
90252884aeSStefan Eßer 	const char* name;
9144d4804dSStefan Eßer 
9244d4804dSStefan Eßer 	/// The type of the option.
93252884aeSStefan Eßer 	BcOptType type;
9444d4804dSStefan Eßer 
9544d4804dSStefan Eßer 	/// The character to return if the long option was parsed.
96252884aeSStefan Eßer 	int val;
9744d4804dSStefan Eßer 
98252884aeSStefan Eßer } BcOptLong;
99252884aeSStefan Eßer 
10044d4804dSStefan Eßer /**
10144d4804dSStefan Eßer  * Initialize data for parsing options.
10244d4804dSStefan Eßer  * @param o     The option data to initialize.
10344d4804dSStefan Eßer  * @param argv  The array of arguments.
10444d4804dSStefan Eßer  */
10578bc019dSStefan Eßer void
10678bc019dSStefan Eßer bc_opt_init(BcOpt* o, char** argv);
107252884aeSStefan Eßer 
10844d4804dSStefan Eßer /**
10944d4804dSStefan Eßer  * Parse an option. This returns a value the same way getopt() and getopt_long()
11044d4804dSStefan Eßer  * do, so it returns a character for the parsed option or -1 if done.
11144d4804dSStefan Eßer  * @param o         The option data.
11244d4804dSStefan Eßer  * @param longopts  The long options.
11344d4804dSStefan Eßer  * @return          A character for the parsed option, or -1 if done.
11444d4804dSStefan Eßer  */
11578bc019dSStefan Eßer int
11678bc019dSStefan Eßer bc_opt_parse(BcOpt* o, const BcOptLong* longopts);
117252884aeSStefan Eßer 
11844d4804dSStefan Eßer /**
11944d4804dSStefan Eßer  * Returns true if the option is `--` and not a long option.
12044d4804dSStefan Eßer  * @param a  The argument to parse.
12144d4804dSStefan Eßer  * @return   True if @a a is the `--` option, false otherwise.
12244d4804dSStefan Eßer  */
123252884aeSStefan Eßer #define BC_OPT_ISDASHDASH(a) \
124252884aeSStefan Eßer 	((a) != NULL && (a)[0] == '-' && (a)[1] == '-' && (a)[2] == '\0')
125252884aeSStefan Eßer 
12644d4804dSStefan Eßer /**
12744d4804dSStefan Eßer  * Returns true if the option is a short option.
12844d4804dSStefan Eßer  * @param a  The argument to parse.
12944d4804dSStefan Eßer  * @return   True if @a a is a short option, false otherwise.
13044d4804dSStefan Eßer  */
131252884aeSStefan Eßer #define BC_OPT_ISSHORTOPT(a) \
132252884aeSStefan Eßer 	((a) != NULL && (a)[0] == '-' && (a)[1] != '-' && (a)[1] != '\0')
133252884aeSStefan Eßer 
13444d4804dSStefan Eßer /**
13544d4804dSStefan Eßer  * Returns true if the option has `--` at the beginning, i.e., is a long option.
13644d4804dSStefan Eßer  * @param a  The argument to parse.
13744d4804dSStefan Eßer  * @return   True if @a a is a long option, false otherwise.
13844d4804dSStefan Eßer  */
139252884aeSStefan Eßer #define BC_OPT_ISLONGOPT(a) \
140252884aeSStefan Eßer 	((a) != NULL && (a)[0] == '-' && (a)[1] == '-' && (a)[2] != '\0')
141252884aeSStefan Eßer 
142252884aeSStefan Eßer #endif // BC_OPT_H
143