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);