2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
11 #elif defined __GNUC__
12 # define alloca __builtin_alloca
14 # define alloca __alloca
15 #elif defined _MSC_VER
17 # define alloca _alloca
23 void *alloca (size_t);
34 # define gettext(x) (x)
35 # define dgettext(domain, x) (x)
38 #define _(x) dgettext("ecore", x)
45 #include "Ecore_Getopt.h"
47 static const char *prog = NULL;
48 static char **argv = NULL;
51 static int helpcol = 80 / 3;
54 _ecore_getopt_help_print_replace_program(FILE *fp, const Ecore_Getopt *parser __UNUSED__, const char *text)
58 const char *d = strchr(text, '%');
66 if (fwrite(text, 1, d - text, fp) != (size_t)(d - text))
69 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
71 fputs(prog ? prog : "???", fp);
72 d += sizeof("prog") - 1;
83 while (text[0] != '\0');
89 _ecore_getopt_version(FILE *fp, const Ecore_Getopt *parser)
91 fputs(_("Version:"), fp);
93 _ecore_getopt_help_print_replace_program(fp, parser, parser->version);
97 _ecore_getopt_help_usage(FILE *fp, const Ecore_Getopt *parser)
99 fputs(_("Usage:"), fp);
104 fprintf(fp, _("%s [options]\n"), prog);
108 _ecore_getopt_help_print_replace_program(fp, parser, gettext(parser->usage));
112 _ecore_getopt_help_line(FILE *fp, const int base, const int total, int used, const char *text, int len)
117 /* process line considering spaces (new line and tabs are spaces!) */
118 while ((used < total) && (len > 0))
120 const char *space = NULL;
127 for (i = 0; i < todo; i++)
128 if (isspace(text[i]))
136 i = fwrite(text, 1, i, fp);
148 if (space[0] == '\n')
150 else if (space[0] == '\t')
155 c = ((used / 8) + 1) * 8;
158 for (; used < c; used++)
168 else if (used < total)
173 i = fwrite(text, 1, i, fp);
184 for (used = 0; used < base; used++)
193 _ecore_getopt_help_description(FILE *fp, const Ecore_Getopt *parser)
195 const char *p, *prg, *ver;
196 int used, prglen, verlen;
198 p = gettext(parser->description);
204 prg = prog ? prog : "???";
205 ver = parser->version ? parser->version : "???";
207 prglen = strlen(prg);
208 verlen = strlen(ver);
214 const char *d = strchr(p, '%');
218 _ecore_getopt_help_line(fp, 0, cols, used, p, strlen(p));
222 used = _ecore_getopt_help_line(fp, 0, cols, used, p, d - p);
224 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
226 used = _ecore_getopt_help_line(fp, 0, cols, used, prg, prglen);
227 d += sizeof("prog") - 1;
229 else if (strncmp(d, "version", sizeof("version") - 1) == 0)
231 used = _ecore_getopt_help_line(fp, 0, cols, used, ver, verlen);
232 d += sizeof("version") - 1;
238 used = _ecore_getopt_help_line(fp, 0, cols, used, "%", 1);
243 while (p[0] != '\0');
249 _ecore_getopt_copyright(FILE *fp, const Ecore_Getopt *parser)
251 const char *txt = gettext(parser->copyright);
252 fputs(_("Copyright:"), fp);
254 _ecore_getopt_help_line
255 (fp, 3, cols, 3, txt, strlen(txt));
260 _ecore_getopt_license(FILE *fp, const Ecore_Getopt *parser)
262 const char *txt = gettext(parser->license);
263 fputs(_("License:"), fp);
265 _ecore_getopt_help_line
266 (fp, 3, cols, 3, txt, strlen(txt));
270 static Ecore_Getopt_Desc_Arg_Requirement
271 _ecore_getopt_desc_arg_requirement(const Ecore_Getopt_Desc *desc)
273 switch (desc->action)
275 case ECORE_GETOPT_ACTION_STORE:
276 return desc->action_param.store.arg_req;
277 case ECORE_GETOPT_ACTION_STORE_CONST:
278 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
279 case ECORE_GETOPT_ACTION_STORE_TRUE:
280 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
281 case ECORE_GETOPT_ACTION_STORE_FALSE:
282 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
283 case ECORE_GETOPT_ACTION_CHOICE:
284 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
285 case ECORE_GETOPT_ACTION_APPEND:
286 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
287 case ECORE_GETOPT_ACTION_COUNT:
288 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
289 case ECORE_GETOPT_ACTION_CALLBACK:
290 return desc->action_param.callback.arg_req;
291 case ECORE_GETOPT_ACTION_HELP:
292 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
293 case ECORE_GETOPT_ACTION_VERSION:
294 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
296 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
301 _ecore_getopt_help_desc_setup_metavar(const Ecore_Getopt_Desc *desc, char *metavar, int *metavarlen, int maxsize)
305 const char *txt = gettext(desc->metavar);
306 *metavarlen = strlen(txt);
307 if (*metavarlen > maxsize - 1)
308 *metavarlen = maxsize - 1;
310 memcpy(metavar, txt, *metavarlen);
311 metavar[*metavarlen] = '\0';
313 else if (desc->longname)
317 *metavarlen = strlen(desc->longname);
318 if (*metavarlen > maxsize - 1)
319 *metavarlen = maxsize - 1;
321 for (i = 0; i < *metavarlen; i++)
322 metavar[i] = toupper(desc->longname[i]);
328 _ecore_getopt_help_desc_show_arg(FILE *fp, Ecore_Getopt_Desc_Arg_Requirement requirement, const char *metavar, int metavarlen)
332 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
337 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
343 if (requirement != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
347 used += metavarlen + 1;
350 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
360 _ecore_getopt_help_desc_store(FILE *fp, const int base, const int total, int used, const Ecore_Getopt_Desc *desc)
362 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
368 for (used = 0; used < base; used++)
373 case ECORE_GETOPT_TYPE_STR:
375 len = sizeof("STR") - 1;
377 case ECORE_GETOPT_TYPE_BOOL:
379 len = sizeof("BOOL") - 1;
381 case ECORE_GETOPT_TYPE_SHORT:
383 len = sizeof("SHORT") - 1;
385 case ECORE_GETOPT_TYPE_INT:
387 len = sizeof("INT") - 1;
389 case ECORE_GETOPT_TYPE_LONG:
391 len = sizeof("LONG") - 1;
393 case ECORE_GETOPT_TYPE_USHORT:
395 len = sizeof("USHORT") - 1;
397 case ECORE_GETOPT_TYPE_UINT:
399 len = sizeof("UINT") - 1;
401 case ECORE_GETOPT_TYPE_ULONG:
403 len = sizeof("ULONG") - 1;
405 case ECORE_GETOPT_TYPE_DOUBLE:
407 len = sizeof("DOUBLE") - 1;
411 len = sizeof("???") - 1;
414 used = _ecore_getopt_help_line
415 (fp, base, total, used, _("Type: "), strlen(_("Type: ")));
416 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
418 if (store->arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES)
421 used = _ecore_getopt_help_line
422 (fp, base, total, used, ". ", sizeof(". ") - 1);
426 case ECORE_GETOPT_TYPE_STR:
427 str = store->def.strv;
428 len = str ? strlen(str) : 0;
430 case ECORE_GETOPT_TYPE_BOOL:
431 str = store->def.boolv ? "true" : "false";
434 case ECORE_GETOPT_TYPE_SHORT:
436 len = snprintf(buf, sizeof(buf), "%hd", store->def.shortv);
437 if (len > sizeof(buf) - 1)
438 len = sizeof(buf) - 1;
440 case ECORE_GETOPT_TYPE_INT:
442 len = snprintf(buf, sizeof(buf), "%d", store->def.intv);
443 if (len > sizeof(buf) - 1)
444 len = sizeof(buf) - 1;
446 case ECORE_GETOPT_TYPE_LONG:
448 len = snprintf(buf, sizeof(buf), "%ld", store->def.longv);
449 if (len > sizeof(buf) - 1)
450 len = sizeof(buf) - 1;
452 case ECORE_GETOPT_TYPE_USHORT:
454 len = snprintf(buf, sizeof(buf), "%hu", store->def.ushortv);
455 if (len > sizeof(buf) - 1)
456 len = sizeof(buf) - 1;
458 case ECORE_GETOPT_TYPE_UINT:
460 len = snprintf(buf, sizeof(buf), "%u", store->def.uintv);
461 if (len > sizeof(buf) - 1)
462 len = sizeof(buf) - 1;
464 case ECORE_GETOPT_TYPE_ULONG:
466 len = snprintf(buf, sizeof(buf), "%lu", store->def.ulongv);
467 if (len > sizeof(buf) - 1)
468 len = sizeof(buf) - 1;
470 case ECORE_GETOPT_TYPE_DOUBLE:
472 len = snprintf(buf, sizeof(buf), "%f", store->def.doublev);
473 if (len > sizeof(buf) - 1)
474 len = sizeof(buf) - 1;
478 len = sizeof("???") - 1;
481 used = _ecore_getopt_help_line
482 (fp, base, total, used, _("Default: "), strlen(_("Default: ")));
483 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
486 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
490 _ecore_getopt_help_desc_choices(FILE *fp, const int base, const int total, int used, const Ecore_Getopt_Desc *desc)
492 const char *const *itr;
493 const char sep[] = ", ";
494 const int seplen = sizeof(sep) - 1;
501 for (; used < base; used++)
504 used = _ecore_getopt_help_line
505 (fp, base, total, used, _("Choices: "), strlen(_("Choices: ")));
507 for (itr = desc->action_param.choices; *itr != NULL; itr++)
509 used = _ecore_getopt_help_line
510 (fp, base, total, used, *itr, strlen(*itr));
512 used = _ecore_getopt_help_line(fp, base, total, used, sep, seplen);
515 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
519 _ecore_getopt_help_desc(FILE *fp, const Ecore_Getopt_Desc *desc)
521 Ecore_Getopt_Desc_Arg_Requirement arg_req;
522 char metavar[32] = "ARG";
526 arg_req = _ecore_getopt_desc_arg_requirement(desc);
527 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
528 _ecore_getopt_help_desc_setup_metavar
529 (desc, metavar, &metavarlen, sizeof(metavar));
537 fputc(desc->shortname, fp);
539 used += _ecore_getopt_help_desc_show_arg
540 (fp, arg_req, metavar, metavarlen);
543 if (desc->shortname && desc->longname)
551 int namelen = strlen(desc->longname);
554 fputs(desc->longname, fp);
556 used += _ecore_getopt_help_desc_show_arg
557 (fp, arg_req, metavar, metavarlen);
563 if (used + 3 >= helpcol)
569 for (; used < helpcol; used++)
572 used = _ecore_getopt_help_line
573 (fp, helpcol, cols, used, desc->help, strlen(desc->help));
575 switch (desc->action)
577 case ECORE_GETOPT_ACTION_STORE:
578 _ecore_getopt_help_desc_store(fp, helpcol, cols, used, desc);
580 case ECORE_GETOPT_ACTION_CHOICE:
581 _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc);
592 _ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc)
594 return (desc->shortname == '\0') && (desc->longname == NULL);
598 _ecore_getopt_help_options(FILE *fp, const Ecore_Getopt *parser)
600 const Ecore_Getopt_Desc *desc;
602 fputs(_("Options:\n"), fp);
604 for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
605 _ecore_getopt_help_desc(fp, desc);
611 * Show nicely formatted help message for the given parser.
613 * Message will be print to stderr.
616 ecore_getopt_help(FILE *fp, const Ecore_Getopt *parser)
624 ecore_app_args_get(&argc, &argv);
625 if ((argc > 0) && (argv[0] != NULL))
631 var = getenv("COLUMNS");
641 _ecore_getopt_help_usage(fp, parser);
642 _ecore_getopt_help_description(fp, parser);
643 _ecore_getopt_help_options(fp, parser);
646 static const Ecore_Getopt_Desc *
647 _ecore_getopt_parse_find_long(const Ecore_Getopt *parser, const char *name)
649 const Ecore_Getopt_Desc *desc = parser->descs;
650 const char *p = strchr(name, '=');
656 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
663 if ((strncmp(name, desc->longname, len) == 0) &&
664 (desc->longname[len] == '\0'))
669 if (strcmp(name, desc->longname) == 0)
677 static const Ecore_Getopt_Desc *
678 _ecore_getopt_parse_find_short(const Ecore_Getopt *parser, char name)
680 const Ecore_Getopt_Desc *desc = parser->descs;
681 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
682 if (name == desc->shortname)
688 _ecore_getopt_parse_find_nonargs_base(const Ecore_Getopt *parser, int argc, char **argv)
691 int src, dst, used, base;
693 nonargs = alloca(sizeof(char*) * argc);
700 const Ecore_Getopt_Desc *desc;
701 Ecore_Getopt_Desc_Arg_Requirement arg_req;
702 char *arg = argv[src];
709 if (arg[2] == '\0') /* explicit end of options, "--" */
714 desc = _ecore_getopt_parse_find_long(parser, arg + 2);
717 desc = _ecore_getopt_parse_find_short(parser, arg[1]);
722 fprintf(stderr, _("ERROR: unknown option --%s.\n"), arg + 2);
724 fprintf(stderr, _("ERROR: unknown option -%c.\n"), arg[1]);
727 memmove(argv + dst, nonargs, used * sizeof(char *));
735 argv[dst] = argv[src];
739 arg_req = _ecore_getopt_desc_arg_requirement(desc);
740 if (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
743 if (strchr(arg, '='))
746 if ((src >= argc) || (argv[src][0] == '-'))
750 argv[dst] = argv[src];
761 if (!base) /* '--' not found */
767 argv[dst] = argv[src];
771 memmove(argv + dst, nonargs, used * sizeof(char *));
776 _ecore_getopt_desc_print_error(const Ecore_Getopt_Desc *desc, const char *fmt, ...)
780 fputs(_("ERROR: "), stderr);
785 fputc(desc->shortname, stderr);
788 if (desc->shortname && desc->longname)
794 fputs(desc->longname, stderr);
800 vfprintf(stderr, fmt, ap);
805 _ecore_getopt_parse_bool(const char *str, unsigned char *v)
807 if ((strcmp(str, "0") == 0) ||
808 (strcasecmp(str, "f") == 0) ||
809 (strcasecmp(str, "false") == 0) ||
810 (strcasecmp(str, "no") == 0) ||
811 (strcasecmp(str, "off") == 0)
817 else if ((strcmp(str, "1") == 0) ||
818 (strcasecmp(str, "t") == 0) ||
819 (strcasecmp(str, "true") == 0) ||
820 (strcasecmp(str, "yes") == 0) ||
821 (strcasecmp(str, "on") == 0)
832 _ecore_getopt_parse_long(const char *str, long int *v)
835 *v = strtol(str, &endptr, 0);
840 _ecore_getopt_parse_double(const char *str, double *v)
843 *v = strtod(str, &endptr);
848 _ecore_getopt_parse_store(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *value, const char *arg_val)
850 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
857 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
861 switch (store->arg_req)
863 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
865 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
868 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
874 case ECORE_GETOPT_TYPE_STR:
875 *value->strp = (char *)arg_val;
877 case ECORE_GETOPT_TYPE_BOOL:
878 if (_ecore_getopt_parse_bool(arg_val, &b))
885 _ecore_getopt_desc_print_error
886 (desc, _("unknown boolean value %s.\n"), arg_val);
889 case ECORE_GETOPT_TYPE_SHORT:
890 if (!_ecore_getopt_parse_long(arg_val, &v))
894 case ECORE_GETOPT_TYPE_INT:
895 if (!_ecore_getopt_parse_long(arg_val, &v))
899 case ECORE_GETOPT_TYPE_LONG:
900 if (!_ecore_getopt_parse_long(arg_val, &v))
904 case ECORE_GETOPT_TYPE_USHORT:
905 if (!_ecore_getopt_parse_long(arg_val, &v))
909 case ECORE_GETOPT_TYPE_UINT:
910 if (!_ecore_getopt_parse_long(arg_val, &v))
914 case ECORE_GETOPT_TYPE_ULONG:
915 if (!_ecore_getopt_parse_long(arg_val, &v))
919 case ECORE_GETOPT_TYPE_DOUBLE:
920 if (!_ecore_getopt_parse_double(arg_val, &d))
929 _ecore_getopt_desc_print_error
930 (desc, _("invalid number format %s\n"), arg_val);
936 case ECORE_GETOPT_TYPE_STR:
937 *value->strp = (char *)store->def.strv;
939 case ECORE_GETOPT_TYPE_BOOL:
940 *value->boolp = store->def.boolv;
942 case ECORE_GETOPT_TYPE_SHORT:
943 *value->shortp = store->def.shortv;
945 case ECORE_GETOPT_TYPE_INT:
946 *value->intp = store->def.intv;
948 case ECORE_GETOPT_TYPE_LONG:
949 *value->longp = store->def.longv;
951 case ECORE_GETOPT_TYPE_USHORT:
952 *value->ushortp = store->def.ushortv;
954 case ECORE_GETOPT_TYPE_UINT:
955 *value->uintp = store->def.uintv;
957 case ECORE_GETOPT_TYPE_ULONG:
958 *value->ulongp = store->def.ulongv;
960 case ECORE_GETOPT_TYPE_DOUBLE:
961 *value->doublep = store->def.doublev;
969 _ecore_getopt_parse_store_const(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
973 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
977 *val->ptrp = (void *)desc->action_param.store_const;
982 _ecore_getopt_parse_store_true(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
986 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
994 _ecore_getopt_parse_store_false(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
998 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1005 static unsigned char
1006 _ecore_getopt_parse_choice(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
1008 const char * const *pchoice;
1012 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1016 pchoice = desc->action_param.choices;
1017 for (; *pchoice != NULL; pchoice++)
1018 if (strcmp(*pchoice, arg_val) == 0)
1020 *val->strp = (char *)*pchoice;
1024 _ecore_getopt_desc_print_error
1025 (desc, _("invalid choice \"%s\". Valid values are: "), arg_val);
1027 pchoice = desc->action_param.choices;
1028 for (; *pchoice != NULL; pchoice++)
1030 fputs(*pchoice, stderr);
1031 if (pchoice[1] != NULL)
1032 fputs(", ", stderr);
1035 fputs(".\n", stderr);
1039 static unsigned char
1040 _ecore_getopt_parse_append(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
1049 _ecore_getopt_desc_print_error
1050 (desc, _("missing parameter to append.\n"));
1056 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1060 switch (desc->action_param.append_type)
1062 case ECORE_GETOPT_TYPE_STR:
1063 data = strdup(arg_val);
1065 case ECORE_GETOPT_TYPE_BOOL:
1067 if (_ecore_getopt_parse_bool(arg_val, &b))
1069 data = malloc(sizeof(unsigned char));
1071 *(unsigned char *)data = b;
1075 _ecore_getopt_desc_print_error
1076 (desc, _("unknown boolean value %s.\n"), arg_val);
1081 case ECORE_GETOPT_TYPE_SHORT:
1083 if (!_ecore_getopt_parse_long(arg_val, &v))
1085 data = malloc(sizeof(short));
1087 *(short *)data = (short)v;
1090 case ECORE_GETOPT_TYPE_INT:
1092 if (!_ecore_getopt_parse_long(arg_val, &v))
1094 data = malloc(sizeof(int));
1096 *(int *)data = (int)v;
1099 case ECORE_GETOPT_TYPE_LONG:
1101 if (!_ecore_getopt_parse_long(arg_val, &v))
1103 data = malloc(sizeof(long));
1108 case ECORE_GETOPT_TYPE_USHORT:
1110 if (!_ecore_getopt_parse_long(arg_val, &v))
1112 data = malloc(sizeof(unsigned short));
1114 *(unsigned short *)data = (unsigned short)v;
1117 case ECORE_GETOPT_TYPE_UINT:
1119 if (!_ecore_getopt_parse_long(arg_val, &v))
1121 data = malloc(sizeof(unsigned int));
1123 *(unsigned int *)data = (unsigned int)v;
1126 case ECORE_GETOPT_TYPE_ULONG:
1128 if (!_ecore_getopt_parse_long(arg_val, &v))
1130 data = malloc(sizeof(unsigned long));
1132 *(unsigned long *)data = v;
1135 case ECORE_GETOPT_TYPE_DOUBLE:
1137 if (!_ecore_getopt_parse_double(arg_val, &d))
1139 data = malloc(sizeof(double));
1141 *(double *)data = d;
1146 _ecore_getopt_desc_print_error(desc, _("could not parse value.\n"));
1151 *val->listp = eina_list_append(*val->listp, data);
1155 _ecore_getopt_desc_print_error
1156 (desc, _("invalid number format %s\n"), arg_val);
1160 static unsigned char
1161 _ecore_getopt_parse_count(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1165 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1173 static unsigned char
1174 _ecore_getopt_parse_callback(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
1176 const Ecore_Getopt_Desc_Callback *cb = &desc->action_param.callback;
1178 switch (cb->arg_req)
1180 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
1183 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
1187 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
1191 if (cb->arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1193 if ((!arg_val) || (arg_val[0] == '\0'))
1195 _ecore_getopt_desc_print_error(desc, _("missing parameter.\n"));
1201 _ecore_getopt_desc_print_error
1202 (desc, _("value has no pointer set.\n"));
1209 _ecore_getopt_desc_print_error(desc, _("missing callback function!\n"));
1213 return cb->func(parser, desc, arg_val, (void *)cb->data, val);
1216 static unsigned char
1217 _ecore_getopt_parse_help(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc __UNUSED__, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1221 ecore_getopt_help(stdout, parser);
1225 static unsigned char
1226 _ecore_getopt_parse_version(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1230 if (!parser->version)
1232 _ecore_getopt_desc_print_error(desc, _("no version was defined.\n"));
1235 _ecore_getopt_version(stdout, parser);
1239 static unsigned char
1240 _ecore_getopt_parse_copyright(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1244 if (!parser->copyright)
1246 _ecore_getopt_desc_print_error(desc, _("no copyright was defined.\n"));
1249 _ecore_getopt_copyright(stdout, parser);
1253 static unsigned char
1254 _ecore_getopt_parse_license(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1258 if (!parser->license)
1260 _ecore_getopt_desc_print_error(desc, _("no license was defined.\n"));
1263 _ecore_getopt_license(stdout, parser);
1267 static unsigned char
1268 _ecore_getopt_desc_handle(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *value, const char *arg_val)
1270 switch (desc->action)
1272 case ECORE_GETOPT_ACTION_STORE:
1273 return _ecore_getopt_parse_store(parser, desc, value, arg_val);
1274 case ECORE_GETOPT_ACTION_STORE_CONST:
1275 return _ecore_getopt_parse_store_const(parser, desc, value, arg_val);
1276 case ECORE_GETOPT_ACTION_STORE_TRUE:
1277 return _ecore_getopt_parse_store_true(parser, desc, value, arg_val);
1278 case ECORE_GETOPT_ACTION_STORE_FALSE:
1279 return _ecore_getopt_parse_store_false(parser, desc, value, arg_val);
1280 case ECORE_GETOPT_ACTION_CHOICE:
1281 return _ecore_getopt_parse_choice(parser, desc, value, arg_val);
1282 case ECORE_GETOPT_ACTION_APPEND:
1283 return _ecore_getopt_parse_append(parser, desc, value, arg_val);
1284 case ECORE_GETOPT_ACTION_COUNT:
1285 return _ecore_getopt_parse_count(parser, desc, value, arg_val);
1286 case ECORE_GETOPT_ACTION_CALLBACK:
1287 return _ecore_getopt_parse_callback(parser, desc, value, arg_val);
1288 case ECORE_GETOPT_ACTION_HELP:
1289 return _ecore_getopt_parse_help(parser, desc, value, arg_val);
1290 case ECORE_GETOPT_ACTION_VERSION:
1291 return _ecore_getopt_parse_version(parser, desc, value, arg_val);
1292 case ECORE_GETOPT_ACTION_COPYRIGHT:
1293 return _ecore_getopt_parse_copyright(parser, desc, value, arg_val);
1294 case ECORE_GETOPT_ACTION_LICENSE:
1295 return _ecore_getopt_parse_license(parser, desc, value, arg_val);
1301 static unsigned char
1302 _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)
1304 const Ecore_Getopt_Desc *desc;
1305 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1306 const char *arg_val;
1308 Ecore_Getopt_Value *value;
1311 desc = _ecore_getopt_parse_find_long(parser, arg);
1314 fprintf(stderr, _("ERROR: unknown option --%s, ignored.\n"), arg);
1324 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1325 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1327 arg_val = strchr(arg, '=');
1332 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1334 arg_val = argv[*idx];
1341 if (arg_val && arg_val[0] == '\0')
1344 if ((!arg_val) && (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1347 (stderr, _("ERROR: option --%s requires an argument!\n"), arg);
1356 desc_idx = desc - parser->descs;
1357 value = values + desc_idx;
1358 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1359 if ((!ret) && parser->strict)
1365 static unsigned char
1366 _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)
1369 while (run && (arg[0] != '\0'))
1372 const Ecore_Getopt_Desc *desc;
1373 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1374 const char *arg_val;
1376 Ecore_Getopt_Value *value;
1379 desc = _ecore_getopt_parse_find_short(parser, arg[0]);
1383 (stderr, _("ERROR: unknown option -%c, ignored.\n"), arg[0]);
1393 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1394 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1401 else if (arg[0] != '\0')
1405 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1407 arg_val = argv[*idx];
1414 if (arg_val && arg_val[0] == '\0')
1418 (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1421 (stderr, _("ERROR: option -%c requires an argument!\n"),
1431 desc_idx = desc - parser->descs;
1432 value = values + desc_idx;
1433 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1434 if ((!ret) && parser->strict)
1444 static unsigned char
1445 _ecore_getopt_parse_arg(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv, int *idx, int *nonargs)
1447 char *arg = argv[*idx];
1451 char **dst, **src, **src_end;
1455 src_end = src + *nonargs - *idx - 1;
1457 for (; src < src_end; src++, dst++)
1466 return _ecore_getopt_parse_arg_long
1467 (parser, values, argc, argv, idx, nonargs, arg + 2);
1469 return _ecore_getopt_parse_arg_short
1470 (parser, values, argc, argv, idx, nonargs, arg + 1);
1473 static const Ecore_Getopt_Desc *
1474 _ecore_getopt_parse_find_short_other(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *orig)
1476 const Ecore_Getopt_Desc *desc = parser->descs;
1477 const char c = orig->shortname;
1479 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1484 if (c == desc->shortname)
1491 static const Ecore_Getopt_Desc *
1492 _ecore_getopt_parse_find_long_other(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *orig)
1494 const Ecore_Getopt_Desc *desc = parser->descs;
1495 const char *name = orig->longname;
1497 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1502 if (desc->longname && (strcmp(name, desc->longname) == 0))
1510 * Check parser for duplicate entries, print them out.
1512 * @return 1 if there are duplicates, 0 otherwise.
1515 ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser)
1517 const Ecore_Getopt_Desc *desc = parser->descs;
1518 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1520 if (desc->shortname)
1522 const Ecore_Getopt_Desc *other;
1523 other = _ecore_getopt_parse_find_short_other(parser, desc);
1526 _ecore_getopt_desc_print_error
1527 (desc, "short name -%c already exists.", desc->shortname);
1529 if (other->longname)
1530 fprintf(stderr, " Other is --%s.\n", other->longname);
1532 fputc('\n', stderr);
1539 const Ecore_Getopt_Desc *other;
1540 other = _ecore_getopt_parse_find_long_other(parser, desc);
1543 _ecore_getopt_desc_print_error
1544 (desc, "long name --%s already exists.", desc->longname);
1546 if (other->shortname)
1547 fprintf(stderr, " Other is -%c.\n", other->shortname);
1549 fputc('\n', stderr);
1557 static const Ecore_Getopt_Desc *
1558 _ecore_getopt_find_help(const Ecore_Getopt *parser)
1560 const Ecore_Getopt_Desc *desc = parser->descs;
1561 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1562 if (desc->action == ECORE_GETOPT_ACTION_HELP)
1568 * Parse command line parameters.
1570 * Walks the command line parameters and parse them based on @a parser
1571 * description, doing actions based on @c parser->descs->action, like
1572 * showing help text, license, copyright, storing values in values and
1575 * It is expected that values is of the same size than @c parser->descs,
1576 * options that do not need a value it will be left untouched.
1578 * All values are expected to be initialized before use. Options with
1579 * action @c ECORE_GETOPT_ACTION_STORE and non required arguments
1580 * (others than @c ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES), are expected
1581 * to provide a value in @c def to be used.
1583 * The following actions will store 1 on value as a boolean
1584 * (@c value->boolp) if it's not NULL to indicate these actions were executed:
1585 * - @c ECORE_GETOPT_ACTION_HELP
1586 * - @c ECORE_GETOPT_ACTION_VERSION
1587 * - @c ECORE_GETOPT_ACTION_COPYRIGHT
1588 * - @c ECORE_GETOPT_ACTION_LICENSE
1590 * Just @c ECORE_GETOPT_ACTION_APPEND will allocate memory and thus
1591 * need to be freed. For consistency between all of appended subtypes,
1592 * @c eina_list->data will contain an allocated memory with the value,
1593 * that is, for @c ECORE_GETOPT_TYPE_STR it will contain a copy of the
1594 * argument, @c ECORE_GETOPT_TYPE_INT a pointer to an allocated
1595 * integer and so on.
1597 * If parser is in strict mode (see @c Ecore_Getopt->strict), then any
1598 * error will abort parsing and -1 is returned. Otherwise it will try
1599 * to continue as far as possible.
1601 * This function may reorder @a argv elements.
1603 * Translation of help strings (description), metavar, usage, license
1604 * and copyright may be translated, standard/global gettext() call
1605 * will be applied on them if ecore was compiled with such support.
1607 * @param parser description of how to work.
1608 * @param value where to store values, it is assumed that this is a vector
1609 * of the same size as @c parser->descs. Values should be previously
1611 * @param argc how many elements in @a argv. If not provided it will be
1612 * retrieved with ecore_app_args_get().
1613 * @param argv command line parameters.
1615 * @return index of first non-option parameter or -1 on error.
1618 ecore_getopt_parse(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv)
1624 fputs(_("ERROR: no parser provided.\n"), stderr);
1629 fputs(_("ERROR: no values provided.\n"), stderr);
1633 if ((argc < 1) || (argv == NULL))
1634 ecore_app_args_get(&argc, &argv);
1638 fputs(_("ERROR: no arguments provided.\n"), stderr);
1642 if (argv[0] != NULL)
1645 prog = parser->prog;
1647 nonargs = _ecore_getopt_parse_find_nonargs_base(parser, argc, argv);
1656 if (!_ecore_getopt_parse_arg(parser, values, argc, argv, &i, &nonargs))
1663 const Ecore_Getopt_Desc *help;
1664 fputs(_("ERROR: invalid options found."), stderr);
1666 help = _ecore_getopt_find_help(parser);
1668 fputc('\n', stderr);
1669 else if (help->longname)
1670 fprintf(stderr, _(" See --%s.\n"), help->longname);
1672 fprintf(stderr, _(" See -%c.\n"), help->shortname);
1679 * Utility to free list and nodes allocated by @a ECORE_GETOPT_ACTION_APPEND.
1681 * @param list pointer to list to be freed.
1682 * @return always NULL, so you can easily make your list head NULL.
1685 ecore_getopt_list_free(Eina_List *list)
1689 EINA_LIST_FREE(list, data)
1695 * Helper ecore_getopt callback to parse geometry (x:y:w:h).
1697 * Storage must be a pointer to @c Eina_Rectangle and will be used to
1698 * store the four values passed in the given string.
1700 * @c callback_data value is ignored, you can safely use @c NULL.
1703 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)
1705 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1707 if (sscanf(str, "%d:%d:%d:%d", &v->x, &v->y, &v->w, &v->h) != 4)
1709 fprintf(stderr, _("ERROR: incorrect geometry value '%s'\n"), str);
1717 * Helper ecore_getopt callback to parse geometry size (WxH).
1719 * Storage must be a pointer to @c Eina_Rectangle and will be used to
1720 * store the two values passed in the given string and 0 in the x and y
1723 * @c callback_data value is ignored, you can safely use @c NULL.
1726 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)
1728 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1730 if (sscanf(str, "%dx%d", &v->w, &v->h) != 2)
1732 fprintf(stderr, _("ERROR: incorrect size value '%s'\n"), str);