8 # define alloca __builtin_alloca
10 # define alloca __alloca
11 #elif defined _MSC_VER
13 # define alloca _alloca
31 # define gettext(x) (x)
32 # define dgettext(domain, x) (x)
35 #define _(x) dgettext("ecore", x)
46 #include "Ecore_Getopt.h"
48 static const char *prog = NULL;
49 static char **argv = NULL;
52 static int helpcol = 80 / 3;
55 _ecore_getopt_help_print_replace_program(FILE *fp,
56 const Ecore_Getopt *parser __UNUSED__,
61 const char *d = strchr(text, '%');
69 if (fwrite(text, 1, d - text, fp) != (size_t)(d - text))
72 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
74 fputs(prog ? prog : "???", fp);
75 d += sizeof("prog") - 1;
86 while (text[0] != '\0');
92 _ecore_getopt_version(FILE *fp,
93 const Ecore_Getopt *parser)
95 fputs(_("Version:"), fp);
97 _ecore_getopt_help_print_replace_program(fp, parser, parser->version);
101 _ecore_getopt_help_usage(FILE *fp,
102 const Ecore_Getopt *parser)
104 fputs(_("Usage:"), fp);
109 fprintf(fp, _("%s [options]\n"), prog);
113 _ecore_getopt_help_print_replace_program(fp, parser, gettext(parser->usage));
117 _ecore_getopt_help_line(FILE *fp,
127 /* process line considering spaces (new line and tabs are spaces!) */
128 while ((used < total) && (len > 0))
130 const char *space = NULL;
137 for (i = 0; i < todo; i++)
138 if (isspace((unsigned char)text[i]))
146 i = fwrite(text, 1, i, fp);
158 if (space[0] == '\n')
160 else if (space[0] == '\t')
165 c = ((used / 8) + 1) * 8;
168 for (; used < c; used++)
178 else if (used < total)
183 i = fwrite(text, 1, i, fp);
194 for (used = 0; used < base; used++)
203 _ecore_getopt_help_description(FILE *fp,
204 const Ecore_Getopt *parser)
206 const char *p, *prg, *ver;
207 int used, prglen, verlen;
209 p = gettext(parser->description);
215 prg = prog ? prog : "???";
216 ver = parser->version ? parser->version : "???";
218 prglen = strlen(prg);
219 verlen = strlen(ver);
225 const char *d = strchr(p, '%');
229 _ecore_getopt_help_line(fp, 0, cols, used, p, strlen(p));
233 used = _ecore_getopt_help_line(fp, 0, cols, used, p, d - p);
235 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
237 used = _ecore_getopt_help_line(fp, 0, cols, used, prg, prglen);
238 d += sizeof("prog") - 1;
240 else if (strncmp(d, "version", sizeof("version") - 1) == 0)
242 used = _ecore_getopt_help_line(fp, 0, cols, used, ver, verlen);
243 d += sizeof("version") - 1;
249 used = _ecore_getopt_help_line(fp, 0, cols, used, "%", 1);
254 while (p[0] != '\0');
260 _ecore_getopt_copyright(FILE *fp,
261 const Ecore_Getopt *parser)
263 const char *txt = gettext(parser->copyright);
264 fputs(_("Copyright:"), fp);
266 _ecore_getopt_help_line
267 (fp, 3, cols, 3, txt, strlen(txt));
272 _ecore_getopt_license(FILE *fp,
273 const Ecore_Getopt *parser)
275 const char *txt = gettext(parser->license);
276 fputs(_("License:"), fp);
278 _ecore_getopt_help_line
279 (fp, 3, cols, 3, txt, strlen(txt));
283 static Ecore_Getopt_Desc_Arg_Requirement
284 _ecore_getopt_desc_arg_requirement(const Ecore_Getopt_Desc *desc)
286 switch (desc->action)
288 case ECORE_GETOPT_ACTION_STORE:
289 return desc->action_param.store.arg_req;
291 case ECORE_GETOPT_ACTION_STORE_CONST:
292 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
294 case ECORE_GETOPT_ACTION_STORE_TRUE:
295 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
297 case ECORE_GETOPT_ACTION_STORE_FALSE:
298 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
300 case ECORE_GETOPT_ACTION_CHOICE:
301 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
303 case ECORE_GETOPT_ACTION_APPEND:
304 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
306 case ECORE_GETOPT_ACTION_COUNT:
307 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
309 case ECORE_GETOPT_ACTION_CALLBACK:
310 return desc->action_param.callback.arg_req;
312 case ECORE_GETOPT_ACTION_HELP:
313 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
315 case ECORE_GETOPT_ACTION_VERSION:
316 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
319 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
324 _ecore_getopt_help_desc_setup_metavar(const Ecore_Getopt_Desc *desc,
331 const char *txt = gettext(desc->metavar);
332 *metavarlen = strlen(txt);
333 if (*metavarlen > maxsize - 1)
334 *metavarlen = maxsize - 1;
336 memcpy(metavar, txt, *metavarlen);
337 metavar[*metavarlen] = '\0';
339 else if (desc->longname)
343 *metavarlen = strlen(desc->longname);
344 if (*metavarlen > maxsize - 1)
345 *metavarlen = maxsize - 1;
347 for (i = 0; i < *metavarlen; i++)
348 metavar[i] = toupper((int) desc->longname[i]);
354 _ecore_getopt_help_desc_show_arg(FILE *fp,
355 Ecore_Getopt_Desc_Arg_Requirement requirement,
361 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
366 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
372 if (requirement != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
376 used += metavarlen + 1;
379 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
389 _ecore_getopt_help_desc_store(FILE *fp,
393 const Ecore_Getopt_Desc *desc)
395 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
401 for (used = 0; used < base; used++)
406 case ECORE_GETOPT_TYPE_STR:
408 len = sizeof("STR") - 1;
411 case ECORE_GETOPT_TYPE_BOOL:
413 len = sizeof("BOOL") - 1;
416 case ECORE_GETOPT_TYPE_SHORT:
418 len = sizeof("SHORT") - 1;
421 case ECORE_GETOPT_TYPE_INT:
423 len = sizeof("INT") - 1;
426 case ECORE_GETOPT_TYPE_LONG:
428 len = sizeof("LONG") - 1;
431 case ECORE_GETOPT_TYPE_USHORT:
433 len = sizeof("USHORT") - 1;
436 case ECORE_GETOPT_TYPE_UINT:
438 len = sizeof("UINT") - 1;
441 case ECORE_GETOPT_TYPE_ULONG:
443 len = sizeof("ULONG") - 1;
446 case ECORE_GETOPT_TYPE_DOUBLE:
448 len = sizeof("DOUBLE") - 1;
453 len = sizeof("???") - 1;
456 used = _ecore_getopt_help_line
457 (fp, base, total, used, _("Type: "), strlen(_("Type: ")));
458 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
460 if (store->arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES)
463 used = _ecore_getopt_help_line
464 (fp, base, total, used, ". ", sizeof(". ") - 1);
468 case ECORE_GETOPT_TYPE_STR:
469 str = store->def.strv;
470 len = str ? strlen(str) : 0;
473 case ECORE_GETOPT_TYPE_BOOL:
474 str = store->def.boolv ? "true" : "false";
478 case ECORE_GETOPT_TYPE_SHORT:
480 len = snprintf(buf, sizeof(buf), "%hd", store->def.shortv);
481 if (len > sizeof(buf) - 1)
482 len = sizeof(buf) - 1;
485 case ECORE_GETOPT_TYPE_INT:
487 len = snprintf(buf, sizeof(buf), "%d", store->def.intv);
488 if (len > sizeof(buf) - 1)
489 len = sizeof(buf) - 1;
492 case ECORE_GETOPT_TYPE_LONG:
494 len = snprintf(buf, sizeof(buf), "%ld", store->def.longv);
495 if (len > sizeof(buf) - 1)
496 len = sizeof(buf) - 1;
499 case ECORE_GETOPT_TYPE_USHORT:
501 len = snprintf(buf, sizeof(buf), "%hu", store->def.ushortv);
502 if (len > sizeof(buf) - 1)
503 len = sizeof(buf) - 1;
506 case ECORE_GETOPT_TYPE_UINT:
508 len = snprintf(buf, sizeof(buf), "%u", store->def.uintv);
509 if (len > sizeof(buf) - 1)
510 len = sizeof(buf) - 1;
513 case ECORE_GETOPT_TYPE_ULONG:
515 len = snprintf(buf, sizeof(buf), "%lu", store->def.ulongv);
516 if (len > sizeof(buf) - 1)
517 len = sizeof(buf) - 1;
520 case ECORE_GETOPT_TYPE_DOUBLE:
522 len = snprintf(buf, sizeof(buf), "%f", store->def.doublev);
523 if (len > sizeof(buf) - 1)
524 len = sizeof(buf) - 1;
529 len = sizeof("???") - 1;
532 used = _ecore_getopt_help_line
533 (fp, base, total, used, _("Default: "), strlen(_("Default: ")));
534 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
537 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
541 _ecore_getopt_help_desc_choices(FILE *fp,
545 const Ecore_Getopt_Desc *desc)
547 const char *const *itr;
548 const char sep[] = ", ";
549 const int seplen = sizeof(sep) - 1;
556 for (; used < base; used++)
559 used = _ecore_getopt_help_line
560 (fp, base, total, used, _("Choices: "), strlen(_("Choices: ")));
562 for (itr = desc->action_param.choices; *itr; itr++)
564 used = _ecore_getopt_help_line
565 (fp, base, total, used, *itr, strlen(*itr));
567 used = _ecore_getopt_help_line(fp, base, total, used, sep, seplen);
570 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
574 _ecore_getopt_help_desc(FILE *fp,
575 const Ecore_Getopt_Desc *desc)
577 Ecore_Getopt_Desc_Arg_Requirement arg_req;
578 char metavar[32] = "ARG";
582 arg_req = _ecore_getopt_desc_arg_requirement(desc);
583 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
584 _ecore_getopt_help_desc_setup_metavar
585 (desc, metavar, &metavarlen, sizeof(metavar));
593 fputc(desc->shortname, fp);
595 used += _ecore_getopt_help_desc_show_arg
596 (fp, arg_req, metavar, metavarlen);
599 if (desc->shortname && desc->longname)
607 int namelen = strlen(desc->longname);
610 fputs(desc->longname, fp);
612 used += _ecore_getopt_help_desc_show_arg
613 (fp, arg_req, metavar, metavarlen);
619 if (used + 3 >= helpcol)
625 for (; used < helpcol; used++)
628 used = _ecore_getopt_help_line
629 (fp, helpcol, cols, used, desc->help, strlen(desc->help));
631 switch (desc->action)
633 case ECORE_GETOPT_ACTION_STORE:
634 _ecore_getopt_help_desc_store(fp, helpcol, cols, used, desc);
637 case ECORE_GETOPT_ACTION_CHOICE:
638 _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc);
650 _ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc)
652 return (desc->shortname == '\0') && (!desc->longname);
656 _ecore_getopt_help_options(FILE *fp,
657 const Ecore_Getopt *parser)
659 const Ecore_Getopt_Desc *desc;
661 fputs(_("Options:\n"), fp);
663 for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
664 _ecore_getopt_help_desc(fp, desc);
670 * Show nicely formatted help message for the given parser.
672 * Message will be print to stderr.
675 ecore_getopt_help(FILE *fp,
676 const Ecore_Getopt *parser)
684 ecore_app_args_get(&argc, &argv);
685 if ((argc > 0) && (argv[0]))
691 var = getenv("COLUMNS");
701 _ecore_getopt_help_usage(fp, parser);
702 _ecore_getopt_help_description(fp, parser);
703 _ecore_getopt_help_options(fp, parser);
706 static const Ecore_Getopt_Desc *
707 _ecore_getopt_parse_find_long(const Ecore_Getopt *parser,
710 const Ecore_Getopt_Desc *desc = parser->descs;
711 const char *p = strchr(name, '=');
717 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
724 if ((strncmp(name, desc->longname, len) == 0) &&
725 (desc->longname[len] == '\0'))
730 if (strcmp(name, desc->longname) == 0)
738 static const Ecore_Getopt_Desc *
739 _ecore_getopt_parse_find_short(const Ecore_Getopt *parser,
742 const Ecore_Getopt_Desc *desc = parser->descs;
743 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
744 if (name == desc->shortname)
750 _ecore_getopt_parse_find_nonargs_base(const Ecore_Getopt *parser,
755 int src, dst, used, base;
757 nonargs = alloca(sizeof(char *) * argc);
764 const Ecore_Getopt_Desc *desc;
765 Ecore_Getopt_Desc_Arg_Requirement arg_req;
766 char *arg = argv[src];
773 if (arg[2] == '\0') /* explicit end of options, "--" */
778 desc = _ecore_getopt_parse_find_long(parser, arg + 2);
781 desc = _ecore_getopt_parse_find_short(parser, arg[1]);
786 fprintf(stderr, _("ERROR: unknown option --%s.\n"), arg + 2);
788 fprintf(stderr, _("ERROR: unknown option -%c.\n"), arg[1]);
791 memmove(argv + dst, nonargs, used * sizeof(char *));
799 argv[dst] = argv[src];
803 arg_req = _ecore_getopt_desc_arg_requirement(desc);
804 if (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
807 if (strchr(arg, '='))
810 if ((src >= argc) || (argv[src][0] == '-'))
814 argv[dst] = argv[src];
825 if (!base) /* '--' not found */
831 argv[dst] = argv[src];
835 memmove(argv + dst, nonargs, used * sizeof(char *));
840 _ecore_getopt_desc_print_error(const Ecore_Getopt_Desc *desc,
846 fputs(_("ERROR: "), stderr);
851 fputc(desc->shortname, stderr);
854 if (desc->shortname && desc->longname)
860 fputs(desc->longname, stderr);
866 vfprintf(stderr, fmt, ap);
871 _ecore_getopt_parse_bool(const char *str,
874 if ((strcmp(str, "0") == 0) ||
875 (strcasecmp(str, "f") == 0) ||
876 (strcasecmp(str, "false") == 0) ||
877 (strcasecmp(str, "no") == 0) ||
878 (strcasecmp(str, "off") == 0)
884 else if ((strcmp(str, "1") == 0) ||
885 (strcasecmp(str, "t") == 0) ||
886 (strcasecmp(str, "true") == 0) ||
887 (strcasecmp(str, "yes") == 0) ||
888 (strcasecmp(str, "on") == 0)
899 _ecore_getopt_parse_long(const char *str,
903 *v = strtol(str, &endptr, 0);
908 _ecore_getopt_parse_double(const char *str,
912 *v = strtod(str, &endptr);
917 _ecore_getopt_parse_store(const Ecore_Getopt *parser __UNUSED__,
918 const Ecore_Getopt_Desc *desc,
919 Ecore_Getopt_Value *value,
922 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
929 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
933 switch (store->arg_req)
935 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
938 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
942 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
948 case ECORE_GETOPT_TYPE_STR:
949 *value->strp = (char *)arg_val;
952 case ECORE_GETOPT_TYPE_BOOL:
953 if (_ecore_getopt_parse_bool(arg_val, &b))
960 _ecore_getopt_desc_print_error
961 (desc, _("unknown boolean value %s.\n"), arg_val);
965 case ECORE_GETOPT_TYPE_SHORT:
966 if (!_ecore_getopt_parse_long(arg_val, &v))
971 case ECORE_GETOPT_TYPE_INT:
972 if (!_ecore_getopt_parse_long(arg_val, &v))
977 case ECORE_GETOPT_TYPE_LONG:
978 if (!_ecore_getopt_parse_long(arg_val, &v))
983 case ECORE_GETOPT_TYPE_USHORT:
984 if (!_ecore_getopt_parse_long(arg_val, &v))
989 case ECORE_GETOPT_TYPE_UINT:
990 if (!_ecore_getopt_parse_long(arg_val, &v))
995 case ECORE_GETOPT_TYPE_ULONG:
996 if (!_ecore_getopt_parse_long(arg_val, &v))
1001 case ECORE_GETOPT_TYPE_DOUBLE:
1002 if (!_ecore_getopt_parse_double(arg_val, &d))
1004 *value->doublep = d;
1011 _ecore_getopt_desc_print_error
1012 (desc, _("invalid number format %s\n"), arg_val);
1016 switch (store->type)
1018 case ECORE_GETOPT_TYPE_STR:
1019 *value->strp = (char *)store->def.strv;
1022 case ECORE_GETOPT_TYPE_BOOL:
1023 *value->boolp = store->def.boolv;
1026 case ECORE_GETOPT_TYPE_SHORT:
1027 *value->shortp = store->def.shortv;
1030 case ECORE_GETOPT_TYPE_INT:
1031 *value->intp = store->def.intv;
1034 case ECORE_GETOPT_TYPE_LONG:
1035 *value->longp = store->def.longv;
1038 case ECORE_GETOPT_TYPE_USHORT:
1039 *value->ushortp = store->def.ushortv;
1042 case ECORE_GETOPT_TYPE_UINT:
1043 *value->uintp = store->def.uintv;
1046 case ECORE_GETOPT_TYPE_ULONG:
1047 *value->ulongp = store->def.ulongv;
1050 case ECORE_GETOPT_TYPE_DOUBLE:
1051 *value->doublep = store->def.doublev;
1059 _ecore_getopt_parse_store_const(const Ecore_Getopt *parser __UNUSED__,
1060 const Ecore_Getopt_Desc *desc,
1061 Ecore_Getopt_Value *val,
1062 const char *arg_val __UNUSED__)
1066 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1070 *val->ptrp = (void *)desc->action_param.store_const;
1075 _ecore_getopt_parse_store_true(const Ecore_Getopt *parser __UNUSED__,
1076 const Ecore_Getopt_Desc *desc,
1077 Ecore_Getopt_Value *val,
1078 const char *arg_val __UNUSED__)
1082 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1085 *val->boolp = EINA_TRUE;
1090 _ecore_getopt_parse_store_false(const Ecore_Getopt *parser __UNUSED__,
1091 const Ecore_Getopt_Desc *desc,
1092 Ecore_Getopt_Value *val,
1093 const char *arg_val __UNUSED__)
1097 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1100 *val->boolp = EINA_FALSE;
1105 _ecore_getopt_parse_choice(const Ecore_Getopt *parser __UNUSED__,
1106 const Ecore_Getopt_Desc *desc,
1107 Ecore_Getopt_Value *val,
1108 const char *arg_val)
1110 const char *const *pchoice;
1114 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1118 pchoice = desc->action_param.choices;
1119 for (; *pchoice; pchoice++)
1120 if (strcmp(*pchoice, arg_val) == 0)
1122 *val->strp = (char *)*pchoice;
1126 _ecore_getopt_desc_print_error
1127 (desc, _("invalid choice \"%s\". Valid values are: "), arg_val);
1129 pchoice = desc->action_param.choices;
1130 for (; *pchoice; pchoice++)
1132 fputs(*pchoice, stderr);
1134 fputs(", ", stderr);
1137 fputs(".\n", stderr);
1142 _ecore_getopt_parse_append(const Ecore_Getopt *parser __UNUSED__,
1143 const Ecore_Getopt_Desc *desc,
1144 Ecore_Getopt_Value *val,
1145 const char *arg_val)
1154 _ecore_getopt_desc_print_error
1155 (desc, _("missing parameter to append.\n"));
1161 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1165 switch (desc->action_param.append_type)
1167 case ECORE_GETOPT_TYPE_STR:
1168 data = strdup(arg_val);
1171 case ECORE_GETOPT_TYPE_BOOL:
1173 if (_ecore_getopt_parse_bool(arg_val, &b))
1175 data = malloc(sizeof(Eina_Bool));
1177 *(Eina_Bool *)data = b;
1181 _ecore_getopt_desc_print_error(desc, _("unknown boolean value %s.\n"), arg_val);
1187 case ECORE_GETOPT_TYPE_SHORT:
1189 if (!_ecore_getopt_parse_long(arg_val, &v))
1191 data = malloc(sizeof(short));
1193 *(short *)data = (short)v;
1197 case ECORE_GETOPT_TYPE_INT:
1199 if (!_ecore_getopt_parse_long(arg_val, &v))
1201 data = malloc(sizeof(int));
1203 *(int *)data = (int)v;
1207 case ECORE_GETOPT_TYPE_LONG:
1209 if (!_ecore_getopt_parse_long(arg_val, &v))
1211 data = malloc(sizeof(long));
1217 case ECORE_GETOPT_TYPE_USHORT:
1219 if (!_ecore_getopt_parse_long(arg_val, &v))
1221 data = malloc(sizeof(unsigned short));
1223 *(unsigned short *)data = (unsigned short)v;
1227 case ECORE_GETOPT_TYPE_UINT:
1229 if (!_ecore_getopt_parse_long(arg_val, &v))
1231 data = malloc(sizeof(unsigned int));
1233 *(unsigned int *)data = (unsigned int)v;
1237 case ECORE_GETOPT_TYPE_ULONG:
1239 if (!_ecore_getopt_parse_long(arg_val, &v))
1241 data = malloc(sizeof(unsigned long));
1243 *(unsigned long *)data = v;
1247 case ECORE_GETOPT_TYPE_DOUBLE:
1249 if (!_ecore_getopt_parse_double(arg_val, &d))
1251 data = malloc(sizeof(double));
1253 *(double *)data = d;
1259 _ecore_getopt_desc_print_error(desc, _("could not parse value.\n"));
1264 *val->listp = eina_list_append(*val->listp, data);
1268 _ecore_getopt_desc_print_error
1269 (desc, _("invalid number format %s\n"), arg_val);
1274 _ecore_getopt_parse_count(const Ecore_Getopt *parser __UNUSED__,
1275 const Ecore_Getopt_Desc *desc,
1276 Ecore_Getopt_Value *val,
1277 const char *arg_val __UNUSED__)
1281 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1290 _ecore_getopt_parse_callback(const Ecore_Getopt *parser,
1291 const Ecore_Getopt_Desc *desc,
1292 Ecore_Getopt_Value *val,
1293 const char *arg_val)
1295 const Ecore_Getopt_Desc_Callback *cb = &desc->action_param.callback;
1297 switch (cb->arg_req)
1299 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
1303 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
1308 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
1312 if (cb->arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1314 if ((!arg_val) || (arg_val[0] == '\0'))
1316 _ecore_getopt_desc_print_error(desc, _("missing parameter.\n"));
1322 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1329 _ecore_getopt_desc_print_error(desc, _("missing callback function!\n"));
1333 return cb->func(parser, desc, arg_val, (void *)cb->data, val);
1337 _ecore_getopt_parse_help(const Ecore_Getopt *parser,
1338 const Ecore_Getopt_Desc *desc __UNUSED__,
1339 Ecore_Getopt_Value *val,
1340 const char *arg_val __UNUSED__)
1343 (*val->boolp) = EINA_TRUE;
1344 ecore_getopt_help(stdout, parser);
1349 _ecore_getopt_parse_version(const Ecore_Getopt *parser,
1350 const Ecore_Getopt_Desc *desc,
1351 Ecore_Getopt_Value *val,
1352 const char *arg_val __UNUSED__)
1355 (*val->boolp) = EINA_TRUE;
1356 if (!parser->version)
1358 _ecore_getopt_desc_print_error(desc, _("no version was defined.\n"));
1361 _ecore_getopt_version(stdout, parser);
1366 _ecore_getopt_parse_copyright(const Ecore_Getopt *parser,
1367 const Ecore_Getopt_Desc *desc,
1368 Ecore_Getopt_Value *val,
1369 const char *arg_val __UNUSED__)
1372 (*val->boolp) = EINA_TRUE;
1373 if (!parser->copyright)
1375 _ecore_getopt_desc_print_error(desc, _("no copyright was defined.\n"));
1378 _ecore_getopt_copyright(stdout, parser);
1383 _ecore_getopt_parse_license(const Ecore_Getopt *parser,
1384 const Ecore_Getopt_Desc *desc,
1385 Ecore_Getopt_Value *val,
1386 const char *arg_val __UNUSED__)
1389 (*val->boolp) = EINA_TRUE;
1390 if (!parser->license)
1392 _ecore_getopt_desc_print_error(desc, _("no license was defined.\n"));
1395 _ecore_getopt_license(stdout, parser);
1400 _ecore_getopt_desc_handle(const Ecore_Getopt *parser,
1401 const Ecore_Getopt_Desc *desc,
1402 Ecore_Getopt_Value *value,
1403 const char *arg_val)
1405 switch (desc->action)
1407 case ECORE_GETOPT_ACTION_STORE:
1408 return _ecore_getopt_parse_store(parser, desc, value, arg_val);
1410 case ECORE_GETOPT_ACTION_STORE_CONST:
1411 return _ecore_getopt_parse_store_const(parser, desc, value, arg_val);
1413 case ECORE_GETOPT_ACTION_STORE_TRUE:
1414 return _ecore_getopt_parse_store_true(parser, desc, value, arg_val);
1416 case ECORE_GETOPT_ACTION_STORE_FALSE:
1417 return _ecore_getopt_parse_store_false(parser, desc, value, arg_val);
1419 case ECORE_GETOPT_ACTION_CHOICE:
1420 return _ecore_getopt_parse_choice(parser, desc, value, arg_val);
1422 case ECORE_GETOPT_ACTION_APPEND:
1423 return _ecore_getopt_parse_append(parser, desc, value, arg_val);
1425 case ECORE_GETOPT_ACTION_COUNT:
1426 return _ecore_getopt_parse_count(parser, desc, value, arg_val);
1428 case ECORE_GETOPT_ACTION_CALLBACK:
1429 return _ecore_getopt_parse_callback(parser, desc, value, arg_val);
1431 case ECORE_GETOPT_ACTION_HELP:
1432 return _ecore_getopt_parse_help(parser, desc, value, arg_val);
1434 case ECORE_GETOPT_ACTION_VERSION:
1435 return _ecore_getopt_parse_version(parser, desc, value, arg_val);
1437 case ECORE_GETOPT_ACTION_COPYRIGHT:
1438 return _ecore_getopt_parse_copyright(parser, desc, value, arg_val);
1440 case ECORE_GETOPT_ACTION_LICENSE:
1441 return _ecore_getopt_parse_license(parser, desc, value, arg_val);
1449 _ecore_getopt_parse_arg_long(const Ecore_Getopt *parser,
1450 Ecore_Getopt_Value *values,
1451 int argc __UNUSED__,
1457 const Ecore_Getopt_Desc *desc;
1458 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1459 const char *arg_val;
1461 Ecore_Getopt_Value *value;
1464 desc = _ecore_getopt_parse_find_long(parser, arg);
1467 fprintf(stderr, _("ERROR: unknown option --%s, ignored.\n"), arg);
1477 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1478 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1480 arg_val = strchr(arg, '=');
1485 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1487 arg_val = argv[*idx];
1494 if (arg_val && arg_val[0] == '\0')
1497 if ((!arg_val) && (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1500 (stderr, _("ERROR: option --%s requires an argument!\n"), arg);
1509 desc_idx = desc - parser->descs;
1510 value = values + desc_idx;
1511 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1512 if ((!ret) && parser->strict)
1519 _ecore_getopt_parse_arg_short(const Ecore_Getopt *parser,
1520 Ecore_Getopt_Value *values,
1521 int argc __UNUSED__,
1528 while (run && (arg[0] != '\0'))
1531 const Ecore_Getopt_Desc *desc;
1532 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1533 const char *arg_val;
1535 Ecore_Getopt_Value *value;
1538 desc = _ecore_getopt_parse_find_short(parser, arg[0]);
1542 (stderr, _("ERROR: unknown option -%c, ignored.\n"), arg[0]);
1552 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1553 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1560 else if (arg[0] != '\0')
1564 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1566 arg_val = argv[*idx];
1573 if (arg_val && arg_val[0] == '\0')
1577 (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1580 (stderr, _("ERROR: option -%c requires an argument!\n"),
1590 desc_idx = desc - parser->descs;
1591 value = values + desc_idx;
1592 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1593 if ((!ret) && parser->strict)
1604 _ecore_getopt_parse_arg(const Ecore_Getopt *parser,
1605 Ecore_Getopt_Value *values,
1611 char *arg = argv[*idx];
1615 char **dst, **src, **src_end;
1619 src_end = src + *nonargs - *idx - 1;
1621 for (; src < src_end; src++, dst++)
1630 return _ecore_getopt_parse_arg_long(parser, values, argc, argv, idx, nonargs, arg + 2);
1632 return _ecore_getopt_parse_arg_short(parser, values, argc, argv, idx, nonargs, arg + 1);
1635 static const Ecore_Getopt_Desc *
1636 _ecore_getopt_parse_find_short_other(const Ecore_Getopt *parser,
1637 const Ecore_Getopt_Desc *orig)
1639 const Ecore_Getopt_Desc *desc = parser->descs;
1640 const char c = orig->shortname;
1642 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1647 if (c == desc->shortname)
1654 static const Ecore_Getopt_Desc *
1655 _ecore_getopt_parse_find_long_other(const Ecore_Getopt *parser,
1656 const Ecore_Getopt_Desc *orig)
1658 const Ecore_Getopt_Desc *desc = parser->descs;
1659 const char *name = orig->longname;
1661 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1666 if (desc->longname && (strcmp(name, desc->longname) == 0))
1674 * Check parser for duplicate entries, print them out.
1676 * @return EINA_TRUE if there are duplicates, EINA_FALSE otherwise.
1679 ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser)
1681 const Ecore_Getopt_Desc *desc = parser->descs;
1682 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1684 if (desc->shortname)
1686 const Ecore_Getopt_Desc *other;
1687 other = _ecore_getopt_parse_find_short_other(parser, desc);
1690 _ecore_getopt_desc_print_error(desc, "short name -%c already exists.", desc->shortname);
1692 if (other->longname)
1693 fprintf(stderr, " Other is --%s.\n", other->longname);
1695 fputc('\n', stderr);
1702 const Ecore_Getopt_Desc *other;
1703 other = _ecore_getopt_parse_find_long_other(parser, desc);
1706 _ecore_getopt_desc_print_error(desc, "long name --%s already exists.", desc->longname);
1708 if (other->shortname)
1709 fprintf(stderr, " Other is -%c.\n", other->shortname);
1711 fputc('\n', stderr);
1719 static const Ecore_Getopt_Desc *
1720 _ecore_getopt_find_help(const Ecore_Getopt *parser)
1722 const Ecore_Getopt_Desc *desc = parser->descs;
1723 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1724 if (desc->action == ECORE_GETOPT_ACTION_HELP)
1730 * Parse command line parameters.
1732 * Walks the command line parameters and parse them based on @a parser
1733 * description, doing actions based on @c parser->descs->action, like
1734 * showing help text, license, copyright, storing values in values and
1737 * It is expected that values is of the same size than @c parser->descs,
1738 * options that do not need a value it will be left untouched.
1740 * All values are expected to be initialized before use. Options with
1741 * action @c ECORE_GETOPT_ACTION_STORE and non required arguments
1742 * (others than @c ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES), are expected
1743 * to provide a value in @c def to be used.
1745 * The following actions will store 1 on value as a boolean
1746 * (@c value->boolp) if it's not NULL to indicate these actions were executed:
1747 * - @c ECORE_GETOPT_ACTION_HELP
1748 * - @c ECORE_GETOPT_ACTION_VERSION
1749 * - @c ECORE_GETOPT_ACTION_COPYRIGHT
1750 * - @c ECORE_GETOPT_ACTION_LICENSE
1752 * Just @c ECORE_GETOPT_ACTION_APPEND will allocate memory and thus
1753 * need to be freed. For consistency between all of appended subtypes,
1754 * @c eina_list->data will contain an allocated memory with the value,
1755 * that is, for @c ECORE_GETOPT_TYPE_STR it will contain a copy of the
1756 * argument, @c ECORE_GETOPT_TYPE_INT a pointer to an allocated
1757 * integer and so on.
1759 * If parser is in strict mode (see @c Ecore_Getopt->strict), then any
1760 * error will abort parsing and -1 is returned. Otherwise it will try
1761 * to continue as far as possible.
1763 * This function may reorder @a argv elements.
1765 * Translation of help strings (description), metavar, usage, license
1766 * and copyright may be translated, standard/global gettext() call
1767 * will be applied on them if ecore was compiled with such support.
1769 * @param parser description of how to work.
1770 * @param values where to store values, it is assumed that this is a vector
1771 * of the same size as @c parser->descs. Values should be previously
1773 * @param argc how many elements in @a argv. If not provided it will be
1774 * retrieved with ecore_app_args_get().
1775 * @param argv command line parameters.
1777 * @return index of first non-option parameter or -1 on error.
1780 ecore_getopt_parse(const Ecore_Getopt *parser,
1781 Ecore_Getopt_Value *values,
1789 fputs(_("ERROR: no parser provided.\n"), stderr);
1794 fputs(_("ERROR: no values provided.\n"), stderr);
1798 if ((argc < 1) || (!argv))
1799 ecore_app_args_get(&argc, &argv);
1803 fputs(_("ERROR: no arguments provided.\n"), stderr);
1810 prog = parser->prog;
1812 nonargs = _ecore_getopt_parse_find_nonargs_base(parser, argc, argv);
1821 if (!_ecore_getopt_parse_arg(parser, values, argc, argv, &i, &nonargs))
1828 const Ecore_Getopt_Desc *help;
1829 fputs(_("ERROR: invalid options found."), stderr);
1831 help = _ecore_getopt_find_help(parser);
1833 fputc('\n', stderr);
1834 else if (help->longname)
1835 fprintf(stderr, _(" See --%s.\n"), help->longname);
1837 fprintf(stderr, _(" See -%c.\n"), help->shortname);
1844 * Utility to free list and nodes allocated by @a ECORE_GETOPT_ACTION_APPEND.
1846 * @param list pointer to list to be freed.
1847 * @return always NULL, so you can easily make your list head NULL.
1850 ecore_getopt_list_free(Eina_List *list)
1854 EINA_LIST_FREE(list, data)
1860 * Helper ecore_getopt callback to parse geometry (x:y:w:h).
1862 * @param str Geometry value
1863 * @param storage must be a pointer to @c Eina_Rectangle and will be used to
1864 * store the four values passed in the given string.
1866 * @c callback_data value is ignored, you can safely use @c NULL.
1869 ecore_getopt_callback_geometry_parse(const Ecore_Getopt *parser __UNUSED__,
1870 const Ecore_Getopt_Desc *desc __UNUSED__,
1872 void *data __UNUSED__,
1873 Ecore_Getopt_Value *storage)
1875 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1877 if (sscanf(str, "%d:%d:%d:%d", &v->x, &v->y, &v->w, &v->h) != 4)
1879 fprintf(stderr, _("ERROR: incorrect geometry value '%s'\n"), str);
1887 * Helper ecore_getopt callback to parse geometry size (WxH).
1889 * @param str size value
1890 * @param storage must be a pointer to @c Eina_Rectangle and will be used to
1891 * store the two values passed in the given string and 0 in the x and y
1894 * @c callback_data value is ignored, you can safely use @c NULL.
1897 ecore_getopt_callback_size_parse(const Ecore_Getopt *parser __UNUSED__,
1898 const Ecore_Getopt_Desc *desc __UNUSED__,
1900 void *data __UNUSED__,
1901 Ecore_Getopt_Value *storage)
1903 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1905 if (sscanf(str, "%dx%d", &v->w, &v->h) != 2)
1907 fprintf(stderr, _("ERROR: incorrect size value '%s'\n"), str);