2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
17 # define gettext(x) (x)
18 # define dgettext(domain, x) (x)
21 #define _(x) dgettext("ecore", x)
28 #include "Ecore_Getopt.h"
30 static const char *prog = NULL;
31 static char **argv = NULL;
34 static int helpcol = 80 / 3;
37 _ecore_getopt_help_print_replace_program(FILE *fp, const Ecore_Getopt *parser __UNUSED__, const char *text)
41 const char *d = strchr(text, '%');
49 if (fwrite(text, 1, d - text, fp) != (size_t)(d - text))
52 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
54 fputs(prog ? prog : "???", fp);
55 d += sizeof("prog") - 1;
66 while (text[0] != '\0');
72 _ecore_getopt_version(FILE *fp, const Ecore_Getopt *parser)
74 fputs(_("Version:"), fp);
76 _ecore_getopt_help_print_replace_program(fp, parser, parser->version);
80 _ecore_getopt_help_usage(FILE *fp, const Ecore_Getopt *parser)
82 fputs(_("Usage:"), fp);
87 fprintf(fp, _("%s [options]\n"), prog);
91 _ecore_getopt_help_print_replace_program(fp, parser, gettext(parser->usage));
95 _ecore_getopt_help_line(FILE *fp, const int base, const int total, int used, const char *text, int len)
100 /* process line considering spaces (new line and tabs are spaces!) */
101 while ((used < total) && (len > 0))
103 const char *space = NULL;
110 for (i = 0; i < todo; i++)
111 if (isspace(text[i]))
119 i = fwrite(text, 1, i, fp);
131 if (space[0] == '\n')
133 else if (space[0] == '\t')
138 c = ((used / 8) + 1) * 8;
141 for (; used < c; used++)
151 else if (used < total)
156 i = fwrite(text, 1, i, fp);
167 for (used = 0; used < base; used++)
176 _ecore_getopt_help_description(FILE *fp, const Ecore_Getopt *parser)
178 const char *p, *prg, *ver;
179 int used, prglen, verlen;
181 p = gettext(parser->description);
187 prg = prog ? prog : "???";
188 ver = parser->version ? parser->version : "???";
190 prglen = strlen(prg);
191 verlen = strlen(ver);
197 const char *d = strchr(p, '%');
201 _ecore_getopt_help_line(fp, 0, cols, used, p, strlen(p));
205 used = _ecore_getopt_help_line(fp, 0, cols, used, p, d - p);
207 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
209 used = _ecore_getopt_help_line(fp, 0, cols, used, prg, prglen);
210 d += sizeof("prog") - 1;
212 else if (strncmp(d, "version", sizeof("version") - 1) == 0)
214 used = _ecore_getopt_help_line(fp, 0, cols, used, ver, verlen);
215 d += sizeof("version") - 1;
221 used = _ecore_getopt_help_line(fp, 0, cols, used, "%", 1);
226 while (p[0] != '\0');
232 _ecore_getopt_copyright(FILE *fp, const Ecore_Getopt *parser)
234 const char *txt = gettext(parser->copyright);
235 fputs(_("Copyright:"), fp);
237 _ecore_getopt_help_line
238 (fp, 3, cols, 3, txt, strlen(txt));
243 _ecore_getopt_license(FILE *fp, const Ecore_Getopt *parser)
245 const char *txt = gettext(parser->license);
246 fputs(_("License:"), fp);
248 _ecore_getopt_help_line
249 (fp, 3, cols, 3, txt, strlen(txt));
253 static Ecore_Getopt_Desc_Arg_Requirement
254 _ecore_getopt_desc_arg_requirement(const Ecore_Getopt_Desc *desc)
256 switch (desc->action)
258 case ECORE_GETOPT_ACTION_STORE:
259 return desc->action_param.store.arg_req;
260 case ECORE_GETOPT_ACTION_STORE_CONST:
261 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
262 case ECORE_GETOPT_ACTION_STORE_TRUE:
263 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
264 case ECORE_GETOPT_ACTION_STORE_FALSE:
265 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
266 case ECORE_GETOPT_ACTION_CHOICE:
267 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
268 case ECORE_GETOPT_ACTION_APPEND:
269 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
270 case ECORE_GETOPT_ACTION_COUNT:
271 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
272 case ECORE_GETOPT_ACTION_CALLBACK:
273 return desc->action_param.callback.arg_req;
274 case ECORE_GETOPT_ACTION_HELP:
275 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
276 case ECORE_GETOPT_ACTION_VERSION:
277 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
279 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
284 _ecore_getopt_help_desc_setup_metavar(const Ecore_Getopt_Desc *desc, char *metavar, int *metavarlen, int maxsize)
288 const char *txt = gettext(desc->metavar);
289 *metavarlen = strlen(txt);
290 if (*metavarlen > maxsize - 1)
291 *metavarlen = maxsize - 1;
293 memcpy(metavar, txt, *metavarlen);
294 metavar[*metavarlen] = '\0';
296 else if (desc->longname)
300 *metavarlen = strlen(desc->longname);
301 if (*metavarlen > maxsize - 1)
302 *metavarlen = maxsize - 1;
304 for (i = 0; i < *metavarlen; i++)
305 metavar[i] = toupper(desc->longname[i]);
311 _ecore_getopt_help_desc_show_arg(FILE *fp, Ecore_Getopt_Desc_Arg_Requirement requirement, const char *metavar, int metavarlen)
315 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
320 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
326 if (requirement != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
330 used += metavarlen + 1;
333 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
343 _ecore_getopt_help_desc_store(FILE *fp, const int base, const int total, int used, const Ecore_Getopt_Desc *desc)
345 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
351 for (used = 0; used < base; used++)
356 case ECORE_GETOPT_TYPE_STR:
358 len = sizeof("STR") - 1;
360 case ECORE_GETOPT_TYPE_BOOL:
362 len = sizeof("BOOL") - 1;
364 case ECORE_GETOPT_TYPE_SHORT:
366 len = sizeof("SHORT") - 1;
368 case ECORE_GETOPT_TYPE_INT:
370 len = sizeof("INT") - 1;
372 case ECORE_GETOPT_TYPE_LONG:
374 len = sizeof("LONG") - 1;
376 case ECORE_GETOPT_TYPE_USHORT:
378 len = sizeof("USHORT") - 1;
380 case ECORE_GETOPT_TYPE_UINT:
382 len = sizeof("UINT") - 1;
384 case ECORE_GETOPT_TYPE_ULONG:
386 len = sizeof("ULONG") - 1;
388 case ECORE_GETOPT_TYPE_DOUBLE:
390 len = sizeof("DOUBLE") - 1;
394 len = sizeof("???") - 1;
397 used = _ecore_getopt_help_line
398 (fp, base, total, used, _("Type: "), strlen(_("Type: ")));
399 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
401 if (store->arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES)
404 used = _ecore_getopt_help_line
405 (fp, base, total, used, ". ", sizeof(". ") - 1);
409 case ECORE_GETOPT_TYPE_STR:
410 str = store->def.strv;
411 len = str ? strlen(str) : 0;
413 case ECORE_GETOPT_TYPE_BOOL:
414 str = store->def.boolv ? "true" : "false";
417 case ECORE_GETOPT_TYPE_SHORT:
419 len = snprintf(buf, sizeof(buf), "%hd", store->def.shortv);
420 if (len > sizeof(buf) - 1)
421 len = sizeof(buf) - 1;
423 case ECORE_GETOPT_TYPE_INT:
425 len = snprintf(buf, sizeof(buf), "%d", store->def.intv);
426 if (len > sizeof(buf) - 1)
427 len = sizeof(buf) - 1;
429 case ECORE_GETOPT_TYPE_LONG:
431 len = snprintf(buf, sizeof(buf), "%ld", store->def.longv);
432 if (len > sizeof(buf) - 1)
433 len = sizeof(buf) - 1;
435 case ECORE_GETOPT_TYPE_USHORT:
437 len = snprintf(buf, sizeof(buf), "%hu", store->def.ushortv);
438 if (len > sizeof(buf) - 1)
439 len = sizeof(buf) - 1;
441 case ECORE_GETOPT_TYPE_UINT:
443 len = snprintf(buf, sizeof(buf), "%u", store->def.uintv);
444 if (len > sizeof(buf) - 1)
445 len = sizeof(buf) - 1;
447 case ECORE_GETOPT_TYPE_ULONG:
449 len = snprintf(buf, sizeof(buf), "%lu", store->def.ulongv);
450 if (len > sizeof(buf) - 1)
451 len = sizeof(buf) - 1;
453 case ECORE_GETOPT_TYPE_DOUBLE:
455 len = snprintf(buf, sizeof(buf), "%f", store->def.doublev);
456 if (len > sizeof(buf) - 1)
457 len = sizeof(buf) - 1;
461 len = sizeof("???") - 1;
464 used = _ecore_getopt_help_line
465 (fp, base, total, used, _("Default: "), strlen(_("Default: ")));
466 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
469 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
473 _ecore_getopt_help_desc_choices(FILE *fp, const int base, const int total, int used, const Ecore_Getopt_Desc *desc)
475 const char *const *itr;
476 const char sep[] = ", ";
477 const int seplen = sizeof(sep) - 1;
484 for (; used < base; used++)
487 used = _ecore_getopt_help_line
488 (fp, base, total, used, _("Choices: "), strlen(_("Choices: ")));
490 for (itr = desc->action_param.choices; *itr != NULL; itr++)
492 used = _ecore_getopt_help_line
493 (fp, base, total, used, *itr, strlen(*itr));
495 used = _ecore_getopt_help_line(fp, base, total, used, sep, seplen);
498 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
502 _ecore_getopt_help_desc(FILE *fp, const Ecore_Getopt_Desc *desc)
504 Ecore_Getopt_Desc_Arg_Requirement arg_req;
505 char metavar[32] = "ARG";
509 arg_req = _ecore_getopt_desc_arg_requirement(desc);
510 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
511 _ecore_getopt_help_desc_setup_metavar
512 (desc, metavar, &metavarlen, sizeof(metavar));
520 fputc(desc->shortname, fp);
522 used += _ecore_getopt_help_desc_show_arg
523 (fp, arg_req, metavar, metavarlen);
526 if (desc->shortname && desc->longname)
534 int namelen = strlen(desc->longname);
537 fputs(desc->longname, fp);
539 used += _ecore_getopt_help_desc_show_arg
540 (fp, arg_req, metavar, metavarlen);
546 if (used + 3 >= helpcol)
552 for (; used < helpcol; used++)
555 used = _ecore_getopt_help_line
556 (fp, helpcol, cols, used, desc->help, strlen(desc->help));
558 switch (desc->action)
560 case ECORE_GETOPT_ACTION_STORE:
561 _ecore_getopt_help_desc_store(fp, helpcol, cols, used, desc);
563 case ECORE_GETOPT_ACTION_CHOICE:
564 _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc);
575 _ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc)
577 return (desc->shortname == '\0') && (desc->longname == NULL);
581 _ecore_getopt_help_options(FILE *fp, const Ecore_Getopt *parser)
583 const Ecore_Getopt_Desc *desc;
585 fputs(_("Options:\n"), fp);
587 for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
588 _ecore_getopt_help_desc(fp, desc);
594 * Show nicely formatted help message for the given parser.
596 * Message will be print to stderr.
599 ecore_getopt_help(FILE *fp, const Ecore_Getopt *parser)
607 ecore_app_args_get(&argc, &argv);
608 if ((argc > 0) && (argv[0] != NULL))
614 var = getenv("COLUMNS");
624 _ecore_getopt_help_usage(fp, parser);
625 _ecore_getopt_help_description(fp, parser);
626 _ecore_getopt_help_options(fp, parser);
629 static const Ecore_Getopt_Desc *
630 _ecore_getopt_parse_find_long(const Ecore_Getopt *parser, const char *name)
632 const Ecore_Getopt_Desc *desc = parser->descs;
633 const char *p = strchr(name, '=');
639 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
646 if ((strncmp(name, desc->longname, len) == 0) &&
647 (desc->longname[len] == '\0'))
652 if (strcmp(name, desc->longname) == 0)
660 static const Ecore_Getopt_Desc *
661 _ecore_getopt_parse_find_short(const Ecore_Getopt *parser, char name)
663 const Ecore_Getopt_Desc *desc = parser->descs;
664 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
665 if (name == desc->shortname)
671 _ecore_getopt_parse_find_nonargs_base(const Ecore_Getopt *parser, int argc, char **argv)
674 int src, dst, used, base;
682 const Ecore_Getopt_Desc *desc;
683 Ecore_Getopt_Desc_Arg_Requirement arg_req;
684 char *arg = argv[src];
691 if (arg[2] == '\0') /* explicit end of options, "--" */
696 desc = _ecore_getopt_parse_find_long(parser, arg + 2);
699 desc = _ecore_getopt_parse_find_short(parser, arg[1]);
704 fprintf(stderr, _("ERROR: unknown option --%s.\n"), arg + 2);
706 fprintf(stderr, _("ERROR: unknown option -%c.\n"), arg[1]);
709 memmove(argv + dst, nonargs, used * sizeof(char *));
717 argv[dst] = argv[src];
721 arg_req = _ecore_getopt_desc_arg_requirement(desc);
722 if (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
725 if (strchr(arg, '='))
728 if ((src >= argc) || (argv[src][0] == '-'))
732 argv[dst] = argv[src];
743 if (!base) /* '--' not found */
749 argv[dst] = argv[src];
753 memmove(argv + dst, nonargs, used * sizeof(char *));
758 _ecore_getopt_desc_print_error(const Ecore_Getopt_Desc *desc, const char *fmt, ...)
762 fputs(_("ERROR: "), stderr);
767 fputc(desc->shortname, stderr);
770 if (desc->shortname && desc->longname)
776 fputs(desc->longname, stderr);
782 vfprintf(stderr, fmt, ap);
787 _ecore_getopt_parse_bool(const char *str, unsigned char *v)
789 if ((strcmp(str, "0") == 0) ||
790 (strcasecmp(str, "f") == 0) ||
791 (strcasecmp(str, "false") == 0) ||
792 (strcasecmp(str, "no") == 0) ||
793 (strcasecmp(str, "off") == 0)
799 else if ((strcmp(str, "1") == 0) ||
800 (strcasecmp(str, "t") == 0) ||
801 (strcasecmp(str, "true") == 0) ||
802 (strcasecmp(str, "yes") == 0) ||
803 (strcasecmp(str, "on") == 0)
814 _ecore_getopt_parse_long(const char *str, long int *v)
817 *v = strtol(str, &endptr, 0);
822 _ecore_getopt_parse_double(const char *str, double *v)
825 *v = strtod(str, &endptr);
830 _ecore_getopt_parse_store(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *value, const char *arg_val)
832 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
839 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
843 switch (store->arg_req)
845 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
847 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
850 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
856 case ECORE_GETOPT_TYPE_STR:
857 *value->strp = (char *)arg_val;
859 case ECORE_GETOPT_TYPE_BOOL:
860 if (_ecore_getopt_parse_bool(arg_val, &b))
867 _ecore_getopt_desc_print_error
868 (desc, _("unknown boolean value %s.\n"), arg_val);
871 case ECORE_GETOPT_TYPE_SHORT:
872 if (!_ecore_getopt_parse_long(arg_val, &v))
876 case ECORE_GETOPT_TYPE_INT:
877 if (!_ecore_getopt_parse_long(arg_val, &v))
881 case ECORE_GETOPT_TYPE_LONG:
882 if (!_ecore_getopt_parse_long(arg_val, &v))
886 case ECORE_GETOPT_TYPE_USHORT:
887 if (!_ecore_getopt_parse_long(arg_val, &v))
891 case ECORE_GETOPT_TYPE_UINT:
892 if (!_ecore_getopt_parse_long(arg_val, &v))
896 case ECORE_GETOPT_TYPE_ULONG:
897 if (!_ecore_getopt_parse_long(arg_val, &v))
901 case ECORE_GETOPT_TYPE_DOUBLE:
902 if (!_ecore_getopt_parse_double(arg_val, &d))
911 _ecore_getopt_desc_print_error
912 (desc, _("invalid number format %s\n"), arg_val);
918 case ECORE_GETOPT_TYPE_STR:
919 *value->strp = (char *)store->def.strv;
921 case ECORE_GETOPT_TYPE_BOOL:
922 *value->boolp = store->def.boolv;
924 case ECORE_GETOPT_TYPE_SHORT:
925 *value->shortp = store->def.shortv;
927 case ECORE_GETOPT_TYPE_INT:
928 *value->intp = store->def.intv;
930 case ECORE_GETOPT_TYPE_LONG:
931 *value->longp = store->def.longv;
933 case ECORE_GETOPT_TYPE_USHORT:
934 *value->ushortp = store->def.ushortv;
936 case ECORE_GETOPT_TYPE_UINT:
937 *value->uintp = store->def.uintv;
939 case ECORE_GETOPT_TYPE_ULONG:
940 *value->ulongp = store->def.ulongv;
942 case ECORE_GETOPT_TYPE_DOUBLE:
943 *value->doublep = store->def.doublev;
951 _ecore_getopt_parse_store_const(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
955 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
959 *val->ptrp = (void *)desc->action_param.store_const;
964 _ecore_getopt_parse_store_true(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
968 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
976 _ecore_getopt_parse_store_false(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
980 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
988 _ecore_getopt_parse_choice(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
990 const char * const *pchoice;
994 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
998 pchoice = desc->action_param.choices;
999 for (; *pchoice != NULL; pchoice++)
1000 if (strcmp(*pchoice, arg_val) == 0)
1002 *val->strp = (char *)*pchoice;
1006 _ecore_getopt_desc_print_error
1007 (desc, _("invalid choice \"%s\". Valid values are: "), arg_val);
1009 pchoice = desc->action_param.choices;
1010 for (; *pchoice != NULL; pchoice++)
1012 fputs(*pchoice, stderr);
1013 if (pchoice[1] != NULL)
1014 fputs(", ", stderr);
1017 fputs(".\n", stderr);
1021 static unsigned char
1022 _ecore_getopt_parse_append(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
1031 _ecore_getopt_desc_print_error
1032 (desc, _("missing parameter to append.\n"));
1038 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1042 switch (desc->action_param.append_type)
1044 case ECORE_GETOPT_TYPE_STR:
1045 data = strdup(arg_val);
1047 case ECORE_GETOPT_TYPE_BOOL:
1049 if (_ecore_getopt_parse_bool(arg_val, &b))
1051 data = malloc(sizeof(unsigned char));
1053 *(unsigned char *)data = b;
1057 _ecore_getopt_desc_print_error
1058 (desc, _("unknown boolean value %s.\n"), arg_val);
1063 case ECORE_GETOPT_TYPE_SHORT:
1065 if (!_ecore_getopt_parse_long(arg_val, &v))
1067 data = malloc(sizeof(short));
1069 *(short *)data = (short)v;
1072 case ECORE_GETOPT_TYPE_INT:
1074 if (!_ecore_getopt_parse_long(arg_val, &v))
1076 data = malloc(sizeof(int));
1078 *(int *)data = (int)v;
1081 case ECORE_GETOPT_TYPE_LONG:
1083 if (!_ecore_getopt_parse_long(arg_val, &v))
1085 data = malloc(sizeof(long));
1090 case ECORE_GETOPT_TYPE_USHORT:
1092 if (!_ecore_getopt_parse_long(arg_val, &v))
1094 data = malloc(sizeof(unsigned short));
1096 *(unsigned short *)data = (unsigned short)v;
1099 case ECORE_GETOPT_TYPE_UINT:
1101 if (!_ecore_getopt_parse_long(arg_val, &v))
1103 data = malloc(sizeof(unsigned int));
1105 *(unsigned int *)data = (unsigned int)v;
1108 case ECORE_GETOPT_TYPE_ULONG:
1110 if (!_ecore_getopt_parse_long(arg_val, &v))
1112 data = malloc(sizeof(unsigned long));
1114 *(unsigned long *)data = v;
1117 case ECORE_GETOPT_TYPE_DOUBLE:
1119 if (!_ecore_getopt_parse_double(arg_val, &d))
1121 data = malloc(sizeof(double));
1123 *(double *)data = d;
1128 _ecore_getopt_desc_print_error(desc, _("could not parse value.\n"));
1133 *val->listp = eina_list_append(*val->listp, data);
1137 _ecore_getopt_desc_print_error
1138 (desc, _("invalid number format %s\n"), arg_val);
1142 static unsigned char
1143 _ecore_getopt_parse_count(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1147 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1155 static unsigned char
1156 _ecore_getopt_parse_callback(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
1158 const Ecore_Getopt_Desc_Callback *cb = &desc->action_param.callback;
1160 switch (cb->arg_req)
1162 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
1165 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
1169 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
1173 if (cb->arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1175 if ((!arg_val) || (arg_val[0] == '\0'))
1177 _ecore_getopt_desc_print_error(desc, _("missing parameter.\n"));
1183 _ecore_getopt_desc_print_error
1184 (desc, _("value has no pointer set.\n"));
1191 _ecore_getopt_desc_print_error(desc, _("missing callback function!\n"));
1195 return cb->func(parser, desc, arg_val, (void *)cb->data, val);
1198 static unsigned char
1199 _ecore_getopt_parse_help(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc __UNUSED__, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1203 ecore_getopt_help(stdout, parser);
1207 static unsigned char
1208 _ecore_getopt_parse_version(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1212 if (!parser->version)
1214 _ecore_getopt_desc_print_error(desc, _("no version was defined.\n"));
1217 _ecore_getopt_version(stdout, parser);
1221 static unsigned char
1222 _ecore_getopt_parse_copyright(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1226 if (!parser->copyright)
1228 _ecore_getopt_desc_print_error(desc, _("no copyright was defined.\n"));
1231 _ecore_getopt_copyright(stdout, parser);
1235 static unsigned char
1236 _ecore_getopt_parse_license(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1240 if (!parser->license)
1242 _ecore_getopt_desc_print_error(desc, _("no license was defined.\n"));
1245 _ecore_getopt_license(stdout, parser);
1249 static unsigned char
1250 _ecore_getopt_desc_handle(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *value, const char *arg_val)
1252 switch (desc->action)
1254 case ECORE_GETOPT_ACTION_STORE:
1255 return _ecore_getopt_parse_store(parser, desc, value, arg_val);
1256 case ECORE_GETOPT_ACTION_STORE_CONST:
1257 return _ecore_getopt_parse_store_const(parser, desc, value, arg_val);
1258 case ECORE_GETOPT_ACTION_STORE_TRUE:
1259 return _ecore_getopt_parse_store_true(parser, desc, value, arg_val);
1260 case ECORE_GETOPT_ACTION_STORE_FALSE:
1261 return _ecore_getopt_parse_store_false(parser, desc, value, arg_val);
1262 case ECORE_GETOPT_ACTION_CHOICE:
1263 return _ecore_getopt_parse_choice(parser, desc, value, arg_val);
1264 case ECORE_GETOPT_ACTION_APPEND:
1265 return _ecore_getopt_parse_append(parser, desc, value, arg_val);
1266 case ECORE_GETOPT_ACTION_COUNT:
1267 return _ecore_getopt_parse_count(parser, desc, value, arg_val);
1268 case ECORE_GETOPT_ACTION_CALLBACK:
1269 return _ecore_getopt_parse_callback(parser, desc, value, arg_val);
1270 case ECORE_GETOPT_ACTION_HELP:
1271 return _ecore_getopt_parse_help(parser, desc, value, arg_val);
1272 case ECORE_GETOPT_ACTION_VERSION:
1273 return _ecore_getopt_parse_version(parser, desc, value, arg_val);
1274 case ECORE_GETOPT_ACTION_COPYRIGHT:
1275 return _ecore_getopt_parse_copyright(parser, desc, value, arg_val);
1276 case ECORE_GETOPT_ACTION_LICENSE:
1277 return _ecore_getopt_parse_license(parser, desc, value, arg_val);
1283 static unsigned char
1284 _ecore_getopt_parse_arg_long(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc __UNUSED__, char **argv, int *idx, int *nonargs, const char *arg)
1286 const Ecore_Getopt_Desc *desc;
1287 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1288 const char *arg_val;
1290 Ecore_Getopt_Value *value;
1293 desc = _ecore_getopt_parse_find_long(parser, arg);
1296 fprintf(stderr, _("ERROR: unknown option --%s, ignored.\n"), arg);
1306 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1307 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1309 arg_val = strchr(arg, '=');
1314 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1316 arg_val = argv[*idx];
1323 if (arg_val && arg_val[0] == '\0')
1326 if ((!arg_val) && (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1329 (stderr, _("ERROR: option --%s requires an argument!\n"), arg);
1338 desc_idx = desc - parser->descs;
1339 value = values + desc_idx;
1340 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1341 if ((!ret) && parser->strict)
1347 static unsigned char
1348 _ecore_getopt_parse_arg_short(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc __UNUSED__, char **argv, int *idx, int *nonargs, const char *arg)
1351 while (run && (arg[0] != '\0'))
1354 const Ecore_Getopt_Desc *desc;
1355 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1356 const char *arg_val;
1358 Ecore_Getopt_Value *value;
1361 desc = _ecore_getopt_parse_find_short(parser, arg[0]);
1365 (stderr, _("ERROR: unknown option -%c, ignored.\n"), arg[0]);
1375 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1376 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1383 else if (arg[0] != '\0')
1387 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1389 arg_val = argv[*idx];
1396 if (arg_val && arg_val[0] == '\0')
1400 (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1403 (stderr, _("ERROR: option -%c requires an argument!\n"),
1413 desc_idx = desc - parser->descs;
1414 value = values + desc_idx;
1415 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1416 if ((!ret) && parser->strict)
1426 static unsigned char
1427 _ecore_getopt_parse_arg(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv, int *idx, int *nonargs)
1429 char *arg = argv[*idx];
1433 char **dst, **src, **src_end;
1437 src_end = src + *nonargs - *idx - 1;
1439 for (; src < src_end; src++, dst++)
1448 return _ecore_getopt_parse_arg_long
1449 (parser, values, argc, argv, idx, nonargs, arg + 2);
1451 return _ecore_getopt_parse_arg_short
1452 (parser, values, argc, argv, idx, nonargs, arg + 1);
1455 static const Ecore_Getopt_Desc *
1456 _ecore_getopt_parse_find_short_other(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *orig)
1458 const Ecore_Getopt_Desc *desc = parser->descs;
1459 const char c = orig->shortname;
1461 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1466 if (c == desc->shortname)
1473 static const Ecore_Getopt_Desc *
1474 _ecore_getopt_parse_find_long_other(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *orig)
1476 const Ecore_Getopt_Desc *desc = parser->descs;
1477 const char *name = orig->longname;
1479 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1484 if (desc->longname && (strcmp(name, desc->longname) == 0))
1492 * Check parser for duplicate entries, print them out.
1494 * @return 1 if there are duplicates, 0 otherwise.
1497 ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser)
1499 const Ecore_Getopt_Desc *desc = parser->descs;
1500 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1502 if (desc->shortname)
1504 const Ecore_Getopt_Desc *other;
1505 other = _ecore_getopt_parse_find_short_other(parser, desc);
1508 _ecore_getopt_desc_print_error
1509 (desc, "short name -%c already exists.", desc->shortname);
1511 if (other->longname)
1512 fprintf(stderr, " Other is --%s.\n", other->longname);
1514 fputc('\n', stderr);
1521 const Ecore_Getopt_Desc *other;
1522 other = _ecore_getopt_parse_find_long_other(parser, desc);
1525 _ecore_getopt_desc_print_error
1526 (desc, "long name --%s already exists.", desc->longname);
1528 if (other->shortname)
1529 fprintf(stderr, " Other is -%c.\n", other->shortname);
1531 fputc('\n', stderr);
1539 static const Ecore_Getopt_Desc *
1540 _ecore_getopt_find_help(const Ecore_Getopt *parser)
1542 const Ecore_Getopt_Desc *desc = parser->descs;
1543 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1544 if (desc->action == ECORE_GETOPT_ACTION_HELP)
1550 * Parse command line parameters.
1552 * Walks the command line parameters and parse them based on @a parser
1553 * description, doing actions based on @c parser->descs->action, like
1554 * showing help text, license, copyright, storing values in values and
1557 * It is expected that values is of the same size than @c parser->descs,
1558 * options that do not need a value it will be left untouched.
1560 * All values are expected to be initialized before use. Options with
1561 * action @c ECORE_GETOPT_ACTION_STORE and non required arguments
1562 * (others than @c ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES), are expected
1563 * to provide a value in @c def to be used.
1565 * The following actions will store 1 on value as a boolean
1566 * (@c value->boolp) if it's not NULL to indicate these actions were executed:
1567 * - @c ECORE_GETOPT_ACTION_HELP
1568 * - @c ECORE_GETOPT_ACTION_VERSION
1569 * - @c ECORE_GETOPT_ACTION_COPYRIGHT
1570 * - @c ECORE_GETOPT_ACTION_LICENSE
1572 * Just @c ECORE_GETOPT_ACTION_APPEND will allocate memory and thus
1573 * need to be freed. For consistency between all of appended subtypes,
1574 * @c eina_list->data will contain an allocated memory with the value,
1575 * that is, for @c ECORE_GETOPT_TYPE_STR it will contain a copy of the
1576 * argument, @c ECORE_GETOPT_TYPE_INT a pointer to an allocated
1577 * integer and so on.
1579 * If parser is in strict mode (see @c Ecore_Getopt->strict), then any
1580 * error will abort parsing and -1 is returned. Otherwise it will try
1581 * to continue as far as possible.
1583 * This function may reorder @a argv elements.
1585 * Translation of help strings (description), metavar, usage, license
1586 * and copyright may be translated, standard/global gettext() call
1587 * will be applied on them if ecore was compiled with such support.
1589 * @param parser description of how to work.
1590 * @param value where to store values, it is assumed that this is a vector
1591 * of the same size as @c parser->descs. Values should be previously
1593 * @param argc how many elements in @a argv. If not provided it will be
1594 * retrieved with ecore_app_args_get().
1595 * @param argv command line parameters.
1597 * @return index of first non-option parameter or -1 on error.
1600 ecore_getopt_parse(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv)
1606 fputs(_("ERROR: no parser provided.\n"), stderr);
1611 fputs(_("ERROR: no values provided.\n"), stderr);
1615 if ((argc < 1) || (argv == NULL))
1616 ecore_app_args_get(&argc, &argv);
1620 fputs(_("ERROR: no arguments provided.\n"), stderr);
1624 if (argv[0] != NULL)
1627 prog = parser->prog;
1629 nonargs = _ecore_getopt_parse_find_nonargs_base(parser, argc, argv);
1638 if (!_ecore_getopt_parse_arg(parser, values, argc, argv, &i, &nonargs))
1645 const Ecore_Getopt_Desc *help;
1646 fputs(_("ERROR: invalid options found."), stderr);
1648 help = _ecore_getopt_find_help(parser);
1650 fputc('\n', stderr);
1651 else if (help->longname)
1652 fprintf(stderr, _(" See --%s.\n"), help->longname);
1654 fprintf(stderr, _(" See -%c.\n"), help->shortname);
1661 * Utility to free list and nodes allocated by @a ECORE_GETOPT_ACTION_APPEND.
1663 * @param list pointer to list to be freed.
1664 * @return always NULL, so you can easily make your list head NULL.
1667 ecore_getopt_list_free(Eina_List *list)
1671 EINA_LIST_FREE(list, data)
1677 * Helper ecore_getopt callback to parse geometry (x:y:w:h).
1679 * Storage must be a pointer to @c Eina_Rectangle and will be used to
1680 * store the four values passed in the given string.
1682 * @c callback_data value is ignored, you can safely use @c NULL.
1685 ecore_getopt_callback_geometry_parse(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc __UNUSED__, const char *str, void *data __UNUSED__, Ecore_Getopt_Value *storage)
1687 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1689 if (sscanf(str, "%d:%d:%d:%d", &v->x, &v->y, &v->w, &v->h) != 4)
1691 fprintf(stderr, _("ERROR: incorrect geometry value '%s'\n"), str);
1699 * Helper ecore_getopt callback to parse geometry size (WxH).
1701 * Storage must be a pointer to @c Eina_Rectangle and will be used to
1702 * store the two values passed in the given string and 0 in the x and y
1705 * @c callback_data value is ignored, you can safely use @c NULL.
1708 ecore_getopt_callback_size_parse(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc __UNUSED__, const char *str, void *data __UNUSED__, Ecore_Getopt_Value *storage)
1710 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1712 if (sscanf(str, "%dx%d", &v->w, &v->h) != 2)
1714 fprintf(stderr, _("ERROR: incorrect size value '%s'\n"), str);