summaryrefslogtreecommitdiff
path: root/src/lib/ecore/ecore_getopt.c
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
commit7d6010b12c47a20e492da808e3192c3f87dab619 (patch)
tree26c6fd189e046a76560c0bc740b85f4d767ae399 /src/lib/ecore/ecore_getopt.c
parent53fc441d5475155965d92da89502fe4634a561b2 (diff)
merge: add escape ecore, fix several bugs
SVN revision: 79995
Diffstat (limited to 'src/lib/ecore/ecore_getopt.c')
-rw-r--r--src/lib/ecore/ecore_getopt.c1936
1 files changed, 1936 insertions, 0 deletions
diff --git a/src/lib/ecore/ecore_getopt.c b/src/lib/ecore/ecore_getopt.c
new file mode 100644
index 0000000000..42e43e8915
--- /dev/null
+++ b/src/lib/ecore/ecore_getopt.c
@@ -0,0 +1,1936 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#ifdef STDC_HEADERS
6# include <stdlib.h>
7# include <stddef.h>
8#else
9# ifdef HAVE_STDLIB_H
10# include <stdlib.h>
11# endif
12#endif
13#ifdef HAVE_ALLOCA_H
14# include <alloca.h>
15#elif !defined alloca
16# ifdef __GNUC__
17# define alloca __builtin_alloca
18# elif defined _AIX
19# define alloca __alloca
20# elif defined _MSC_VER
21# include <malloc.h>
22# define alloca _alloca
23# elif !defined HAVE_ALLOCA
24# ifdef __cplusplus
25extern "C"
26# endif
27void *alloca (size_t);
28# endif
29#endif
30
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <stdarg.h>
35#include <ctype.h>
36
37#ifdef ENABLE_NLS
38# include <libintl.h>
39#else
40# define gettext(x) (x)
41# define dgettext(domain, x) (x)
42#endif
43
44#define _(x) dgettext("ecore", x)
45
46#ifdef _WIN32_WCE
47# include <Evil.h>
48#endif
49
50#ifdef HAVE_EXOTIC
51# include <Exotic.h>
52#endif
53
54#include "Ecore.h"
55#include "Ecore_Getopt.h"
56
57static const char *prog = NULL;
58static char **_argv = NULL;
59static int _argc = 0;
60static int cols = 80;
61static int helpcol = 80 / 3;
62
63static void
64_ecore_getopt_help_print_replace_program(FILE *fp,
65 const Ecore_Getopt *parser EINA_UNUSED,
66 const char *text)
67{
68 do
69 {
70 const char *d = strchr(text, '%');
71
72 if (!d)
73 {
74 fputs(text, fp);
75 break;
76 }
77
78 if (fwrite(text, 1, d - text, fp) != (size_t)(d - text))
79 return;
80 d++;
81 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
82 {
83 fputs(prog ? prog : "???", fp);
84 d += sizeof("prog") - 1;
85 }
86 else
87 {
88 if (d[0] == '%')
89 d++;
90 fputc('%', fp);
91 }
92
93 text = d;
94 }
95 while (text[0] != '\0');
96
97 fputc('\n', fp);
98}
99
100static void
101_ecore_getopt_version(FILE *fp,
102 const Ecore_Getopt *parser)
103{
104 fputs(_("Version:"), fp);
105 fputc(' ', fp);
106 _ecore_getopt_help_print_replace_program(fp, parser, parser->version);
107}
108
109static void
110_ecore_getopt_help_usage(FILE *fp,
111 const Ecore_Getopt *parser)
112{
113 fputs(_("Usage:"), fp);
114 fputc(' ', fp);
115
116 if (!parser->usage)
117 {
118 fprintf(fp, _("%s [options]\n"), prog);
119 return;
120 }
121
122 _ecore_getopt_help_print_replace_program(fp, parser, gettext(parser->usage));
123}
124
125static int
126_ecore_getopt_help_line(FILE *fp,
127 const int base,
128 const int total,
129 int used,
130 const char *text,
131 int len)
132{
133 int linebreak = 0;
134 do
135 {
136 /* process line considering spaces (new line and tabs are spaces!) */
137 while ((used < total) && (len > 0))
138 {
139 const char *space = NULL;
140 int i, todo;
141
142 todo = total - used;
143 if (todo > len)
144 todo = len;
145
146 for (i = 0; i < todo; i++)
147 if (isspace((unsigned char)text[i]))
148 {
149 space = text + i;
150 break;
151 }
152
153 if (space)
154 {
155 i = fwrite(text, 1, i, fp);
156 i++;
157 text += i;
158 len -= i;
159 used += i;
160
161 if (linebreak)
162 {
163 linebreak = 0;
164 continue;
165 }
166
167 if (space[0] == '\n')
168 break;
169 else if (space[0] == '\t')
170 {
171 int c;
172
173 used--;
174 c = ((used / 8) + 1) * 8;
175 if (c < total)
176 {
177 for (; used < c; used++)
178 fputc(' ', fp);
179 }
180 else
181 {
182 text--;
183 len++;
184 break;
185 }
186 }
187 else if (used < total)
188 fputc(space[0], fp);
189 }
190 else
191 {
192 i = fwrite(text, 1, i, fp);
193 text += i;
194 len -= i;
195 used += i;
196 }
197 linebreak = 0;
198 }
199 if (len <= 0)
200 break;
201 linebreak = 1;
202 fputc('\n', fp);
203 for (used = 0; used < base; used++)
204 fputc(' ', fp);
205 }
206 while (1);
207
208 return used;
209}
210
211static void
212_ecore_getopt_help_description(FILE *fp,
213 const Ecore_Getopt *parser)
214{
215 const char *p, *prg, *ver;
216 int used, prglen, verlen;
217
218 p = gettext(parser->description);
219 if (!p)
220 return;
221
222 fputc('\n', fp);
223
224 prg = prog ? prog : "???";
225 ver = parser->version ? parser->version : "???";
226
227 prglen = strlen(prg);
228 verlen = strlen(ver);
229
230 used = 0;
231
232 do
233 {
234 const char *d = strchr(p, '%');
235
236 if (!d)
237 {
238 _ecore_getopt_help_line(fp, 0, cols, used, p, strlen(p));
239 break;
240 }
241
242 used = _ecore_getopt_help_line(fp, 0, cols, used, p, d - p);
243 d++;
244 if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
245 {
246 used = _ecore_getopt_help_line(fp, 0, cols, used, prg, prglen);
247 d += sizeof("prog") - 1;
248 }
249 else if (strncmp(d, "version", sizeof("version") - 1) == 0)
250 {
251 used = _ecore_getopt_help_line(fp, 0, cols, used, ver, verlen);
252 d += sizeof("version") - 1;
253 }
254 else
255 {
256 if (d[0] == '%')
257 d++;
258 used = _ecore_getopt_help_line(fp, 0, cols, used, "%", 1);
259 }
260
261 p = d;
262 }
263 while (p[0] != '\0');
264
265 fputs("\n\n", fp);
266}
267
268static void
269_ecore_getopt_copyright(FILE *fp,
270 const Ecore_Getopt *parser)
271{
272 const char *txt = gettext(parser->copyright);
273 fputs(_("Copyright:"), fp);
274 fputs("\n ", fp);
275 _ecore_getopt_help_line
276 (fp, 3, cols, 3, txt, strlen(txt));
277 fputc('\n', fp);
278}
279
280static void
281_ecore_getopt_license(FILE *fp,
282 const Ecore_Getopt *parser)
283{
284 const char *txt = gettext(parser->license);
285 fputs(_("License:"), fp);
286 fputs("\n ", fp);
287 _ecore_getopt_help_line
288 (fp, 3, cols, 3, txt, strlen(txt));
289 fputc('\n', fp);
290}
291
292static Ecore_Getopt_Desc_Arg_Requirement
293_ecore_getopt_desc_arg_requirement(const Ecore_Getopt_Desc *desc)
294{
295 switch (desc->action)
296 {
297 case ECORE_GETOPT_ACTION_STORE:
298 return desc->action_param.store.arg_req;
299
300 case ECORE_GETOPT_ACTION_STORE_CONST:
301 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
302
303 case ECORE_GETOPT_ACTION_STORE_TRUE:
304 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
305
306 case ECORE_GETOPT_ACTION_STORE_FALSE:
307 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
308
309 case ECORE_GETOPT_ACTION_CHOICE:
310 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
311
312 case ECORE_GETOPT_ACTION_APPEND:
313 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
314
315 case ECORE_GETOPT_ACTION_COUNT:
316 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
317
318 case ECORE_GETOPT_ACTION_CALLBACK:
319 return desc->action_param.callback.arg_req;
320
321 case ECORE_GETOPT_ACTION_HELP:
322 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
323
324 case ECORE_GETOPT_ACTION_VERSION:
325 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
326
327 default:
328 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
329 }
330}
331
332static void
333_ecore_getopt_help_desc_setup_metavar(const Ecore_Getopt_Desc *desc,
334 char *metavar,
335 int *metavarlen,
336 int maxsize)
337{
338 if (desc->metavar)
339 {
340 const char *txt = gettext(desc->metavar);
341 *metavarlen = strlen(txt);
342 if (*metavarlen > maxsize - 1)
343 *metavarlen = maxsize - 1;
344
345 memcpy(metavar, txt, *metavarlen);
346 metavar[*metavarlen] = '\0';
347 }
348 else if (desc->longname)
349 {
350 int i;
351
352 *metavarlen = strlen(desc->longname);
353 if (*metavarlen > maxsize - 1)
354 *metavarlen = maxsize - 1;
355
356 for (i = 0; i < *metavarlen; i++)
357 metavar[i] = toupper((int) desc->longname[i]);
358 metavar[i] = '\0';
359 }
360}
361
362static int
363_ecore_getopt_help_desc_show_arg(FILE *fp,
364 Ecore_Getopt_Desc_Arg_Requirement requirement,
365 const char *metavar,
366 int metavarlen)
367{
368 int used;
369
370 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
371 return 0;
372
373 used = 0;
374
375 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
376 {
377 fputc('[', fp);
378 used++;
379 }
380
381 if (requirement != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
382 {
383 fputc('=', fp);
384 fputs(metavar, fp);
385 used += metavarlen + 1;
386 }
387
388 if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
389 {
390 fputc(']', fp);
391 used++;
392 }
393
394 return used;
395}
396
397static int
398_ecore_getopt_help_desc_store(FILE *fp,
399 const int base,
400 const int total,
401 int used,
402 const Ecore_Getopt_Desc *desc)
403{
404 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
405 char buf[64];
406 const char *str;
407 size_t len;
408
409 fputc('\n', fp);
410 for (used = 0; used < base; used++)
411 fputc(' ', fp);
412
413 switch (store->type)
414 {
415 case ECORE_GETOPT_TYPE_STR:
416 str = "STR";
417 len = sizeof("STR") - 1;
418 break;
419
420 case ECORE_GETOPT_TYPE_BOOL:
421 str = "BOOL";
422 len = sizeof("BOOL") - 1;
423 break;
424
425 case ECORE_GETOPT_TYPE_SHORT:
426 str = "SHORT";
427 len = sizeof("SHORT") - 1;
428 break;
429
430 case ECORE_GETOPT_TYPE_INT:
431 str = "INT";
432 len = sizeof("INT") - 1;
433 break;
434
435 case ECORE_GETOPT_TYPE_LONG:
436 str = "LONG";
437 len = sizeof("LONG") - 1;
438 break;
439
440 case ECORE_GETOPT_TYPE_USHORT:
441 str = "USHORT";
442 len = sizeof("USHORT") - 1;
443 break;
444
445 case ECORE_GETOPT_TYPE_UINT:
446 str = "UINT";
447 len = sizeof("UINT") - 1;
448 break;
449
450 case ECORE_GETOPT_TYPE_ULONG:
451 str = "ULONG";
452 len = sizeof("ULONG") - 1;
453 break;
454
455 case ECORE_GETOPT_TYPE_DOUBLE:
456 str = "DOUBLE";
457 len = sizeof("DOUBLE") - 1;
458 break;
459
460 default:
461 str = "???";
462 len = sizeof("???") - 1;
463 }
464
465 used = _ecore_getopt_help_line
466 (fp, base, total, used, _("Type: "), strlen(_("Type: ")));
467 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
468
469 if (store->arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES)
470 goto end;
471
472 used = _ecore_getopt_help_line
473 (fp, base, total, used, ". ", sizeof(". ") - 1);
474
475 switch (store->type)
476 {
477 case ECORE_GETOPT_TYPE_STR:
478 str = store->def.strv;
479 len = str ? strlen(str) : 0;
480 break;
481
482 case ECORE_GETOPT_TYPE_BOOL:
483 str = store->def.boolv ? "true" : "false";
484 len = strlen(str);
485 break;
486
487 case ECORE_GETOPT_TYPE_SHORT:
488 str = buf;
489 len = snprintf(buf, sizeof(buf), "%hd", store->def.shortv);
490 if (len > sizeof(buf) - 1)
491 len = sizeof(buf) - 1;
492 break;
493
494 case ECORE_GETOPT_TYPE_INT:
495 str = buf;
496 len = snprintf(buf, sizeof(buf), "%d", store->def.intv);
497 if (len > sizeof(buf) - 1)
498 len = sizeof(buf) - 1;
499 break;
500
501 case ECORE_GETOPT_TYPE_LONG:
502 str = buf;
503 len = snprintf(buf, sizeof(buf), "%ld", store->def.longv);
504 if (len > sizeof(buf) - 1)
505 len = sizeof(buf) - 1;
506 break;
507
508 case ECORE_GETOPT_TYPE_USHORT:
509 str = buf;
510 len = snprintf(buf, sizeof(buf), "%hu", store->def.ushortv);
511 if (len > sizeof(buf) - 1)
512 len = sizeof(buf) - 1;
513 break;
514
515 case ECORE_GETOPT_TYPE_UINT:
516 str = buf;
517 len = snprintf(buf, sizeof(buf), "%u", store->def.uintv);
518 if (len > sizeof(buf) - 1)
519 len = sizeof(buf) - 1;
520 break;
521
522 case ECORE_GETOPT_TYPE_ULONG:
523 str = buf;
524 len = snprintf(buf, sizeof(buf), "%lu", store->def.ulongv);
525 if (len > sizeof(buf) - 1)
526 len = sizeof(buf) - 1;
527 break;
528
529 case ECORE_GETOPT_TYPE_DOUBLE:
530 str = buf;
531 len = snprintf(buf, sizeof(buf), "%f", store->def.doublev);
532 if (len > sizeof(buf) - 1)
533 len = sizeof(buf) - 1;
534 break;
535
536 default:
537 str = "???";
538 len = sizeof("???") - 1;
539 }
540
541 used = _ecore_getopt_help_line
542 (fp, base, total, used, _("Default: "), strlen(_("Default: ")));
543 used = _ecore_getopt_help_line(fp, base, total, used, str, len);
544
545end:
546 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
547}
548
549static int
550_ecore_getopt_help_desc_choices(FILE *fp,
551 const int base,
552 const int total,
553 int used,
554 const Ecore_Getopt_Desc *desc)
555{
556 const char *const *itr;
557 const char sep[] = ", ";
558 const int seplen = sizeof(sep) - 1;
559
560 if (used > 0)
561 {
562 fputc('\n', fp);
563 used = 0;
564 }
565 for (; used < base; used++)
566 fputc(' ', fp);
567
568 used = _ecore_getopt_help_line
569 (fp, base, total, used, _("Choices: "), strlen(_("Choices: ")));
570
571 for (itr = desc->action_param.choices; *itr; itr++)
572 {
573 used = _ecore_getopt_help_line
574 (fp, base, total, used, *itr, strlen(*itr));
575 if (itr[1])
576 used = _ecore_getopt_help_line(fp, base, total, used, sep, seplen);
577 }
578
579 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
580}
581
582static void
583_ecore_getopt_help_desc(FILE *fp,
584 const Ecore_Getopt_Desc *desc)
585{
586 Ecore_Getopt_Desc_Arg_Requirement arg_req;
587 char metavar[32] = "ARG";
588 int metavarlen = 3;
589 int used;
590
591 arg_req = _ecore_getopt_desc_arg_requirement(desc);
592 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
593 _ecore_getopt_help_desc_setup_metavar
594 (desc, metavar, &metavarlen, sizeof(metavar));
595
596 fputs(" ", fp);
597 used = 2;
598
599 if (desc->shortname)
600 {
601 fputc('-', fp);
602 fputc(desc->shortname, fp);
603 used += 2;
604 used += _ecore_getopt_help_desc_show_arg
605 (fp, arg_req, metavar, metavarlen);
606 }
607
608 if (desc->shortname && desc->longname)
609 {
610 fputs(", ", fp);
611 used += 2;
612 }
613
614 if (desc->longname)
615 {
616 int namelen = strlen(desc->longname);
617
618 fputs("--", fp);
619 fputs(desc->longname, fp);
620 used += 2 + namelen;
621 used += _ecore_getopt_help_desc_show_arg
622 (fp, arg_req, metavar, metavarlen);
623 }
624
625 if (!desc->help)
626 goto end;
627
628 if (used + 3 >= helpcol)
629 {
630 fputc('\n', fp);
631 used = 0;
632 }
633
634 for (; used < helpcol; used++)
635 fputc(' ', fp);
636
637 used = _ecore_getopt_help_line
638 (fp, helpcol, cols, used, desc->help, strlen(desc->help));
639
640 switch (desc->action)
641 {
642 case ECORE_GETOPT_ACTION_STORE:
643 _ecore_getopt_help_desc_store(fp, helpcol, cols, used, desc);
644 break;
645
646 case ECORE_GETOPT_ACTION_CHOICE:
647 _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc);
648 break;
649
650 default:
651 break;
652 }
653
654end:
655 fputc('\n', fp);
656}
657
658static Eina_Bool
659_ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc)
660{
661 return (desc->shortname == '\0') && (!desc->longname);
662}
663
664static void
665_ecore_getopt_help_options(FILE *fp,
666 const Ecore_Getopt *parser)
667{
668 const Ecore_Getopt_Desc *desc;
669
670 fputs(_("Options:\n"), fp);
671
672 for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
673 _ecore_getopt_help_desc(fp, desc);
674
675 fputc('\n', fp);
676}
677
678/**
679 * Show nicely formatted help message for the given parser.
680 *
681 * @param fp The file the message will be printed on.
682 * @param parser The parser to be used.
683 */
684EAPI void
685ecore_getopt_help(FILE *fp,
686 const Ecore_Getopt *parser)
687{
688 const char *var;
689
690 EINA_MAIN_LOOP_CHECK_RETURN;
691 if (!parser) return;
692
693 if (_argc < 1)
694 {
695 ecore_app_args_get(&_argc, &_argv);
696 if ((_argc > 0) && (_argv[0]))
697 prog = _argv[0];
698 else
699 prog = parser->prog;
700 }
701
702 var = getenv("COLUMNS");
703 if (var)
704 {
705 cols = atoi(var);
706 if (cols < 20)
707 cols = 20;
708
709 helpcol = cols / 3;
710 }
711
712 _ecore_getopt_help_usage(fp, parser);
713 _ecore_getopt_help_description(fp, parser);
714 _ecore_getopt_help_options(fp, parser);
715}
716
717static const Ecore_Getopt_Desc *
718_ecore_getopt_parse_find_long(const Ecore_Getopt *parser,
719 const char *name)
720{
721 const Ecore_Getopt_Desc *desc = parser->descs;
722 const char *p = strchr(name, '=');
723 int len = 0;
724
725 if (p)
726 len = p - name;
727
728 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
729 {
730 if (!desc->longname)
731 continue;
732
733 if (p)
734 {
735 if ((strncmp(name, desc->longname, len) == 0) &&
736 (desc->longname[len] == '\0'))
737 return desc;
738 }
739 else
740 {
741 if (strcmp(name, desc->longname) == 0)
742 return desc;
743 }
744 }
745
746 return NULL;
747}
748
749static const Ecore_Getopt_Desc *
750_ecore_getopt_parse_find_short(const Ecore_Getopt *parser,
751 char name)
752{
753 const Ecore_Getopt_Desc *desc = parser->descs;
754 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
755 if (name == desc->shortname)
756 return desc;
757 return NULL;
758}
759
760static int
761_ecore_getopt_parse_find_nonargs_base(const Ecore_Getopt *parser,
762 int argc,
763 char **argv)
764{
765 char **nonargs;
766 int src, dst, used, base;
767
768 nonargs = alloca(sizeof(char *) * argc);
769 src = 1;
770 dst = 1;
771 used = 0;
772 base = 0;
773 while (src < argc)
774 {
775 const Ecore_Getopt_Desc *desc;
776 Ecore_Getopt_Desc_Arg_Requirement arg_req;
777 char *arg = argv[src];
778
779 if (arg[0] != '-')
780 goto found_nonarg;
781
782 if (arg[1] == '-')
783 {
784 if (arg[2] == '\0') /* explicit end of options, "--" */
785 {
786 base = 1;
787 break;
788 }
789 desc = _ecore_getopt_parse_find_long(parser, arg + 2);
790 }
791 else
792 desc = _ecore_getopt_parse_find_short(parser, arg[1]);
793
794 if (!desc)
795 {
796 if (arg[1] == '-')
797 fprintf(stderr, _("ERROR: unknown option --%s.\n"), arg + 2);
798 else
799 fprintf(stderr, _("ERROR: unknown option -%c.\n"), arg[1]);
800 if (parser->strict)
801 {
802 memmove(argv + dst, nonargs, used * sizeof(char *));
803 return -1;
804 }
805 else
806 goto found_nonarg;
807 }
808
809 if (src != dst)
810 argv[dst] = argv[src];
811 src++;
812 dst++;
813
814 arg_req = _ecore_getopt_desc_arg_requirement(desc);
815 if (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
816 continue;
817
818 if (strchr(arg, '='))
819 continue;
820
821 if ((src >= argc) || (argv[src][0] == '-'))
822 continue;
823
824 if (src != dst)
825 argv[dst] = argv[src];
826 src++;
827 dst++;
828 continue;
829
830found_nonarg:
831 nonargs[used] = arg;
832 used++;
833 src++;
834 }
835
836 if (!base) /* '--' not found */
837 base = dst;
838 else
839 {
840 base = dst;
841 if (src != dst)
842 argv[dst] = argv[src];
843 dst++;
844 }
845
846 memmove(argv + dst, nonargs, used * sizeof(char *));
847 return base;
848}
849
850static void
851_ecore_getopt_desc_print_error(const Ecore_Getopt_Desc *desc,
852 const char *fmt,
853 ...)
854{
855 va_list ap;
856
857 fputs(_("ERROR: "), stderr);
858
859 if (desc->shortname)
860 {
861 fputc('-', stderr);
862 fputc(desc->shortname, stderr);
863 }
864
865 if (desc->shortname && desc->longname)
866 fputs(", ", stderr);
867
868 if (desc->longname)
869 {
870 fputs("--", stderr);
871 fputs(desc->longname, stderr);
872 }
873
874 fputs(": ", stderr);
875
876 va_start(ap, fmt);
877 vfprintf(stderr, fmt, ap);
878 va_end(ap);
879}
880
881static Eina_Bool
882_ecore_getopt_parse_bool(const char *str,
883 Eina_Bool *v)
884{
885 if ((strcmp(str, "0") == 0) ||
886 (strcasecmp(str, "f") == 0) ||
887 (strcasecmp(str, "false") == 0) ||
888 (strcasecmp(str, "no") == 0) ||
889 (strcasecmp(str, "off") == 0)
890 )
891 {
892 *v = EINA_FALSE;
893 return EINA_TRUE;
894 }
895 else if ((strcmp(str, "1") == 0) ||
896 (strcasecmp(str, "t") == 0) ||
897 (strcasecmp(str, "true") == 0) ||
898 (strcasecmp(str, "yes") == 0) ||
899 (strcasecmp(str, "on") == 0)
900 )
901 {
902 *v = EINA_TRUE;
903 return EINA_TRUE;
904 }
905
906 return EINA_FALSE;
907}
908
909static Eina_Bool
910_ecore_getopt_parse_long(const char *str,
911 long int *v)
912{
913 char *endptr = NULL;
914 *v = strtol(str, &endptr, 0);
915 return endptr > str;
916}
917
918static Eina_Bool
919_ecore_getopt_parse_double(const char *str,
920 double *v)
921{
922 char *endptr = NULL;
923 *v = strtod(str, &endptr);
924 return endptr > str;
925}
926
927static Eina_Bool
928_ecore_getopt_parse_store(const Ecore_Getopt *parser EINA_UNUSED,
929 const Ecore_Getopt_Desc *desc,
930 Ecore_Getopt_Value *value,
931 const char *arg_val)
932{
933 const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
934 long int v;
935 double d;
936 Eina_Bool b;
937
938 if (!value->ptrp)
939 {
940 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
941 return EINA_FALSE;
942 }
943
944 switch (store->arg_req)
945 {
946 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
947 goto use_optional;
948
949 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
950 if (!arg_val)
951 goto use_optional;
952
953 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
954 break;
955 }
956
957 switch (store->type)
958 {
959 case ECORE_GETOPT_TYPE_STR:
960 *value->strp = (char *)arg_val;
961 return EINA_TRUE;
962
963 case ECORE_GETOPT_TYPE_BOOL:
964 if (_ecore_getopt_parse_bool(arg_val, &b))
965 {
966 *value->boolp = b;
967 return EINA_TRUE;
968 }
969 else
970 {
971 _ecore_getopt_desc_print_error
972 (desc, _("unknown boolean value %s.\n"), arg_val);
973 return EINA_FALSE;
974 }
975
976 case ECORE_GETOPT_TYPE_SHORT:
977 if (!_ecore_getopt_parse_long(arg_val, &v))
978 goto error;
979 *value->shortp = v;
980 return EINA_TRUE;
981
982 case ECORE_GETOPT_TYPE_INT:
983 if (!_ecore_getopt_parse_long(arg_val, &v))
984 goto error;
985 *value->intp = v;
986 return EINA_TRUE;
987
988 case ECORE_GETOPT_TYPE_LONG:
989 if (!_ecore_getopt_parse_long(arg_val, &v))
990 goto error;
991 *value->longp = v;
992 return EINA_TRUE;
993
994 case ECORE_GETOPT_TYPE_USHORT:
995 if (!_ecore_getopt_parse_long(arg_val, &v))
996 goto error;
997 *value->ushortp = v;
998 return EINA_TRUE;
999
1000 case ECORE_GETOPT_TYPE_UINT:
1001 if (!_ecore_getopt_parse_long(arg_val, &v))
1002 goto error;
1003 *value->uintp = v;
1004 return EINA_TRUE;
1005
1006 case ECORE_GETOPT_TYPE_ULONG:
1007 if (!_ecore_getopt_parse_long(arg_val, &v))
1008 goto error;
1009 *value->ulongp = v;
1010 return EINA_TRUE;
1011
1012 case ECORE_GETOPT_TYPE_DOUBLE:
1013 if (!_ecore_getopt_parse_double(arg_val, &d))
1014 goto error;
1015 *value->doublep = d;
1016 break;
1017 }
1018
1019 return EINA_TRUE;
1020
1021error:
1022 _ecore_getopt_desc_print_error
1023 (desc, _("invalid number format %s\n"), arg_val);
1024 return EINA_FALSE;
1025
1026use_optional:
1027 switch (store->type)
1028 {
1029 case ECORE_GETOPT_TYPE_STR:
1030 *value->strp = (char *)store->def.strv;
1031 break;
1032
1033 case ECORE_GETOPT_TYPE_BOOL:
1034 *value->boolp = store->def.boolv;
1035 break;
1036
1037 case ECORE_GETOPT_TYPE_SHORT:
1038 *value->shortp = store->def.shortv;
1039 break;
1040
1041 case ECORE_GETOPT_TYPE_INT:
1042 *value->intp = store->def.intv;
1043 break;
1044
1045 case ECORE_GETOPT_TYPE_LONG:
1046 *value->longp = store->def.longv;
1047 break;
1048
1049 case ECORE_GETOPT_TYPE_USHORT:
1050 *value->ushortp = store->def.ushortv;
1051 break;
1052
1053 case ECORE_GETOPT_TYPE_UINT:
1054 *value->uintp = store->def.uintv;
1055 break;
1056
1057 case ECORE_GETOPT_TYPE_ULONG:
1058 *value->ulongp = store->def.ulongv;
1059 break;
1060
1061 case ECORE_GETOPT_TYPE_DOUBLE:
1062 *value->doublep = store->def.doublev;
1063 break;
1064 }
1065
1066 return EINA_TRUE;
1067}
1068
1069static Eina_Bool
1070_ecore_getopt_parse_store_const(const Ecore_Getopt *parser EINA_UNUSED,
1071 const Ecore_Getopt_Desc *desc,
1072 Ecore_Getopt_Value *val,
1073 const char *arg_val EINA_UNUSED)
1074{
1075 if (!val->ptrp)
1076 {
1077 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1078 return EINA_FALSE;
1079 }
1080
1081 *val->ptrp = (void *)desc->action_param.store_const;
1082 return EINA_TRUE;
1083}
1084
1085static Eina_Bool
1086_ecore_getopt_parse_store_true(const Ecore_Getopt *parser EINA_UNUSED,
1087 const Ecore_Getopt_Desc *desc,
1088 Ecore_Getopt_Value *val,
1089 const char *arg_val EINA_UNUSED)
1090{
1091 if (!val->boolp)
1092 {
1093 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1094 return EINA_FALSE;
1095 }
1096 *val->boolp = EINA_TRUE;
1097 return EINA_TRUE;
1098}
1099
1100static Eina_Bool
1101_ecore_getopt_parse_store_false(const Ecore_Getopt *parser EINA_UNUSED,
1102 const Ecore_Getopt_Desc *desc,
1103 Ecore_Getopt_Value *val,
1104 const char *arg_val EINA_UNUSED)
1105{
1106 if (!val->boolp)
1107 {
1108 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1109 return EINA_FALSE;
1110 }
1111 *val->boolp = EINA_FALSE;
1112 return EINA_TRUE;
1113}
1114
1115static Eina_Bool
1116_ecore_getopt_parse_choice(const Ecore_Getopt *parser EINA_UNUSED,
1117 const Ecore_Getopt_Desc *desc,
1118 Ecore_Getopt_Value *val,
1119 const char *arg_val)
1120{
1121 const char *const *pchoice;
1122
1123 if (!val->strp)
1124 {
1125 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1126 return EINA_FALSE;
1127 }
1128
1129 pchoice = desc->action_param.choices;
1130 for (; *pchoice; pchoice++)
1131 if (strcmp(*pchoice, arg_val) == 0)
1132 {
1133 *val->strp = (char *)*pchoice;
1134 return EINA_TRUE;
1135 }
1136
1137 _ecore_getopt_desc_print_error
1138 (desc, _("invalid choice \"%s\". Valid values are: "), arg_val);
1139
1140 pchoice = desc->action_param.choices;
1141 for (; *pchoice; pchoice++)
1142 {
1143 fputs(*pchoice, stderr);
1144 if (pchoice[1])
1145 fputs(", ", stderr);
1146 }
1147
1148 fputs(".\n", stderr);
1149 return EINA_FALSE;
1150}
1151
1152static Eina_Bool
1153_ecore_getopt_parse_append(const Ecore_Getopt *parser EINA_UNUSED,
1154 const Ecore_Getopt_Desc *desc,
1155 Ecore_Getopt_Value *val,
1156 const char *arg_val)
1157{
1158 void *data;
1159 long int v;
1160 double d;
1161 Eina_Bool b;
1162
1163 if (!arg_val)
1164 {
1165 _ecore_getopt_desc_print_error
1166 (desc, _("missing parameter to append.\n"));
1167 return EINA_FALSE;
1168 }
1169
1170 if (!val->listp)
1171 {
1172 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1173 return EINA_FALSE;
1174 }
1175
1176 switch (desc->action_param.append_type)
1177 {
1178 case ECORE_GETOPT_TYPE_STR:
1179 data = strdup(arg_val);
1180 break;
1181
1182 case ECORE_GETOPT_TYPE_BOOL:
1183 {
1184 if (_ecore_getopt_parse_bool(arg_val, &b))
1185 {
1186 data = malloc(sizeof(Eina_Bool));
1187 if (data)
1188 *(Eina_Bool *)data = b;
1189 }
1190 else
1191 {
1192 _ecore_getopt_desc_print_error(desc, _("unknown boolean value %s.\n"), arg_val);
1193 return EINA_FALSE;
1194 }
1195 }
1196 break;
1197
1198 case ECORE_GETOPT_TYPE_SHORT:
1199 {
1200 if (!_ecore_getopt_parse_long(arg_val, &v))
1201 goto error;
1202 data = malloc(sizeof(short));
1203 if (data)
1204 *(short *)data = (short)v;
1205 }
1206 break;
1207
1208 case ECORE_GETOPT_TYPE_INT:
1209 {
1210 if (!_ecore_getopt_parse_long(arg_val, &v))
1211 goto error;
1212 data = malloc(sizeof(int));
1213 if (data)
1214 *(int *)data = (int)v;
1215 }
1216 break;
1217
1218 case ECORE_GETOPT_TYPE_LONG:
1219 {
1220 if (!_ecore_getopt_parse_long(arg_val, &v))
1221 goto error;
1222 data = malloc(sizeof(long));
1223 if (data)
1224 *(long *)data = v;
1225 }
1226 break;
1227
1228 case ECORE_GETOPT_TYPE_USHORT:
1229 {
1230 if (!_ecore_getopt_parse_long(arg_val, &v))
1231 goto error;
1232 data = malloc(sizeof(unsigned short));
1233 if (data)
1234 *(unsigned short *)data = (unsigned short)v;
1235 }
1236 break;
1237
1238 case ECORE_GETOPT_TYPE_UINT:
1239 {
1240 if (!_ecore_getopt_parse_long(arg_val, &v))
1241 goto error;
1242 data = malloc(sizeof(unsigned int));
1243 if (data)
1244 *(unsigned int *)data = (unsigned int)v;
1245 }
1246 break;
1247
1248 case ECORE_GETOPT_TYPE_ULONG:
1249 {
1250 if (!_ecore_getopt_parse_long(arg_val, &v))
1251 goto error;
1252 data = malloc(sizeof(unsigned long));
1253 if (data)
1254 *(unsigned long *)data = v;
1255 }
1256 break;
1257
1258 case ECORE_GETOPT_TYPE_DOUBLE:
1259 {
1260 if (!_ecore_getopt_parse_double(arg_val, &d))
1261 goto error;
1262 data = malloc(sizeof(double));
1263 if (data)
1264 *(double *)data = d;
1265 }
1266 break;
1267
1268 default:
1269 {
1270 _ecore_getopt_desc_print_error(desc, _("could not parse value.\n"));
1271 return EINA_FALSE;
1272 }
1273 }
1274
1275 *val->listp = eina_list_append(*val->listp, data);
1276 return EINA_TRUE;
1277
1278error:
1279 _ecore_getopt_desc_print_error
1280 (desc, _("invalid number format %s\n"), arg_val);
1281 return EINA_FALSE;
1282}
1283
1284static Eina_Bool
1285_ecore_getopt_parse_count(const Ecore_Getopt *parser EINA_UNUSED,
1286 const Ecore_Getopt_Desc *desc,
1287 Ecore_Getopt_Value *val,
1288 const char *arg_val EINA_UNUSED)
1289{
1290 if (!val->intp)
1291 {
1292 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1293 return EINA_FALSE;
1294 }
1295
1296 (*val->intp)++;
1297 return EINA_TRUE;
1298}
1299
1300static Eina_Bool
1301_ecore_getopt_parse_callback(const Ecore_Getopt *parser,
1302 const Ecore_Getopt_Desc *desc,
1303 Ecore_Getopt_Value *val,
1304 const char *arg_val)
1305{
1306 const Ecore_Getopt_Desc_Callback *cb = &desc->action_param.callback;
1307
1308 switch (cb->arg_req)
1309 {
1310 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
1311 arg_val = cb->def;
1312 break;
1313
1314 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
1315 if (!arg_val)
1316 arg_val = cb->def;
1317 break;
1318
1319 case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
1320 break;
1321 }
1322
1323 if (cb->arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1324 {
1325 if ((!arg_val) || (arg_val[0] == '\0'))
1326 {
1327 _ecore_getopt_desc_print_error(desc, _("missing parameter.\n"));
1328 return EINA_FALSE;
1329 }
1330
1331 if (!val->ptrp)
1332 {
1333 _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
1334 return EINA_FALSE;
1335 }
1336 }
1337
1338 if (!cb->func)
1339 {
1340 _ecore_getopt_desc_print_error(desc, _("missing callback function!\n"));
1341 return EINA_FALSE;
1342 }
1343
1344 return cb->func(parser, desc, arg_val, (void *)cb->data, val);
1345}
1346
1347static Eina_Bool
1348_ecore_getopt_parse_help(const Ecore_Getopt *parser,
1349 const Ecore_Getopt_Desc *desc EINA_UNUSED,
1350 Ecore_Getopt_Value *val,
1351 const char *arg_val EINA_UNUSED)
1352{
1353 if (val->boolp)
1354 (*val->boolp) = EINA_TRUE;
1355 ecore_getopt_help(stdout, parser);
1356 return EINA_TRUE;
1357}
1358
1359static Eina_Bool
1360_ecore_getopt_parse_version(const Ecore_Getopt *parser,
1361 const Ecore_Getopt_Desc *desc,
1362 Ecore_Getopt_Value *val,
1363 const char *arg_val EINA_UNUSED)
1364{
1365 if (val->boolp)
1366 (*val->boolp) = EINA_TRUE;
1367 if (!parser->version)
1368 {
1369 _ecore_getopt_desc_print_error(desc, _("no version was defined.\n"));
1370 return EINA_FALSE;
1371 }
1372 _ecore_getopt_version(stdout, parser);
1373 return EINA_TRUE;
1374}
1375
1376static Eina_Bool
1377_ecore_getopt_parse_copyright(const Ecore_Getopt *parser,
1378 const Ecore_Getopt_Desc *desc,
1379 Ecore_Getopt_Value *val,
1380 const char *arg_val EINA_UNUSED)
1381{
1382 if (val->boolp)
1383 (*val->boolp) = EINA_TRUE;
1384 if (!parser->copyright)
1385 {
1386 _ecore_getopt_desc_print_error(desc, _("no copyright was defined.\n"));
1387 return EINA_FALSE;
1388 }
1389 _ecore_getopt_copyright(stdout, parser);
1390 return EINA_TRUE;
1391}
1392
1393static Eina_Bool
1394_ecore_getopt_parse_license(const Ecore_Getopt *parser,
1395 const Ecore_Getopt_Desc *desc,
1396 Ecore_Getopt_Value *val,
1397 const char *arg_val EINA_UNUSED)
1398{
1399 if (val->boolp)
1400 (*val->boolp) = EINA_TRUE;
1401 if (!parser->license)
1402 {
1403 _ecore_getopt_desc_print_error(desc, _("no license was defined.\n"));
1404 return EINA_FALSE;
1405 }
1406 _ecore_getopt_license(stdout, parser);
1407 return EINA_TRUE;
1408}
1409
1410static Eina_Bool
1411_ecore_getopt_desc_handle(const Ecore_Getopt *parser,
1412 const Ecore_Getopt_Desc *desc,
1413 Ecore_Getopt_Value *value,
1414 const char *arg_val)
1415{
1416 switch (desc->action)
1417 {
1418 case ECORE_GETOPT_ACTION_STORE:
1419 return _ecore_getopt_parse_store(parser, desc, value, arg_val);
1420
1421 case ECORE_GETOPT_ACTION_STORE_CONST:
1422 return _ecore_getopt_parse_store_const(parser, desc, value, arg_val);
1423
1424 case ECORE_GETOPT_ACTION_STORE_TRUE:
1425 return _ecore_getopt_parse_store_true(parser, desc, value, arg_val);
1426
1427 case ECORE_GETOPT_ACTION_STORE_FALSE:
1428 return _ecore_getopt_parse_store_false(parser, desc, value, arg_val);
1429
1430 case ECORE_GETOPT_ACTION_CHOICE:
1431 return _ecore_getopt_parse_choice(parser, desc, value, arg_val);
1432
1433 case ECORE_GETOPT_ACTION_APPEND:
1434 return _ecore_getopt_parse_append(parser, desc, value, arg_val);
1435
1436 case ECORE_GETOPT_ACTION_COUNT:
1437 return _ecore_getopt_parse_count(parser, desc, value, arg_val);
1438
1439 case ECORE_GETOPT_ACTION_CALLBACK:
1440 return _ecore_getopt_parse_callback(parser, desc, value, arg_val);
1441
1442 case ECORE_GETOPT_ACTION_HELP:
1443 return _ecore_getopt_parse_help(parser, desc, value, arg_val);
1444
1445 case ECORE_GETOPT_ACTION_VERSION:
1446 return _ecore_getopt_parse_version(parser, desc, value, arg_val);
1447
1448 case ECORE_GETOPT_ACTION_COPYRIGHT:
1449 return _ecore_getopt_parse_copyright(parser, desc, value, arg_val);
1450
1451 case ECORE_GETOPT_ACTION_LICENSE:
1452 return _ecore_getopt_parse_license(parser, desc, value, arg_val);
1453
1454 default:
1455 return EINA_FALSE;
1456 }
1457}
1458
1459static Eina_Bool
1460_ecore_getopt_parse_arg_long(const Ecore_Getopt *parser,
1461 Ecore_Getopt_Value *values,
1462 int argc EINA_UNUSED,
1463 char **argv,
1464 int *idx,
1465 int *nonargs,
1466 const char *arg)
1467{
1468 const Ecore_Getopt_Desc *desc;
1469 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1470 const char *arg_val;
1471 int desc_idx;
1472 Ecore_Getopt_Value *value;
1473 Eina_Bool ret;
1474
1475 desc = _ecore_getopt_parse_find_long(parser, arg);
1476 if (!desc)
1477 {
1478 fprintf(stderr, _("ERROR: unknown option --%s, ignored.\n"), arg);
1479 if (parser->strict)
1480 return EINA_FALSE;
1481
1482 (*idx)++;
1483 return EINA_TRUE;
1484 }
1485
1486 (*idx)++;
1487
1488 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1489 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1490 {
1491 arg_val = strchr(arg, '=');
1492 if (arg_val)
1493 arg_val++;
1494 else
1495 {
1496 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1497 {
1498 arg_val = argv[*idx];
1499 (*idx)++;
1500 }
1501 else
1502 arg_val = NULL;
1503 }
1504
1505 if (arg_val && arg_val[0] == '\0')
1506 arg_val = NULL;
1507
1508 if ((!arg_val) && (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1509 {
1510 fprintf
1511 (stderr, _("ERROR: option --%s requires an argument!\n"), arg);
1512 if (parser->strict)
1513 return EINA_FALSE;
1514 return EINA_TRUE;
1515 }
1516 }
1517 else
1518 arg_val = NULL;
1519
1520 desc_idx = desc - parser->descs;
1521 value = values + desc_idx;
1522 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1523 if ((!ret) && parser->strict)
1524 return EINA_FALSE;
1525
1526 return EINA_TRUE;
1527}
1528
1529static Eina_Bool
1530_ecore_getopt_parse_arg_short(const Ecore_Getopt *parser,
1531 Ecore_Getopt_Value *values,
1532 int argc EINA_UNUSED,
1533 char **argv,
1534 int *idx,
1535 int *nonargs,
1536 const char *arg)
1537{
1538 int run = 1;
1539 while (run && (arg[0] != '\0'))
1540 {
1541 int opt = arg[0];
1542 const Ecore_Getopt_Desc *desc;
1543 Ecore_Getopt_Desc_Arg_Requirement arg_req;
1544 const char *arg_val;
1545 int desc_idx;
1546 Ecore_Getopt_Value *value;
1547 Eina_Bool ret;
1548
1549 desc = _ecore_getopt_parse_find_short(parser, arg[0]);
1550 if (!desc)
1551 {
1552 fprintf
1553 (stderr, _("ERROR: unknown option -%c, ignored.\n"), arg[0]);
1554 if (parser->strict)
1555 return EINA_FALSE;
1556
1557 arg++;
1558 continue;
1559 }
1560
1561 arg++;
1562
1563 arg_req = _ecore_getopt_desc_arg_requirement(desc);
1564 if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
1565 {
1566 (*idx)++;
1567 run = 0;
1568
1569 if (arg[0] == '=')
1570 arg_val = arg + 1;
1571 else if (arg[0] != '\0')
1572 arg_val = arg;
1573 else
1574 {
1575 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
1576 {
1577 arg_val = argv[*idx];
1578 (*idx)++;
1579 }
1580 else
1581 arg_val = NULL;
1582 }
1583
1584 if (arg_val && arg_val[0] == '\0')
1585 arg_val = NULL;
1586
1587 if ((!arg_val) &&
1588 (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
1589 {
1590 fprintf
1591 (stderr, _("ERROR: option -%c requires an argument!\n"),
1592 opt);
1593 if (parser->strict)
1594 return EINA_FALSE;
1595 return EINA_TRUE;
1596 }
1597 }
1598 else
1599 arg_val = NULL;
1600
1601 desc_idx = desc - parser->descs;
1602 value = values + desc_idx;
1603 ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
1604 if ((!ret) && parser->strict)
1605 return EINA_FALSE;
1606 }
1607
1608 if (run)
1609 (*idx)++;
1610
1611 return EINA_TRUE;
1612}
1613
1614static Eina_Bool
1615_ecore_getopt_parse_arg(const Ecore_Getopt *parser,
1616 Ecore_Getopt_Value *values,
1617 int argc,
1618 char **argv,
1619 int *idx,
1620 int *nonargs)
1621{
1622 char *arg = argv[*idx];
1623
1624 if (arg[0] != '-')
1625 {
1626 char **dst, **src, **src_end;
1627
1628 dst = argv + *idx;
1629 src = dst + 1;
1630 src_end = src + *nonargs - *idx - 1;
1631
1632 for (; src < src_end; src++, dst++)
1633 *dst = *src;
1634
1635 *dst = arg;
1636 (*nonargs)--;
1637 return EINA_TRUE;
1638 }
1639
1640 if (arg[1] == '-')
1641 return _ecore_getopt_parse_arg_long(parser, values, argc, argv, idx, nonargs, arg + 2);
1642 else
1643 return _ecore_getopt_parse_arg_short(parser, values, argc, argv, idx, nonargs, arg + 1);
1644}
1645
1646static const Ecore_Getopt_Desc *
1647_ecore_getopt_parse_find_short_other(const Ecore_Getopt *parser,
1648 const Ecore_Getopt_Desc *orig)
1649{
1650 const Ecore_Getopt_Desc *desc = parser->descs;
1651 const char c = orig->shortname;
1652
1653 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1654 {
1655 if (desc == orig)
1656 return NULL;
1657
1658 if (c == desc->shortname)
1659 return desc;
1660 }
1661
1662 return NULL;
1663}
1664
1665static const Ecore_Getopt_Desc *
1666_ecore_getopt_parse_find_long_other(const Ecore_Getopt *parser,
1667 const Ecore_Getopt_Desc *orig)
1668{
1669 const Ecore_Getopt_Desc *desc = parser->descs;
1670 const char *name = orig->longname;
1671
1672 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1673 {
1674 if (desc == orig)
1675 return NULL;
1676
1677 if (desc->longname && (strcmp(name, desc->longname) == 0))
1678 return desc;
1679 }
1680
1681 return NULL;
1682}
1683
1684/**
1685 * Check parser for duplicate entries, print them out.
1686 *
1687 * @return @c EINA_TRUE if there are duplicates, @c EINA_FALSE otherwise.
1688 * @param parser The parser to be checked.
1689 */
1690EAPI Eina_Bool
1691ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser)
1692{
1693 const Ecore_Getopt_Desc *desc = parser->descs;
1694 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1695 {
1696 if (desc->shortname)
1697 {
1698 const Ecore_Getopt_Desc *other;
1699 other = _ecore_getopt_parse_find_short_other(parser, desc);
1700 if (other)
1701 {
1702 _ecore_getopt_desc_print_error(desc, "short name -%c already exists.", desc->shortname);
1703
1704 if (other->longname)
1705 fprintf(stderr, " Other is --%s.\n", other->longname);
1706 else
1707 fputc('\n', stderr);
1708 return EINA_TRUE;
1709 }
1710 }
1711
1712 if (desc->longname)
1713 {
1714 const Ecore_Getopt_Desc *other;
1715 other = _ecore_getopt_parse_find_long_other(parser, desc);
1716 if (other)
1717 {
1718 _ecore_getopt_desc_print_error(desc, "long name --%s already exists.", desc->longname);
1719
1720 if (other->shortname)
1721 fprintf(stderr, " Other is -%c.\n", other->shortname);
1722 else
1723 fputc('\n', stderr);
1724 return EINA_TRUE;
1725 }
1726 }
1727 }
1728 return EINA_FALSE;
1729}
1730
1731static const Ecore_Getopt_Desc *
1732_ecore_getopt_find_help(const Ecore_Getopt *parser)
1733{
1734 const Ecore_Getopt_Desc *desc = parser->descs;
1735 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
1736 if (desc->action == ECORE_GETOPT_ACTION_HELP)
1737 return desc;
1738 return NULL;
1739}
1740
1741/**
1742 * Parse command line parameters.
1743 *
1744 * Walks the command line parameters and parse them based on @a parser
1745 * description, doing actions based on @c parser->descs->action, like
1746 * showing help text, license, copyright, storing values in values and
1747 * so on.
1748 *
1749 * It is expected that values is of the same size than @c parser->descs,
1750 * options that do not need a value it will be left untouched.
1751 *
1752 * All values are expected to be initialized before use. Options with
1753 * action @c ECORE_GETOPT_ACTION_STORE and non required arguments
1754 * (others than @c ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES), are expected
1755 * to provide a value in @c def to be used.
1756 *
1757 * The following actions will store @c 1 on value as a boolean
1758 * (@c value->boolp) if it's not @c NULL to indicate these actions were
1759 * executed:
1760 * - @c ECORE_GETOPT_ACTION_HELP
1761 * - @c ECORE_GETOPT_ACTION_VERSION
1762 * - @c ECORE_GETOPT_ACTION_COPYRIGHT
1763 * - @c ECORE_GETOPT_ACTION_LICENSE
1764 *
1765 * Just @c ECORE_GETOPT_ACTION_APPEND will allocate memory and thus
1766 * need to be freed. For consistency between all of appended subtypes,
1767 * @c eina_list->data will contain an allocated memory with the value,
1768 * that is, for @c ECORE_GETOPT_TYPE_STR it will contain a copy of the
1769 * argument, @c ECORE_GETOPT_TYPE_INT a pointer to an allocated
1770 * integer and so on.
1771 *
1772 * If parser is in strict mode (see @c Ecore_Getopt->strict), then any
1773 * error will abort parsing and @c -1 is returned. Otherwise it will try
1774 * to continue as far as possible.
1775 *
1776 * This function may reorder @a argv elements.
1777 *
1778 * Translation of help strings (description), metavar, usage, license
1779 * and copyright may be translated, standard/global gettext() call
1780 * will be applied on them if ecore was compiled with such support.
1781 *
1782 * @param parser description of how to work.
1783 * @param values where to store values, it is assumed that this is a vector
1784 * of the same size as @c parser->descs. Values should be previously
1785 * initialized.
1786 * @param argc how many elements in @a argv. If not provided it will be
1787 * retrieved with ecore_app_args_get().
1788 * @param argv command line parameters.
1789 *
1790 * @return index of first non-option parameter or -1 on error.
1791 */
1792EAPI int
1793ecore_getopt_parse(const Ecore_Getopt *parser,
1794 Ecore_Getopt_Value *values,
1795 int argc,
1796 char **argv)
1797{
1798 int i, nonargs;
1799
1800 if (!parser)
1801 {
1802 fputs(_("ERROR: no parser provided.\n"), stderr);
1803 return -1;
1804 }
1805 if (!values)
1806 {
1807 fputs(_("ERROR: no values provided.\n"), stderr);
1808 return -1;
1809 }
1810
1811 if ((argc < 1) || (!argv))
1812 ecore_app_args_get(&argc, &argv);
1813
1814 if (argc < 1)
1815 {
1816 fputs(_("ERROR: no arguments provided.\n"), stderr);
1817 return -1;
1818 }
1819
1820 if (argv[0])
1821 prog = argv[0];
1822 else
1823 prog = parser->prog;
1824
1825 nonargs = _ecore_getopt_parse_find_nonargs_base(parser, argc, argv);
1826 if (nonargs < 0)
1827 goto error;
1828
1829 if (nonargs > argc)
1830 nonargs = argc;
1831
1832 i = 1;
1833 while (i < nonargs)
1834 if (!_ecore_getopt_parse_arg(parser, values, argc, argv, &i, &nonargs))
1835 goto error;
1836
1837 return nonargs;
1838
1839error:
1840 {
1841 const Ecore_Getopt_Desc *help;
1842 fputs(_("ERROR: invalid options found."), stderr);
1843
1844 help = _ecore_getopt_find_help(parser);
1845 if (!help)
1846 fputc('\n', stderr);
1847 else if (help->longname)
1848 fprintf(stderr, _(" See --%s.\n"), help->longname);
1849 else
1850 fprintf(stderr, _(" See -%c.\n"), help->shortname);
1851 }
1852
1853 return -1;
1854}
1855
1856/**
1857 * Utility to free list and nodes allocated by @a ECORE_GETOPT_ACTION_APPEND.
1858 *
1859 * @param list pointer to list to be freed.
1860 * @return always @c NULL, so you can easily make your list head @c NULL.
1861 */
1862EAPI Eina_List *
1863ecore_getopt_list_free(Eina_List *list)
1864{
1865 void *data;
1866
1867 EINA_LIST_FREE(list, data)
1868 free(data);
1869 return NULL;
1870}
1871
1872/**
1873 * Helper ecore_getopt callback to parse geometry (x:y:w:h).
1874 *
1875 * @param parser This parameter isn't in use.
1876 * @param desc This parameter isn't in use.
1877 * @param str Geometry value
1878 * @param data This parameter isn't in use.
1879 * @param storage must be a pointer to @c Eina_Rectangle and will be used to
1880 * store the four values passed in the given string.
1881 * @return @c EINA_TRUE on success, @c EINA_FALSE on incorrect geometry value.
1882 *
1883 * @c callback_data value is ignored, you can safely use @c NULL.
1884 */
1885EAPI Eina_Bool
1886ecore_getopt_callback_geometry_parse(const Ecore_Getopt *parser EINA_UNUSED,
1887 const Ecore_Getopt_Desc *desc EINA_UNUSED,
1888 const char *str,
1889 void *data EINA_UNUSED,
1890 Ecore_Getopt_Value *storage)
1891{
1892 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1893
1894 if (sscanf(str, "%d:%d:%d:%d", &v->x, &v->y, &v->w, &v->h) != 4)
1895 {
1896 fprintf(stderr, _("ERROR: incorrect geometry value '%s'\n"), str);
1897 return EINA_FALSE;
1898 }
1899
1900 return EINA_TRUE;
1901}
1902
1903/**
1904 * Helper ecore_getopt callback to parse geometry size (WxH).
1905 *
1906 * @param parser This parameter isn't in use.
1907 * @param desc This parameter isn't in use.
1908 * @param str size value
1909 * @param data This parameter isn't in use.
1910 * @param storage must be a pointer to @c Eina_Rectangle and will be used to
1911 * store the two values passed in the given string and @c 0 in the x and y
1912 * fields.
1913 * @return @c EINA_TRUE on success, @c EINA_FALSE on incorrect size value.
1914 *
1915 * @c callback_data value is ignored, you can safely use @c NULL.
1916 */
1917EAPI Eina_Bool
1918ecore_getopt_callback_size_parse(const Ecore_Getopt *parser EINA_UNUSED,
1919 const Ecore_Getopt_Desc *desc EINA_UNUSED,
1920 const char *str,
1921 void *data EINA_UNUSED,
1922 Ecore_Getopt_Value *storage)
1923{
1924 Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
1925
1926 if (sscanf(str, "%dx%d", &v->w, &v->h) != 2)
1927 {
1928 fprintf(stderr, _("ERROR: incorrect size value '%s'\n"), str);
1929 return EINA_FALSE;
1930 }
1931 v->x = 0;
1932 v->y = 0;
1933
1934 return EINA_TRUE;
1935}
1936