2 * UCW Library -- Parsing of command line options
4 * (c) 2013 Jan Moskyto Matejka <mq@ucw.cz>
5 * (c) 2014 Martin Mares <mj@ucw.cz>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
13 #include <ucw/strtonum.h>
14 #include <ucw/fastbuf.h>
17 static void show_version(struct opt_item * opt UNUSED, const char * value UNUSED, void * data UNUSED) {
18 printf("This is a simple tea boiling console v0.1.\n");
22 struct teapot_temperature {
33 static char * temp_scale_str[] = { "C", "F", "K", "Re", "R" };
35 static enum TEAPOT_TYPE {
41 } set = TEAPOT_UNDEFINED;
43 static char * teapot_type_str[] = { "standard", "exclusive", "glass", "hands" };
45 static int show_hooks = 0;
46 static int english = 0;
48 static int verbose = 1;
49 static int with_gas = 0;
50 static int *black_magic;
52 static int water_amount = 0;
53 static int clean_pot = 1;
54 static char * first_tea = NULL;
56 #define MAX_TEA_COUNT 30
57 static char * tea_list[MAX_TEA_COUNT];
58 static int tea_num = 0;
59 static void add_tea(struct opt_item * opt UNUSED, const char * name, void * data) {
60 char ** tea_list = data;
61 if (tea_num >= MAX_TEA_COUNT) {
62 fprintf(stderr, "Cannot boil more than %d teas.\n", MAX_TEA_COUNT);
63 exit(OPT_EXIT_BAD_ARGS);
65 tea_list[tea_num++] = xstrdup(name);
68 static const char * teapot_temperature_parser(char * in, void * ptr) {
69 struct teapot_temperature * temp = ptr;
71 const char * err = str_to_int(&temp->value, in, &next, 10);
74 if (!strcmp("C", next))
75 temp->scale = TEMP_CELSIUS;
76 else if (!strcmp("F", next))
77 temp->scale = TEMP_FAHRENHEIT;
78 else if (!strcmp("K", next))
79 temp->scale = TEMP_KELVIN;
80 else if (!strcmp("R", next))
81 temp->scale = TEMP_RANKINE;
82 else if (!strcmp("Re", next))
83 temp->scale = TEMP_REAUMUR;
85 fprintf(stderr, "Unknown scale: %s\n", next);
86 exit(OPT_EXIT_BAD_ARGS);
91 static void teapot_temperature_dumper(struct fastbuf * fb, void * ptr) {
92 struct teapot_temperature * temp = ptr;
93 bprintf(fb, "%d%s", temp->value, temp_scale_str[temp->scale]);
96 static struct cf_user_type teapot_temperature_t = {
97 .size = sizeof(struct teapot_temperature),
98 .name = "teapot_temperature_t",
99 .parser = (cf_parser1*) teapot_temperature_parser,
100 .dumper = (cf_dumper1*) teapot_temperature_dumper
103 static void opt_test_hook(struct opt_item * opt, uint event UNUSED, const char * value, void * data) {
107 printf("[HOOK-%s:%c/%s=%s] ", (char *) data, opt->letter, opt->name, value);
109 printf("[HOOK-%s] ", (char *) data);
112 static struct opt_section water_options = {
114 OPT_INT('w', "water", water_amount, OPT_REQUIRED | OPT_REQUIRED_VALUE, "<volume>\tAmount of water (in mls; required)"),
115 OPT_BOOL('G', "with-gas", with_gas, OPT_NO_VALUE, "\tUse water with gas"),
120 static struct opt_section options = {
122 OPT_HELP("A simple tea boiling console."),
123 OPT_HELP("Usage: teapot [options] name-of-the-tea"),
125 OPT_HELP("Black, green or white tea supported as well as fruit or herbal tea."),
126 OPT_HELP("You may specify more kinds of tea, all of them will be boiled for you, in the given order."),
127 OPT_HELP("At least one kind of tea must be specified."),
129 OPT_HELP("Options:"),
131 OPT_CALL('V', "version", show_version, NULL, OPT_NO_VALUE, "\tShow the version"),
133 OPT_BOOL('e', "english-style", english, 0, "\tEnglish style (with milk)"),
134 OPT_INT('s', "sugar", sugar, OPT_REQUIRED_VALUE, "<spoons>\tAmount of sugar (in teaspoons)"),
135 OPT_SWITCH(0, "standard-set", set, TEAPOT_STANDARD, OPT_SINGLE, "\tStandard teapot"),
136 OPT_SWITCH('x', "exclusive-set", set, TEAPOT_EXCLUSIVE, OPT_SINGLE, "\tExclusive teapot"),
137 OPT_SWITCH('g', "glass-set", set, TEAPOT_GLASS, OPT_SINGLE, "\tTransparent glass teapot"),
138 OPT_SWITCH('h', "hands", set, TEAPOT_HANDS, OPT_SINGLE, "\tUse user's hands as a teapot (a bit dangerous)"),
139 OPT_USER('t', "temperature", temperature, teapot_temperature_t, OPT_REQUIRED_VALUE | OPT_REQUIRED,
140 "<value>\tWanted final temperature of the tea to be served (required)\n"
141 "\t\tSupported scales: Celsius [60C], Fahrenheit [140F],\n"
142 "\t\t Kelvin [350K], Rankine [600R] and Reaumur [50Re]\n"
143 "\t\tOnly integer values allowed."),
144 OPT_INC('v', "verbose", verbose, 0, "\tVerbose (the more -v, the more verbose)"),
145 OPT_INC('q', "quiet", verbose, OPT_NEGATIVE, "\tQuiet (the more -q, the more quiet)"),
146 OPT_INT_MULTIPLE('b', NULL, black_magic, 0, "<strength>\tUse black magic to make the tea extraordinarily delicious.\n\t\tMay be specified more than once to describe the amounts of black magic to be invoked in each step of tea boiling."),
147 OPT_BOOL('p', "pray", pray, OPT_SINGLE, "\tPray before boiling"),
148 OPT_BOOL(0, "no-clean", clean_pot, OPT_NEGATIVE, "\tDo not clean the teapot before boiling"),
149 OPT_STRING(OPT_POSITIONAL(1), NULL, first_tea, OPT_REQUIRED, ""),
150 OPT_CALL(OPT_POSITIONAL_TAIL, NULL, add_tea, &tea_list, 0, ""),
152 OPT_HELP("Water options:"),
153 OPT_SECTION(water_options),
154 OPT_HOOK(opt_test_hook, "prearg", OPT_HOOK_BEFORE_ARG),
155 OPT_HOOK(opt_test_hook, "preval", OPT_HOOK_BEFORE_VALUE),
156 OPT_HOOK(opt_test_hook, "postval", OPT_HOOK_AFTER_VALUE),
157 OPT_BOOL('H', "show-hooks", show_hooks, 0, "\tDemonstrate the hooks."),
159 OPT_HELP("Configuration options:"),
170 int main(int argc UNUSED, char ** argv)
172 cf_def_file = "etc/libucw";
173 GARY_INIT(black_magic, 0);
174 opt_parse(&options, argv+1);
176 printf("English style: %s|", english ? "yes" : "no");
178 printf("Sugar: %d teaspoons|", sugar);
180 printf("Chosen teapot: %s|", teapot_type_str[set]);
181 printf("Temperature: %d%s|", temperature.value, temp_scale_str[temperature.scale]);
182 printf("Verbosity: %d|", verbose);
183 uint magick = GARY_SIZE(black_magic);
184 for (uint i=0; i<magick; i++)
185 printf("Black magic: %d|", black_magic[i]);
186 printf("Prayer: %s|", pray ? "yes" : "no");
187 printf("Clean: %s|", clean_pot ? "yes" : "no");
188 printf("Water amount: %d|", water_amount);
189 printf("Gas: %s|", with_gas ? "yes" : "no");
190 printf("First tea: %s|", first_tea);
191 for (int i=0; i<tea_num; i++)
192 printf("Boiling a tea: %s|", tea_list[i]);
194 printf("Everything OK. Bye.\n");