2 * Written 2016 by Andre Noll <maan@tuebingen.mpg.de>
4 * Public domain, no copyright claims.
10 #include <sys/types.h>
16 #include "lopsubex.lsg.h"
18 typedef int (*example_handler_t
)(struct lls_parse_result
*);
20 struct local_command_info
{
21 example_handler_t handler
;
24 #define EXPORT_CMD(_cmd) \
25 const struct local_command_info lsg_lopsubex_com_ ## _cmd ## _user_data = { \
26 .handler = com_ ## _cmd \
29 #define CMD_PTR(_cmd) lls_cmd(LSG_LOPSUBEX_CMD_ ## _cmd, lopsubex_suite)
30 #define OPT_PTR(_cmd, _opt) \
31 lls_opt(LSG_LOPSUBEX_ ## _cmd ## _OPT_ ## _opt, CMD_PTR(_cmd))
33 #define OPT_RESULT(_cmd, _opt, _lpr) \
34 lls_opt_result(LSG_LOPSUBEX_ ## _cmd ## _OPT_ ## _opt, _lpr)
36 static void print_available_commands(void)
38 const struct lls_command
*cmd
;
40 printf("Available subcommands:\n");
41 for (i
= 1; (cmd
= lls_cmd(i
, lopsubex_suite
)); i
++) {
42 const char *name
= lls_command_name(cmd
);
43 const char *purpose
= lls_purpose(cmd
);
44 printf("%-20s%s\n", name
, purpose
);
48 static const struct lls_command
*lookup_subcmd_or_die(const char *str
)
51 int ret
= lls_lookup_subcmd(str
, lopsubex_suite
, &errctx
);
55 printf("%s: ", errctx
);
56 printf("%s\n", lls_strerror(-ret
));
57 print_available_commands();
60 return lls_cmd(ret
, lopsubex_suite
);
63 static int com_flag(struct lls_parse_result
*lpr
)
65 const struct lls_opt_result
*r
= OPT_RESULT(FLAG
, SIMPLE
, lpr
);
67 /* flag count is obtained with lls_given() */
68 printf("--simple is given %u times\n", lls_opt_given(r
));
70 r
= OPT_RESULT(FLAG
, SQRT4
, lpr
);
71 printf("--sqrt4 (aka -2) is given %u times\n", lls_opt_given(r
));
76 static int com_int_param(struct lls_parse_result
*lpr
)
78 const struct lls_opt_result
*r_r
= OPT_RESULT(INT_PARAM
, ROTATE
, lpr
);
79 printf("rotating by %d degrees\n", lls_int32_val(0, r_r
));
84 static int com_multiple(struct lls_parse_result
*lpr
)
86 const struct lls_opt_result
*r
;
90 r
= OPT_RESULT(MULTIPLE
, VERBOSE
, lpr
);
91 printf("--verbose is given %d times\n", lls_opt_given(r
));
92 r
= OPT_RESULT(MULTIPLE
, INPUT_FILE
, lpr
);
93 given
= lls_opt_given(r
);
94 printf("--input-file is given %d times\n", lls_opt_given(r
));
95 for (i
= 0; i
< given
; i
++)
96 printf("--input-file val #%d: %s\n", i
, lls_string_val(i
, r
));
97 r
= OPT_RESULT(MULTIPLE
, OUTPUT_FILE
, lpr
);
98 printf("--output-file is given %d times\n", lls_opt_given(r
));
99 printf("--output-file val: %s\n", lls_string_val(0, r
));
104 static int com_custom_synopsis(struct lls_parse_result
*lpr
)
106 const struct lls_command
*cmd
= CMD_PTR(CUSTOM_SYNOPSIS
);
107 char *long_help
= lls_long_help(cmd
);
108 printf("%s\n", long_help
);
112 EXPORT_CMD(custom_synopsis
)
114 static void fruit_salad(struct lls_parse_result
*lpr
)
116 const struct lls_opt_result
*r_f
= OPT_RESULT(SERIALIZE
, FRUIT
, lpr
);
117 const struct lls_opt_result
*r_a
= OPT_RESULT(SERIALIZE
, AMOUNT
, lpr
);
118 const struct lls_opt_result
*r_s
= OPT_RESULT(SERIALIZE
, SUGAR
, lpr
);
119 const struct lls_opt_result
*r_c
= OPT_RESULT(SERIALIZE
, CONTAINER
, lpr
);
122 printf("Put %d gramms of fruits (", lls_uint32_val(0, r_a
));
123 num_vals
= lls_opt_given(r_f
) > 0? lls_opt_given(r_f
) : 1;
124 for (i
= 0; i
< num_vals
; i
++)
125 printf("%s%s", lls_string_val(i
, r_f
),
126 i
== num_vals
- 1? "" : ", ");
127 printf(") in a %s, ", lls_string_val(0, r_c
));
128 if (lls_opt_given(r_s
))
129 printf("add sugar, ");
130 printf("and serve cold.\n");
133 static int com_serialize(struct lls_parse_result
*lpr
)
135 const struct lls_command
*cmd
= CMD_PTR(SERIALIZE
);
139 struct lls_parse_result
*dlpr
; /* deserialized */
142 ret
= lls_serialize_parse_result(lpr
, cmd
, &buf
, &nbytes
);
145 printf("serialized parse result into %zu byte buffer\n", nbytes
);
146 ret
= lls_deserialize_parse_result(buf
, cmd
, &dlpr
);
150 printf("successfully deserialized parse result\n");
152 lls_free_parse_result(dlpr
, cmd
);
155 EXPORT_CMD(serialize
)
157 static int com_non_ascii(struct lls_parse_result
*lpr
)
159 const struct lls_opt_result
*r_c
= OPT_RESULT(NON_ASCII
, CITY
, lpr
);
160 const char *city
= lls_string_val(0, r_c
);
162 if (strcmp(city
, "Göttingen"))
163 printf("I don't know anything about %s\n", city
);
165 printf("One of the most famous citicens of Göttingen was\n"
166 "the mathematician Carl Friedrich Gauß.\n");
169 EXPORT_CMD(non_ascii
)
171 static int com_enum(struct lls_parse_result
*lpr
)
173 const struct lls_option
*o_c
= OPT_PTR(ENUM
, COLOR
);
174 const struct lls_opt_result
*r_c
= OPT_RESULT(ENUM
, COLOR
, lpr
);
175 bool c_given
= lls_opt_given(r_c
);
179 num
= lls_uint32_val(0, r_c
);
180 color
= lls_enum_string_val(num
, o_c
);
181 printf("%s value: #%d: %s\n", c_given
? "good" : "default", num
, color
);
182 printf("Band names containing '%s'\n", color
);
185 printf("Red Snapper\n");
186 printf("Red Lorry Yellow Lorry\n");
189 printf("Green Day\n");
190 printf("Green Jelly\n");
193 printf("Blue Cheer\n");
194 printf("Blue Öyster Cult\n");
197 printf("Nothing appropriate\n");
200 printf("Available colors:\n");
201 for (num
= 0; num
< LSG_NUM_LOPSUBEX_ENUM_COLOR_VALUES
; num
++)
202 printf("color #%d: %s\n", num
,
203 lls_enum_string_val(num
, o_c
));
209 static int com_quotes(struct lls_parse_result
*lpr
)
211 const struct lls_opt_result
*r_s
= OPT_RESULT(QUOTES
, CHARS
, lpr
);
212 const char *val
= lls_string_val(0, r_s
);
214 printf("Special characters: %s\n", val
);
219 static int com_help(struct lls_parse_result
*lpr
)
221 const struct lls_command
*cmd
= CMD_PTR(HELP
);
222 const struct lls_opt_result
*r_l
= OPT_RESULT(HELP
, LONG
, lpr
);
226 ret
= lls_check_arg_count(lpr
, 0, 1, NULL
);
229 if (lls_num_inputs(lpr
) > 0)
230 cmd
= lookup_subcmd_or_die(lls_input(0, lpr
));
231 if (lls_opt_given(r_l
))
232 txt
= lls_long_help(cmd
);
234 txt
= lls_short_help(cmd
);
241 static int com_default_val(struct lls_parse_result
*lpr
)
243 const struct lls_opt_result
*r
;
245 const char *txt1
, *txt2
;
247 r
= OPT_RESULT(DEFAULT_VAL
, WIDTH
, lpr
);
248 val1
= lls_uint32_val(0, r
);
249 r
= OPT_RESULT(DEFAULT_VAL
, HEIGHT
, lpr
);
250 val2
= lls_uint32_val(0, r
);
251 printf("geometry: %" PRIu32
"x%" PRIu32
"\n", val1
, val2
);
253 r
= OPT_RESULT(DEFAULT_VAL
, TOWN
, lpr
);
254 txt1
= lls_string_val(0, r
);
255 r
= OPT_RESULT(DEFAULT_VAL
, STREET
, lpr
);
256 txt2
= lls_string_val(0, r
);
257 printf("address: %s, %s\n", txt2
, txt1
);
259 r
= OPT_RESULT(DEFAULT_VAL
, TIME
, lpr
);
260 val1
= lls_uint32_val(0, r
);
261 txt1
= lls_enum_string_val(val1
, OPT_PTR(DEFAULT_VAL
, TIME
));
262 r
= OPT_RESULT(DEFAULT_VAL
, WEEKDAY
, lpr
);
263 val2
= lls_uint32_val(0, r
);
264 txt2
= lls_enum_string_val(val2
, OPT_PTR(DEFAULT_VAL
, WEEKDAY
));
265 printf("when: %s %s\n", txt2
, txt1
);
269 EXPORT_CMD(default_val
)
271 static int com_optional_arg(struct lls_parse_result
*lpr
)
273 const struct lls_opt_result
*r
;
275 r
= OPT_RESULT(OPTIONAL_ARG
, WIDTH
, lpr
);
277 printf("width: %u (%u times given)\n", lls_uint32_val(0, r
),
279 r
= OPT_RESULT(OPTIONAL_ARG
, HEIGHT
, lpr
);
280 printf("height: %u (%u times given)\n", lls_uint32_val(0, r
),
282 printf("%u non-option arguments\n", lls_num_inputs(lpr
));
285 EXPORT_CMD(optional_arg
)
287 /* stringify the first argument (author information) */
288 #define LOPSUBEX_AUX_INFO(_author, _perms) #_author,
289 static const char * const authors
[] = {LSG_LOPSUBEX_AUX_INFOS
};
290 #undef LOPSUBEX_AUX_INFO
291 #define LOPSUBEX_AUX_INFO(_author, _perms) _perms,
292 static const mode_t permissions
[] = {LSG_LOPSUBEX_AUX_INFOS
};
293 static int com_aux_info(struct lls_parse_result
*lpr
)
295 const struct lls_command
*cmd
;
298 for (i
= 0; (cmd
= lls_cmd(i
, lopsubex_suite
)); i
++) {
299 const char *name
= lls_command_name(cmd
);
300 printf("%s: ", name
);
301 printf("author: %s, permissions: %o\n", authors
[i
],
308 int main(int argc
, char **argv
)
311 const struct lls_command
*cmd
;
312 struct lls_parse_result
*lpr
;
313 const struct local_command_info
*lci
;
317 printf("Usage: %s <subcommand> [options]\n", argv
[0]);
318 print_available_commands();
321 cmd
= lookup_subcmd_or_die(argv
[1]);
322 ret
= lls_parse(argc
- 1, argv
+ 1, cmd
, &lpr
, &errctx
);
324 printf("%s: %s\n", errctx
, lls_strerror(-ret
));
328 lci
= lls_user_data(cmd
);
329 ret
= lci
->handler(lpr
);
330 lls_free_parse_result(lpr
, cmd
);
331 exit(ret
< 0? EXIT_FAILURE
: EXIT_SUCCESS
);