Improve diagnostics of lls_check_arg_count().
[lopsub.git] / lopsub-internal.h
1 /*
2  * Copyright (C) 2016 Andre Noll <maan@tuebingen.mpg.de>
3  *
4  * Licensed under the LGPL v3, see http://www.gnu.org/licenses/lgpl-3.0.html
5  */
6
7 #include <inttypes.h>
8
9 #define LLS_ABI_VERSION 2
10
11 /*
12  * Concat "lls_abi_version" and the ABI version number to produce the name of a
13  * variable. To concat the *expansion* of the macro arguments, we have to use
14  * two levels of macros since otherwise the arguments are not macro-expanded
15  * first.
16  */
17 #define LLS_CONCAT_EXPAND(_prefix, _suffix) LLS_CONCAT(_prefix, _suffix)
18 #define LLS_CONCAT(_prefix, _suffix) _prefix ## _suffix
19 #define LLS_ABI_VERSION_VAR LLS_CONCAT_EXPAND(lls_abi_version, LLS_ABI_VERSION)
20
21 /*
22  * Declare the variable. It is defined in lopsub.c, which is part of the
23  * library. The single mission of this variable is to cause an error at link
24  * time on ABI version mismatches. The actual value of the variable is
25  * irrelevant. When the lopsubgen utility translates a suite into a .c file,
26  * the generated C code references this variable, using the *lopsubgen* ABI
27  * version for the reference. Therefore, if the lopsubgen ABI version differs
28  * from the ABI version of the library, the symbol can not be resolved,
29  * resulting in a link error.
30  */
31 extern const unsigned LLS_ABI_VERSION_VAR;
32
33 /*
34  * Options may have an optional or mandatory argument.
35  *
36  * The lobsubgen command initializes the ->arg_info field of each lls_option
37  * structure from the corresponding line of the .suite file.
38  *
39  * See also: ->arg_info of struct lls_option.
40  */
41 enum lls_arg_info {
42         LLS_NO_ARGUMENT, /* Option does not take an argument. */
43         LLS_REQUIRED_ARGUMENT, /* An argument must be given. */
44         LLS_OPTIONAL_ARGUMENT, /* Option takes an optional argument. */
45 };
46
47 /*
48  * In addition to the argument type, there is a set of flags associated with
49  * each option. All but the LLS_IGNORED flag correspond directly to the
50  * possible values of the flag directive in the suite file.
51  */
52 enum lls_option_flag {
53         /* Store each given argument (rather than only the last). */
54         LLS_MULTIPLE = 1,
55         /* It's an error if the option is not given. */
56         LLS_REQUIRED = 2,
57         /* Whether a default value was specified in the suite file. */
58         LLS_HAS_DEFAULT = 4,
59         /* For help text not related to any particular option. */
60         LLS_IGNORED = 8,
61 };
62
63 /*
64  * Ignored if arg_info is LLS_NO_ARGUMENT. A value of zero means no argument.
65  * We don't need an identifier like LLS_NONE though, because we can test the
66  * arg_info field to tell whether an argument can be supplied.
67  *
68  * See also: union lls_val.
69  */
70 enum lls_arg_type {
71         /* Option takes a string argument. */
72         LLS_STRING = 1,
73         /* Signed 32 bit integer. */
74         LLS_INT32,
75         /* Unsigned 32 bit integer. */
76         LLS_UINT32,
77         /* Signed 64 bit integer. */
78         LLS_INT64,
79         /* Unsigned 64 bit integer. */
80         LLS_UINT64,
81 };
82
83 /*
84  * Stores the argument to an option.
85  *
86  * The default value of an option, the set of possible values for an option and
87  * the actually given value are all stored in an instance of this union.
88  *
89  * To determine the relevant alternative of the union, both the ->arg_type and
90  * the ->values field of the corresponding struct lls_option are
91  * important. For the values array itself, ->arg_type always determines the
92  * alternative of each element in the array. For other objects the following
93  * rule applies. If ->values is not given, ->arg_type determines the
94  * alternative for both ->default_val and lls_opt_result->value. On the other
95  * hand, if ->values is given, the ->uint32_val alternative is the index into
96  * the ->values array that indicates which of the possible values is the
97  * default value (for ->default_val) or was given in the arguments to
98  * lls_parse() (lls_opt_result).
99  */
100 union lls_val {
101         char *string_val; /* LLS_STRING */
102         int32_t int32_val; /* LLS_INT32 */
103         uint32_t uint32_val; /* LLS_UINT32 */
104         int64_t int64_val; /* LLS_INT64 */
105         uint64_t uint64_val; /* LLS_UINT64 */
106 };
107
108 /*
109  * Describes one option of one command of a suite.
110  *
111  * For each option of every command in the .suite file, lopsubgen
112  * generates one structure of this type.
113  */
114 struct lls_option {
115         /* The long name (short-only options are not supported). */
116         const char * const name;
117         /* Optional one-character variant. */
118         const char short_opt;
119         /* Mandatory one-line summary. */
120         const char * const summary;
121         /* Whether the option takes an argument, and if it is mandatory. */
122         const enum lls_arg_info arg_info;
123         /* Which alternative of the lls_val union is chosen. */
124         const enum lls_arg_type arg_type;
125         /* Description of the type of values (used for help output). */
126         const char * const typestr;
127         /* See enum lls_option_flag. */
128         const unsigned flags;
129         /* If not given, integer values default to 0, strings to NULL. */
130         const union lls_val default_val;
131         /* Optional multi-line help text. */
132         const char * const help;
133         /* If this is not NULL, only the given values are allowed. */
134         const union lls_val * const values;
135 };
136
137 /* Describes a command of a suite. */
138 struct lls_command {
139         /* Only identifiers are allowed as command names. */
140         const char * const name;
141         /* One line of text, shown in all variants of help text. */
142         const char * const purpose;
143         /* Multi line text in long help and man page. */
144         const char * const description;
145         /* How non-option arguments should be called in the synopsis. */
146         const char * const non_opts_name;
147         /* Optional, will be computed if not given. */
148         const char * const synopsis;
149         /* Array of options for this command. */
150         const struct lls_option * const options;
151         /* Closing remarks after the option list in long help and man page. */
152         const char * const closing;
153         /* Initialized to com_NAME_user_data with NAME being the command name. */
154         const void * const user_data;
155         /* Contains the array size of ->options. */
156         const int num_options;
157 };
158
159 struct lls_suite {
160         const char * const name;
161         const char * const caption;
162         const struct lls_command * const commands;
163         const int num_subcommands;
164 };
165
166 struct lls_opt_result {
167         unsigned given;
168         /* for multiple options, one value for each time the option was given */
169         union lls_val *value;
170 };
171
172 struct lls_parse_result {
173         char **inputs; /* non-options, non-args */
174         unsigned num_inputs;
175         struct lls_opt_result *opt_result; /* one per option */
176 };
177
178 /*
179  * Most library functions return a negative error code on failure. The
180  * LLS_ERRORS macro expands to a list of all possible errors, optionally
181  * including the text of each error code. The LLS_ERROR macro (without the
182  * trailing S) controls how each error is expanded.
183  */
184 #define LLS_ERRORS \
185         LLS_ERROR(SUCCESS, "success") \
186         LLS_ERROR(NOMEM, "allocation failure") \
187         LLS_ERROR(BAD_OPTION, "option not recognized") \
188         LLS_ERROR(AMBIG_OPTION, "option is ambiguous") \
189         LLS_ERROR(OPT_MANDATORY, "mandatory option not given") \
190         LLS_ERROR(ARG_GIVEN, "argument given to non-arg option") \
191         LLS_ERROR(NO_ARG_GIVEN, "argument required but not given") \
192         LLS_ERROR(TRAILING_BACKSLASH, "unexpected trailing backslash") \
193         LLS_ERROR(UNMATCHED_QUOTE, "unmatched quote character") \
194         LLS_ERROR(TRAILING_GARBAGE, "garbage at end of line or argument") \
195         LLS_ERROR(YY_SCAN, "error setting up lex input buffer") \
196         LLS_ERROR(YY_LEX, "yylex() failed") \
197         LLS_ERROR(BAD_SUBCMD, "invalid subcommand") \
198         LLS_ERROR(AMBIG_SUBCMD, "ambiguous subcommand") \
199         LLS_ERROR(BAD_ARG_COUNT, "invalid number of arguments") \
200         LLS_ERROR(OVERFLOW, "value too large") \
201         LLS_ERROR(NO_DIGITS, "no digits found in string") \
202         LLS_ERROR(ENUM, "invalid value for enum option") \
203
204 /*
205  * Given an identifier and a string literal, forget the string, and prefix the
206  * identifier with E_LLS_ to produce an identifier for an error code like
207  * E_LLS_OVERFLOW. Finally, append a comma. While this definition of LLS_ERROR
208  * is active, LLS_ERRORS expands to a comma-separated list of error codes. See
209  * enum lls_errors below.
210  */
211 #define LLS_ERROR(_n, _s) E_LLS_ ## _n,
212
213 /*
214  * Declare the enumeration of all error codes as identifiers like like
215  * E_LLS_OVERFLOW. Also, the total number of error codes is declared as
216  * NUM_LLS_ERRORS.
217  */
218 enum lls_errors {LLS_ERRORS NUM_LLS_ERRORS};
219 #undef LLS_ERROR