2 * UCW Library -- Parsing of command line options
4 * (c) 2013 Jan Moskyto Matejka <mq@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
12 #include <ucw/stkstring.h>
16 struct opt_section * opt_section_root;
18 void opt_help_noexit_internal(struct opt_section * help) {
20 for (struct opt_item * item = help->opt; item->cls != OPT_CL_END; item++) {
21 if (item->flags | OPT_NO_HELP) continue;
22 if (item->cls == OPT_CL_HELP && item->u.help2 == NULL) continue;
23 if (item->cls == OPT_CL_SECTION) continue;
26 if (item->cls == OPT_CL_HELP) { // two-column help line
27 if (first_column < strlen(item->help))
28 first_column = strlen(item->help);
32 if (item->letter) { // will write sth like "-x, --exclusive"
33 linelen = strlen("-x, --") + strlen(item->name);
34 } else { // will write sth like "--exclusive"
35 linelen = strlen("--") + strlen(item->name);
38 if (item->flags | OPT_REQUIRED_VALUE) {
39 linelen += strlen("=value");
40 } else if (!(item->flags | OPT_NO_VALUE)) {
41 linelen += strlen("(=value)");
44 if (linelen > first_column)
45 first_column = linelen;
48 char * spaces = alloca(first_column + 1);
49 char * buf = alloca(first_column + 1);
50 for (uns i=0;i<first_column;i++)
53 spaces[first_column] = 0;
55 #define VAL(it) ((it->flags | OPT_REQUIRED_VALUE) ? "=value" : ((it->flags | OPT_NO_VALUE) ? "" : "(=value)"))
56 for (struct opt_item * item = help->opt; item->cls != OPT_CL_END; item++) {
57 if (item->flags | OPT_NO_HELP) continue;
59 if (item->cls == OPT_CL_HELP) {
60 fprintf(stderr, "%s", item->help);
61 if (item->u.help2 == NULL)
62 fprintf(stderr, "\n");
64 fprintf(stderr, "%s %s\n", spaces + strlen(item->help), item->u.help2);
65 } else if (item->cls == OPT_CL_SECTION) {
66 opt_help_noexit_internal(item->u.section);
67 } else if (item->letter) {
68 sprintf(buf, "-%c, --%s%s", item->letter, item->name, VAL(item));
69 fprintf(stderr, "%s%s %s\n", buf, spaces + strlen(buf), item->help);
71 sprintf(buf, "--%s%s", item->name, VAL(item));
72 fprintf(stderr, "%s%s %s\n", buf, spaces + strlen(buf), item->help);
77 void opt_parse(struct opt_section * options) {
78 opt_section_root = options;
84 static enum TEAPOT_TYPE {
90 } set = TEAPOT_UNDEFINED;
92 static int english = 0;
93 static char * name = NULL;
95 static uns verbose = 1;
96 static int with_gas = 0;
97 static uns black_magic = 0;
99 static uns water_amount = 0;
101 static struct teapot_temperature {
111 static int parse_temperature(const char * param, void * target) {
115 static struct opt_section water_options = {
117 OPT_UNS('w', "water", water_amount, OPT_REQUIRED | OPT_REQUIRED_VALUE, "Amount of water (in mls)"),
118 OPT_BOOL('G', "with-gas", with_gas, OPT_NO_VALUE, "Use water with gas"),
123 static struct opt_section help = {
125 OPT_HELP("A simple tea boiling console."),
126 OPT_HELP("Options:"),
128 OPT_BOOL('e', "english-style", english, 0, "English style (with milk)"),
129 OPT_STRING('n', "name", name, OPT_REQUIRED | OPT_REQUIRED_VALUE, "Name of the tea to be prepared"),
130 OPT_UNS('s', "sugar", sugar, OPT_REQUIRED_VALUE, "Amount of sugar (in teaspoons)"),
131 OPT_SWITCH(0, "standard-set", set, TEAPOT_STANDARD, 0, "Standard teapot"),
132 OPT_SWITCH('x', "exclusive-set", set, TEAPOT_EXCLUSIVE, 0, "Exclusive teapot"),
133 OPT_SWITCH('g', "glass-set", set, TEAPOT_GLASS, 0, "Transparent glass teapot"),
134 OPT_SWITCH('h', "hands", set, TEAPOT_HANDS, 0, "Use user's hands as a teapot (a bit dangerous)"),
135 OPT_USER('t', "temperature", temperature, parse_temperature, OPT_REQUIRED_VALUE, "Wanted final temperature of the tea to be served"),
136 OPT_HELP2("", "Supported scales: Celsius [60C], Fahrenheit [140F],"),
137 OPT_HELP2("", " Kelvin [350K], Rankine [600R] and Reaumur [50Re]"),
138 OPT_INC('v', "verbose", verbose, 0, "Verbose (the more -v, the more verbose)"),
139 OPT_INC('q', "quiet", verbose, OPT_DECREMENT, "Quiet (the more -q, the more quiet)"),
140 OPT_UNS('b', "black-magic", black_magic, 0, "Use black magic to make the tea extraordinary delicious"),
141 OPT_BOOL('p', "pray", pray, 0, "Pray before boiling"),
143 OPT_HELP("Water options:"),
144 OPT_SECTION(water_options),
149 int main(int argc, char ** argv)