8 # define alloca __builtin_alloca
10 # define alloca __alloca
11 #elif defined _MSC_VER
13 # define alloca _alloca
19 void *alloca (size_t);
30 # define gettext(x) (x)
31 # define dgettext(domain, x) (x)
34 #define _(x) dgettext("ecore", x)
41 #include "Ecore_Getopt.h"
43 static const char *prog = NULL;
44 static char **argv = NULL;
47 static int helpcol = 80 / 3;
50 _ecore_getopt_help_print_replace_program(FILE *fp, const Ecore_Getopt *parser __UNUSED__, const char *text)
54 const char *d = strchr(text, '%');
62 if (fwrite(text, 1, d - text, fp) != (size_t)(d - text))
65 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
67 fputs(prog ? prog : "???", fp);
68 d += sizeof("prog") - 1;
79 while (text[0] != '\0');
85 _ecore_getopt_version(FILE *fp, const Ecore_Getopt *parser)
87 fputs(_("Version:"), fp);
89 _ecore_getopt_help_print_replace_program(fp, parser, parser->version);
93 _ecore_getopt_help_usage(FILE *fp, const Ecore_Getopt *parser)
95 fputs(_("Usage:"), fp);
100 fprintf(fp, _("%s [options]\n"), prog);
104 _ecore_getopt_help_print_replace_program(fp, parser, gettext(parser->usage));
108 _ecore_getopt_help_line(FILE *fp, const int base, const int total, int used, const char *text, int len)
113 /* process line considering spaces (new line and tabs are spaces!) */
114 while ((used < total) && (len > 0))
116 const char *space = NULL;
123 for (i = 0; i < todo; i++)
124 if (isspace(text[i]))
132 i = fwrite(text, 1, i, fp);
144 if (space[0] == '\n')
146 else if (space[0] == '\t')
151 c = ((used / 8) + 1) * 8;
154 for (; used < c; used++)
164 else if (used < total)
169 i = fwrite(text, 1, i, fp);
180 for (used = 0; used < base; used++)
189 _ecore_getopt_help_description(FILE *fp, const Ecore_Getopt *parser)
191 const char *p, *prg, *ver;
192 int used, prglen, verlen;
194 p = gettext(parser->description);
200 prg = prog ? prog : "???";
201 ver = parser->version ? parser->version : "???";
203 prglen = strlen(prg);
204 verlen = strlen(ver);
210 const char *d = strchr(p, '%');
214 _ecore_getopt_help_line(fp, 0, cols, used, p, strlen(p));
218 used = _ecore_getopt_help_line(fp, 0, cols, used, p, d - p);
220 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
222 used = _ecore_getopt_help_line(fp, 0, cols, used, prg, prglen);
223 d += sizeof("prog") - 1;
225 else if (strncmp(d, "version", sizeof("version") - 1) == 0)
227 used = _ecore_getopt_help_line(fp, 0, cols, used, ver, verlen);
228 d += sizeof("version") - 1;
234 used = _ecore_getopt_help_line(fp, 0, cols, used, "%", 1);
239 while (p[0] != '\0');
245 _ecore_getopt_copyright(FILE *fp, const Ecore_Getopt *parser)
247 const char *txt = gettext(parser->copyright);
248 fputs(_("Copyright:"), fp);
250 _ecore_getopt_help_line
251 (fp, 3, cols, 3, txt, strlen(txt));
256 _ecore_getopt_license(FILE *fp, const Ecore_Getopt *parser)
258 const char *txt = gettext(parser->license);
259 fputs(_("License:"), fp);
261 _ecore_getopt_help_line
262 (fp, 3, cols, 3, txt, strlen(txt));
266 static Ecore_Getopt_Desc_Arg_Requirement
267 _ecore_getopt_desc_arg_requirement(const Ecore_Getopt_Desc *desc)
269 switch (desc->action)
271 case ECORE_GETOPT_ACTION_STORE:
272 return desc->action_param.store.arg_req;
273 case ECORE_GETOPT_ACTION_STORE_CONST:
274 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
275 case ECORE_GETOPT_ACTION_STORE_TRUE:
276 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
277 case ECORE_GETOPT_ACTION_STORE_FALSE:
278 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
279 case ECORE_GETOPT_ACTION_CHOICE:
280 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
281 case ECORE_GETOPT_ACTION_APPEND:
282 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
283 case ECORE_GETOPT_ACTION_COUNT:
284 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
285 case ECORE_GETOPT_ACTION_CALLBACK:
286 return desc->action_param.callback.arg_req;
287 case ECORE_GETOPT_ACTION_HELP:
288 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
289 case ECORE_GETOPT_ACTION_VERSION:
290 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
292 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
297 _ecore_getopt_help_desc_setup_metavar(const Ecore_Getopt_Desc *desc, char *metavar, int *metavarlen, int maxsize)
301 const char *txt = gettext(desc->metavar);
302 *metavarlen = strlen(txt);
303 if (*metavarlen > maxsize - 1)
304 *metavarlen = maxsize - 1;
306 memcpy(metavar, txt, *metavarlen);
307 metavar[*metavarlen] = '\0';
309 else if (desc->longname)
313 *metavarlen = strlen(desc->longname);
314 if (*metavarlen > maxsize - 1)
315 *metavarlen = maxsize - 1;
317 for (i = 0; i < *metavarlen; i++)
318 metavar[i] = toupper(desc->longname[i]);
324 _ecore_getopt_help_desc_show_arg(FILE *fp, Ecore_Getopt_Desc_Arg_Requirement requirement, const char *metavar, int metavarlen)
328 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
333 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
339 if (requirement != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
343 used += metavarlen + 1;
346 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
356 _ecore_getopt_help_desc_store(FILE *fp, const int base, const int total, int used, const Ecore_Getopt_Desc *desc)
358 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
364 for (used = 0; used < base; used++)
369 case ECORE_GETOPT_TYPE_STR:
371 len = sizeof("STR") - 1;
373 case ECORE_GETOPT_TYPE_BOOL:
375 len = sizeof("BOOL") - 1;
377 case ECORE_GETOPT_TYPE_SHORT:
379 len = sizeof("SHORT") - 1;
381 case ECORE_GETOPT_TYPE_INT:
383 len = sizeof("INT") - 1;
385 case ECORE_GETOPT_TYPE_LONG:
387 len = sizeof("LONG") - 1;
389 case ECORE_GETOPT_TYPE_USHORT:
391 len = sizeof("USHORT") - 1;
393 case ECORE_GETOPT_TYPE_UINT:
395 len = sizeof("UINT") - 1;
397 case ECORE_GETOPT_TYPE_ULONG:
399 len = sizeof("ULONG") - 1;
401 case ECORE_GETOPT_TYPE_DOUBLE:
403 len = sizeof("DOUBLE") - 1;
407 len = sizeof("???") - 1;
410 used = _ecore_getopt_help_line
411 (fp, base, total, used, _("Type: "), strlen(_("Type: ")));
412 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
414 if (store->arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES)
417 used = _ecore_getopt_help_line
418 (fp, base, total, used, ". ", sizeof(". ") - 1);
422 case ECORE_GETOPT_TYPE_STR:
423 str = store->def.strv;
424 len = str ? strlen(str) : 0;
426 case ECORE_GETOPT_TYPE_BOOL:
427 str = store->def.boolv ? "true" : "false";
430 case ECORE_GETOPT_TYPE_SHORT:
432 len = snprintf(buf, sizeof(buf), "%hd", store->def.shortv);
433 if (len > sizeof(buf) - 1)
434 len = sizeof(buf) - 1;
436 case ECORE_GETOPT_TYPE_INT:
438 len = snprintf(buf, sizeof(buf), "%d", store->def.intv);
439 if (len > sizeof(buf) - 1)
440 len = sizeof(buf) - 1;
442 case ECORE_GETOPT_TYPE_LONG:
444 len = snprintf(buf, sizeof(buf), "%ld", store->def.longv);
445 if (len > sizeof(buf) - 1)
446 len = sizeof(buf) - 1;
448 case ECORE_GETOPT_TYPE_USHORT:
450 len = snprintf(buf, sizeof(buf), "%hu", store->def.ushortv);
451 if (len > sizeof(buf) - 1)
452 len = sizeof(buf) - 1;
454 case ECORE_GETOPT_TYPE_UINT:
456 len = snprintf(buf, sizeof(buf), "%u", store->def.uintv);
457 if (len > sizeof(buf) - 1)
458 len = sizeof(buf) - 1;
460 case ECORE_GETOPT_TYPE_ULONG:
462 len = snprintf(buf, sizeof(buf), "%lu", store->def.ulongv);
463 if (len > sizeof(buf) - 1)
464 len = sizeof(buf) - 1;
466 case ECORE_GETOPT_TYPE_DOUBLE:
468 len = snprintf(buf, sizeof(buf), "%f", store->def.doublev);
469 if (len > sizeof(buf) - 1)
470 len = sizeof(buf) - 1;
474 len = sizeof("???") - 1;
477 used = _ecore_getopt_help_line
478 (fp, base, total, used, _("Default: "), strlen(_("Default: ")));
479 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
482 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
486 _ecore_getopt_help_desc_choices(FILE *fp, const int base, const int total, int used, const Ecore_Getopt_Desc *desc)
488 const char *const *itr;
489 const char sep[] = ", ";
490 const int seplen = sizeof(sep) - 1;
497 for (; used < base; used++)
500 used = _ecore_getopt_help_line
501 (fp, base, total, used, _("Choices: "), strlen(_("Choices: ")));
503 for (itr = desc->action_param.choices; *itr; itr++)
505 used = _ecore_getopt_help_line
506 (fp, base, total, used, *itr, strlen(*itr));
508 used = _ecore_getopt_help_line(fp, base, total, used, sep, seplen);
511 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
515 _ecore_getopt_help_desc(FILE *fp, const Ecore_Getopt_Desc *desc)
517 Ecore_Getopt_Desc_Arg_Requirement arg_req;
518 char metavar[32] = "ARG";
522 arg_req = _ecore_getopt_desc_arg_requirement(desc);
523 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
524 _ecore_getopt_help_desc_setup_metavar
525 (desc, metavar, &metavarlen, sizeof(metavar));
533 fputc(desc->shortname, fp);
535 used += _ecore_getopt_help_desc_show_arg
536 (fp, arg_req, metavar, metavarlen);
539 if (desc->shortname && desc->longname)
547 int namelen = strlen(desc->longname);
550 fputs(desc->longname, fp);
552 used += _ecore_getopt_help_desc_show_arg
553 (fp, arg_req, metavar, metavarlen);
559 if (used + 3 >= helpcol)
565 for (; used < helpcol; used++)
568 used = _ecore_getopt_help_line
569 (fp, helpcol, cols, used, desc->help, strlen(desc->help));
571 switch (desc->action)
573 case ECORE_GETOPT_ACTION_STORE:
574 _ecore_getopt_help_desc_store(fp, helpcol, cols, used, desc);
576 case ECORE_GETOPT_ACTION_CHOICE:
577 _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc);
588 _ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc)
590 return (desc->shortname == '\0') && (!desc->longname);
594 _ecore_getopt_help_options(FILE *fp, const Ecore_Getopt *parser)
596 const Ecore_Getopt_Desc *desc;
598 fputs(_("Options:\n"), fp);
600 for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
601 _ecore_getopt_help_desc(fp, desc);
607 * Show nicely formatted help message for the given parser.
609 * Message will be print to stderr.
612 ecore_getopt_help(FILE *fp, const Ecore_Getopt *parser)
620 ecore_app_args_get(&argc, &argv);
621 if ((argc > 0) && (argv[0]))
627 var = getenv("COLUMNS");
637 _ecore_getopt_help_usage(fp, parser);
638 _ecore_getopt_help_description(fp, parser);
639 _ecore_getopt_help_options(fp, parser);
642 static const Ecore_Getopt_Desc *
643 _ecore_getopt_parse_find_long(const Ecore_Getopt *parser, const char *name)
645 const Ecore_Getopt_Desc *desc = parser->descs;
646 const char *p = strchr(name, '=');
652 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
659 if ((strncmp(name, desc->longname, len) == 0) &&
660 (desc->longname[len] == '\0'))
665 if (strcmp(name, desc->longname) == 0)
673 static const Ecore_Getopt_Desc *
674 _ecore_getopt_parse_find_short(const Ecore_Getopt *parser, char name)
676 const Ecore_Getopt_Desc *desc = parser->descs;
677 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
678 if (name == desc->shortname)
684 _ecore_getopt_parse_find_nonargs_base(const Ecore_Getopt *parser, int argc, char **argv)
687 int src, dst, used, base;
689 nonargs = alloca(sizeof(char*) * argc);
696 const Ecore_Getopt_Desc *desc;
697 Ecore_Getopt_Desc_Arg_Requirement arg_req;
698 char *arg = argv[src];
705 if (arg[2] == '\0') /* explicit end of options, "--" */
710 desc = _ecore_getopt_parse_find_long(parser, arg + 2);
713 desc = _ecore_getopt_parse_find_short(parser, arg[1]);
718 fprintf(stderr, _("ERROR: unknown option --%s.\n"), arg + 2);
720 fprintf(stderr, _("ERROR: unknown option -%c.\n"), arg[1]);
723 memmove(argv + dst, nonargs, used * sizeof(char *));
731 argv[dst] = argv[src];
735 arg_req = _ecore_getopt_desc_arg_requirement(desc);
736 if (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
739 if (strchr(arg, '='))
742 if ((src >= argc) || (argv[src][0] == '-'))
746 argv[dst] = argv[src];
757 if (!base) /* '--' not found */
763 argv[dst] = argv[src];
767 memmove(argv + dst, nonargs, used * sizeof(char *));
772 _ecore_getopt_desc_print_error(const Ecore_Getopt_Desc *desc, const char *fmt, ...)
776 fputs(_("ERROR: "), stderr);
781 fputc(desc->shortname, stderr);
784 if (desc->shortname && desc->longname)
790 fputs(desc->longname, stderr);
796 vfprintf(stderr, fmt, ap);
801 _ecore_getopt_parse_bool(const char *str, unsigned char *v)
803 if ((strcmp(str, "0") == 0) ||
804 (strcasecmp(str, "f") == 0) ||
805 (strcasecmp(str, "false") == 0) ||
806 (strcasecmp(str, "no") == 0) ||
807 (strcasecmp(str, "off") == 0)
813 else if ((strcmp(str, "1") == 0) ||
814 (strcasecmp(str, "t") == 0) ||
815 (strcasecmp(str, "true") == 0) ||
816 (strcasecmp(str, "yes") == 0) ||
817 (strcasecmp(str, "on") == 0)
828 _ecore_getopt_parse_long(const char *str, long int *v)
831 *v = strtol(str, &endptr, 0);
836 _ecore_getopt_parse_double(const char *str, double *v)
839 *v = strtod(str, &endptr);
844 _ecore_getopt_parse_store(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *value, const char *arg_val)
846 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
853 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
857 switch (store->arg_req)
859 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
861 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
864 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
870 case ECORE_GETOPT_TYPE_STR:
871 *value->strp = (char *)arg_val;
873 case ECORE_GETOPT_TYPE_BOOL:
874 if (_ecore_getopt_parse_bool(arg_val, &b))
881 _ecore_getopt_desc_print_error
882 (desc, _("unknown boolean value %s.\n"), arg_val);
885 case ECORE_GETOPT_TYPE_SHORT:
886 if (!_ecore_getopt_parse_long(arg_val, &v))
890 case ECORE_GETOPT_TYPE_INT:
891 if (!_ecore_getopt_parse_long(arg_val, &v))
895 case ECORE_GETOPT_TYPE_LONG:
896 if (!_ecore_getopt_parse_long(arg_val, &v))
900 case ECORE_GETOPT_TYPE_USHORT:
901 if (!_ecore_getopt_parse_long(arg_val, &v))
905 case ECORE_GETOPT_TYPE_UINT:
906 if (!_ecore_getopt_parse_long(arg_val, &v))
910 case ECORE_GETOPT_TYPE_ULONG:
911 if (!_ecore_getopt_parse_long(arg_val, &v))
915 case ECORE_GETOPT_TYPE_DOUBLE:
916 if (!_ecore_getopt_parse_double(arg_val, &d))
925 _ecore_getopt_desc_print_error
926 (desc, _("invalid number format %s\n"), arg_val);
932 case ECORE_GETOPT_TYPE_STR:
933 *value->strp = (char *)store->def.strv;
935 case ECORE_GETOPT_TYPE_BOOL:
936 *value->boolp = store->def.boolv;
938 case ECORE_GETOPT_TYPE_SHORT:
939 *value->shortp = store->def.shortv;
941 case ECORE_GETOPT_TYPE_INT:
942 *value->intp = store->def.intv;
944 case ECORE_GETOPT_TYPE_LONG:
945 *value->longp = store->def.longv;
947 case ECORE_GETOPT_TYPE_USHORT:
948 *value->ushortp = store->def.ushortv;
950 case ECORE_GETOPT_TYPE_UINT:
951 *value->uintp = store->def.uintv;
953 case ECORE_GETOPT_TYPE_ULONG:
954 *value->ulongp = store->def.ulongv;
956 case ECORE_GETOPT_TYPE_DOUBLE:
957 *value->doublep = store->def.doublev;
965 _ecore_getopt_parse_store_const(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
969 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
973 *val->ptrp = (void *)desc->action_param.store_const;
978 _ecore_getopt_parse_store_true(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
982 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
990 _ecore_getopt_parse_store_false(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
994 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1001 static unsigned char
1002 _ecore_getopt_parse_choice(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
1004 const char * const *pchoice;
1008 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1012 pchoice = desc->action_param.choices;
1013 for (; *pchoice; pchoice++)
1014 if (strcmp(*pchoice, arg_val) == 0)
1016 *val->strp = (char *)*pchoice;
1020 _ecore_getopt_desc_print_error
1021 (desc, _("invalid choice \"%s\". Valid values are: "), arg_val);
1023 pchoice = desc->action_param.choices;
1024 for (; *pchoice; pchoice++)
1026 fputs(*pchoice, stderr);
1028 fputs(", ", stderr);
1031 fputs(".\n", stderr);
1035 static unsigned char
1036 _ecore_getopt_parse_append(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
1045 _ecore_getopt_desc_print_error
1046 (desc, _("missing parameter to append.\n"));
1052 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1056 switch (desc->action_param.append_type)
1058 case ECORE_GETOPT_TYPE_STR:
1059 data = strdup(arg_val);
1061 case ECORE_GETOPT_TYPE_BOOL:
1063 if (_ecore_getopt_parse_bool(arg_val, &b))
1065 data = malloc(sizeof(unsigned char));
1067 *(unsigned char *)data = b;
1071 _ecore_getopt_desc_print_error
1072 (desc, _("unknown boolean value %s.\n"), arg_val);
1077 case ECORE_GETOPT_TYPE_SHORT:
1079 if (!_ecore_getopt_parse_long(arg_val, &v))
1081 data = malloc(sizeof(short));
1083 *(short *)data = (short)v;
1086 case ECORE_GETOPT_TYPE_INT:
1088 if (!_ecore_getopt_parse_long(arg_val, &v))
1090 data = malloc(sizeof(int));
1092 *(int *)data = (int)v;
1095 case ECORE_GETOPT_TYPE_LONG:
1097 if (!_ecore_getopt_parse_long(arg_val, &v))
1099 data = malloc(sizeof(long));
1104 case ECORE_GETOPT_TYPE_USHORT:
1106 if (!_ecore_getopt_parse_long(arg_val, &v))
1108 data = malloc(sizeof(unsigned short));
1110 *(unsigned short *)data = (unsigned short)v;
1113 case ECORE_GETOPT_TYPE_UINT:
1115 if (!_ecore_getopt_parse_long(arg_val, &v))
1117 data = malloc(sizeof(unsigned int));
1119 *(unsigned int *)data = (unsigned int)v;
1122 case ECORE_GETOPT_TYPE_ULONG:
1124 if (!_ecore_getopt_parse_long(arg_val, &v))
1126 data = malloc(sizeof(unsigned long));
1128 *(unsigned long *)data = v;
1131 case ECORE_GETOPT_TYPE_DOUBLE:
1133 if (!_ecore_getopt_parse_double(arg_val, &d))
1135 data = malloc(sizeof(double));
1137 *(double *)data = d;
1142 _ecore_getopt_desc_print_error(desc, _("could not parse value.\n"));
1147 *val->listp = eina_list_append(*val->listp, data);
1151 _ecore_getopt_desc_print_error
1152 (desc, _("invalid number format %s\n"), arg_val);
1156 static unsigned char
1157 _ecore_getopt_parse_count(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1161 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1169 static unsigned char
1170 _ecore_getopt_parse_callback(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
1172 const Ecore_Getopt_Desc_Callback *cb = &desc->action_param.callback;
1174 switch (cb->arg_req)
1176 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
1179 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
1183 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
1187 if (cb->arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1189 if ((!arg_val) || (arg_val[0] == '\0'))
1191 _ecore_getopt_desc_print_error(desc, _("missing parameter.\n"));
1197 _ecore_getopt_desc_print_error
1198 (desc, _("value has no pointer set.\n"));
1205 _ecore_getopt_desc_print_error(desc, _("missing callback function!\n"));
1209 return cb->func(parser, desc, arg_val, (void *)cb->data, val);
1212 static unsigned char
1213 _ecore_getopt_parse_help(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc __UNUSED__, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1217 ecore_getopt_help(stdout, parser);
1221 static unsigned char
1222 _ecore_getopt_parse_version(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1226 if (!parser->version)
1228 _ecore_getopt_desc_print_error(desc, _("no version was defined.\n"));
1231 _ecore_getopt_version(stdout, parser);
1235 static unsigned char
1236 _ecore_getopt_parse_copyright(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1240 if (!parser->copyright)
1242 _ecore_getopt_desc_print_error(desc, _("no copyright was defined.\n"));
1245 _ecore_getopt_copyright(stdout, parser);
1249 static unsigned char
1250 _ecore_getopt_parse_license(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
1254 if (!parser->license)
1256 _ecore_getopt_desc_print_error(desc, _("no license was defined.\n"));
1259 _ecore_getopt_license(stdout, parser);
1263 static unsigned char
1264 _ecore_getopt_desc_handle(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *value, const char *arg_val)
1266 switch (desc->action)
1268 case ECORE_GETOPT_ACTION_STORE:
1269 return _ecore_getopt_parse_store(parser, desc, value, arg_val);
1270 case ECORE_GETOPT_ACTION_STORE_CONST:
1271 return _ecore_getopt_parse_store_const(parser, desc, value, arg_val);
1272 case ECORE_GETOPT_ACTION_STORE_TRUE:
1273 return _ecore_getopt_parse_store_true(parser, desc, value, arg_val);
1274 case ECORE_GETOPT_ACTION_STORE_FALSE:
1275 return _ecore_getopt_parse_store_false(parser, desc, value, arg_val);
1276 case ECORE_GETOPT_ACTION_CHOICE:
1277 return _ecore_getopt_parse_choice(parser, desc, value, arg_val);
1278 case ECORE_GETOPT_ACTION_APPEND:
1279 return _ecore_getopt_parse_append(parser, desc, value, arg_val);
1280 case ECORE_GETOPT_ACTION_COUNT:
1281 return _ecore_getopt_parse_count(parser, desc, value, arg_val);
1282 case ECORE_GETOPT_ACTION_CALLBACK:
1283 return _ecore_getopt_parse_callback(parser, desc, value, arg_val);
1284 case ECORE_GETOPT_ACTION_HELP:
1285 return _ecore_getopt_parse_help(parser, desc, value, arg_val);
1286 case ECORE_GETOPT_ACTION_VERSION:
1287 return _ecore_getopt_parse_version(parser, desc, value, arg_val);
1288 case ECORE_GETOPT_ACTION_COPYRIGHT:
1289 return _ecore_getopt_parse_copyright(parser, desc, value, arg_val);
1290 case ECORE_GETOPT_ACTION_LICENSE:
1291 return _ecore_getopt_parse_license(parser, desc, value, arg_val);
1297 static unsigned char
1298 _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)
1300 const Ecore_Getopt_Desc *desc;
1301 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1302 const char *arg_val;
1304 Ecore_Getopt_Value *value;
1307 desc = _ecore_getopt_parse_find_long(parser, arg);
1310 fprintf(stderr, _("ERROR: unknown option --%s, ignored.\n"), arg);
1320 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1321 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1323 arg_val = strchr(arg, '=');
1328 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1330 arg_val = argv[*idx];
1337 if (arg_val && arg_val[0] == '\0')
1340 if ((!arg_val) && (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1343 (stderr, _("ERROR: option --%s requires an argument!\n"), arg);
1352 desc_idx = desc - parser->descs;
1353 value = values + desc_idx;
1354 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1355 if ((!ret) && parser->strict)
1361 static unsigned char
1362 _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)
1365 while (run && (arg[0] != '\0'))
1368 const Ecore_Getopt_Desc *desc;
1369 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1370 const char *arg_val;
1372 Ecore_Getopt_Value *value;
1375 desc = _ecore_getopt_parse_find_short(parser, arg[0]);
1379 (stderr, _("ERROR: unknown option -%c, ignored.\n"), arg[0]);
1389 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1390 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1397 else if (arg[0] != '\0')
1401 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1403 arg_val = argv[*idx];
1410 if (arg_val && arg_val[0] == '\0')
1414 (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1417 (stderr, _("ERROR: option -%c requires an argument!\n"),
1427 desc_idx = desc - parser->descs;
1428 value = values + desc_idx;
1429 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1430 if ((!ret) && parser->strict)
1440 static unsigned char
1441 _ecore_getopt_parse_arg(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv, int *idx, int *nonargs)
1443 char *arg = argv[*idx];
1447 char **dst, **src, **src_end;
1451 src_end = src + *nonargs - *idx - 1;
1453 for (; src < src_end; src++, dst++)
1462 return _ecore_getopt_parse_arg_long
1463 (parser, values, argc, argv, idx, nonargs, arg + 2);
1465 return _ecore_getopt_parse_arg_short
1466 (parser, values, argc, argv, idx, nonargs, arg + 1);
1469 static const Ecore_Getopt_Desc *
1470 _ecore_getopt_parse_find_short_other(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *orig)
1472 const Ecore_Getopt_Desc *desc = parser->descs;
1473 const char c = orig->shortname;
1475 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1480 if (c == desc->shortname)
1487 static const Ecore_Getopt_Desc *
1488 _ecore_getopt_parse_find_long_other(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *orig)
1490 const Ecore_Getopt_Desc *desc = parser->descs;
1491 const char *name = orig->longname;
1493 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1498 if (desc->longname && (strcmp(name, desc->longname) == 0))
1506 * Check parser for duplicate entries, print them out.
1508 * @return 1 if there are duplicates, 0 otherwise.
1511 ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser)
1513 const Ecore_Getopt_Desc *desc = parser->descs;
1514 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1516 if (desc->shortname)
1518 const Ecore_Getopt_Desc *other;
1519 other = _ecore_getopt_parse_find_short_other(parser, desc);
1522 _ecore_getopt_desc_print_error
1523 (desc, "short name -%c already exists.", desc->shortname);
1525 if (other->longname)
1526 fprintf(stderr, " Other is --%s.\n", other->longname);
1528 fputc('\n', stderr);
1535 const Ecore_Getopt_Desc *other;
1536 other = _ecore_getopt_parse_find_long_other(parser, desc);
1539 _ecore_getopt_desc_print_error
1540 (desc, "long name --%s already exists.", desc->longname);
1542 if (other->shortname)
1543 fprintf(stderr, " Other is -%c.\n", other->shortname);
1545 fputc('\n', stderr);
1553 static const Ecore_Getopt_Desc *
1554 _ecore_getopt_find_help(const Ecore_Getopt *parser)
1556 const Ecore_Getopt_Desc *desc = parser->descs;
1557 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1558 if (desc->action == ECORE_GETOPT_ACTION_HELP)
1564 * Parse command line parameters.
1566 * Walks the command line parameters and parse them based on @a parser
1567 * description, doing actions based on @c parser->descs->action, like
1568 * showing help text, license, copyright, storing values in values and
1571 * It is expected that values is of the same size than @c parser->descs,
1572 * options that do not need a value it will be left untouched.
1574 * All values are expected to be initialized before use. Options with
1575 * action @c ECORE_GETOPT_ACTION_STORE and non required arguments
1576 * (others than @c ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES), are expected
1577 * to provide a value in @c def to be used.
1579 * The following actions will store 1 on value as a boolean
1580 * (@c value->boolp) if it's not NULL to indicate these actions were executed:
1581 * - @c ECORE_GETOPT_ACTION_HELP
1582 * - @c ECORE_GETOPT_ACTION_VERSION
1583 * - @c ECORE_GETOPT_ACTION_COPYRIGHT
1584 * - @c ECORE_GETOPT_ACTION_LICENSE
1586 * Just @c ECORE_GETOPT_ACTION_APPEND will allocate memory and thus
1587 * need to be freed. For consistency between all of appended subtypes,
1588 * @c eina_list->data will contain an allocated memory with the value,
1589 * that is, for @c ECORE_GETOPT_TYPE_STR it will contain a copy of the
1590 * argument, @c ECORE_GETOPT_TYPE_INT a pointer to an allocated
1591 * integer and so on.
1593 * If parser is in strict mode (see @c Ecore_Getopt->strict), then any
1594 * error will abort parsing and -1 is returned. Otherwise it will try
1595 * to continue as far as possible.
1597 * This function may reorder @a argv elements.
1599 * Translation of help strings (description), metavar, usage, license
1600 * and copyright may be translated, standard/global gettext() call
1601 * will be applied on them if ecore was compiled with such support.
1603 * @param parser description of how to work.
1604 * @param value where to store values, it is assumed that this is a vector
1605 * of the same size as @c parser->descs. Values should be previously
1607 * @param argc how many elements in @a argv. If not provided it will be
1608 * retrieved with ecore_app_args_get().
1609 * @param argv command line parameters.
1611 * @return index of first non-option parameter or -1 on error.
1614 ecore_getopt_parse(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv)
1620 fputs(_("ERROR: no parser provided.\n"), stderr);
1625 fputs(_("ERROR: no values provided.\n"), stderr);
1629 if ((argc < 1) || (!argv))
1630 ecore_app_args_get(&argc, &argv);
1634 fputs(_("ERROR: no arguments provided.\n"), stderr);
1641 prog = parser->prog;
1643 nonargs = _ecore_getopt_parse_find_nonargs_base(parser, argc, argv);
1652 if (!_ecore_getopt_parse_arg(parser, values, argc, argv, &i, &nonargs))
1659 const Ecore_Getopt_Desc *help;
1660 fputs(_("ERROR: invalid options found."), stderr);
1662 help = _ecore_getopt_find_help(parser);
1664 fputc('\n', stderr);
1665 else if (help->longname)
1666 fprintf(stderr, _(" See --%s.\n"), help->longname);
1668 fprintf(stderr, _(" See -%c.\n"), help->shortname);
1675 * Utility to free list and nodes allocated by @a ECORE_GETOPT_ACTION_APPEND.
1677 * @param list pointer to list to be freed.
1678 * @return always NULL, so you can easily make your list head NULL.
1681 ecore_getopt_list_free(Eina_List *list)
1685 EINA_LIST_FREE(list, data)
1691 * Helper ecore_getopt callback to parse geometry (x:y:w:h).
1693 * Storage must be a pointer to @c Eina_Rectangle and will be used to
1694 * store the four values passed in the given string.
1696 * @c callback_data value is ignored, you can safely use @c NULL.
1699 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)
1701 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1703 if (sscanf(str, "%d:%d:%d:%d", &v->x, &v->y, &v->w, &v->h) != 4)
1705 fprintf(stderr, _("ERROR: incorrect geometry value '%s'\n"), str);
1713 * Helper ecore_getopt callback to parse geometry size (WxH).
1715 * Storage must be a pointer to @c Eina_Rectangle and will be used to
1716 * store the two values passed in the given string and 0 in the x and y
1719 * @c callback_data value is ignored, you can safely use @c NULL.
1722 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)
1724 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1726 if (sscanf(str, "%dx%d", &v->w, &v->h) != 2)
1728 fprintf(stderr, _("ERROR: incorrect size value '%s'\n"), str);