build: Compress man pages.
[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