Improve diagnostics of errors in rc files.
Showing
1 changed file
with
109 additions
and
20 deletions
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | 1 | /* GNU Mailutils -- a suite of utilities for electronic mail |
2 | Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006 | 2 | Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007 |
3 | Free Software Foundation, Inc. | 3 | Free Software Foundation, Inc. |
4 | 4 | ||
5 | This library is free software; you can redistribute it and/or | 5 | This library is free software; you can redistribute it and/or |
... | @@ -45,6 +45,7 @@ | ... | @@ -45,6 +45,7 @@ |
45 | #include <mailutils/mailbox.h> | 45 | #include <mailutils/mailbox.h> |
46 | #include <mailutils/nls.h> | 46 | #include <mailutils/nls.h> |
47 | #include <mailutils/argcv.h> | 47 | #include <mailutils/argcv.h> |
48 | #include "mu_umaxtostr.h" | ||
48 | 49 | ||
49 | #define ARG_LOG_FACILITY 1 | 50 | #define ARG_LOG_FACILITY 1 |
50 | #define ARG_LOCK_FLAGS 2 | 51 | #define ARG_LOCK_FLAGS 2 |
... | @@ -55,6 +56,20 @@ | ... | @@ -55,6 +56,20 @@ |
55 | #define ARG_SHOW_OPTIONS 7 | 56 | #define ARG_SHOW_OPTIONS 7 |
56 | #define ARG_LICENSE 8 | 57 | #define ARG_LICENSE 8 |
57 | #define ARG_MAILBOX_TYPE 9 | 58 | #define ARG_MAILBOX_TYPE 9 |
59 | #define ARG_FILE_OPTION 10 | ||
60 | #define ARG_LINE_OPTION 11 | ||
61 | |||
62 | static struct argp_option mu_locus_argp_options[] = | ||
63 | { | ||
64 | { "FILE", ARG_FILE_OPTION, "STRING", OPTION_HIDDEN, | ||
65 | "File name where the following options appeared " | ||
66 | "(empty string for command line)", 0 }, | ||
67 | { "LINE", ARG_LINE_OPTION, "NUMBER", OPTION_HIDDEN, | ||
68 | "Line number where the following options appeared", 0 }, | ||
69 | { NULL, 0, NULL, 0, NULL, 0 } | ||
70 | }; | ||
71 | |||
72 | |||
58 | 73 | ||
59 | static struct argp_option mu_common_argp_options[] = | 74 | static struct argp_option mu_common_argp_options[] = |
60 | { | 75 | { |
... | @@ -130,16 +145,30 @@ static struct argp_option mu_daemon_argp_option[] = { | ... | @@ -130,16 +145,30 @@ static struct argp_option mu_daemon_argp_option[] = { |
130 | { NULL, 0, NULL, 0, NULL, 0 } | 145 | { NULL, 0, NULL, 0, NULL, 0 } |
131 | }; | 146 | }; |
132 | 147 | ||
148 | static error_t mu_locus_argp_parser (int key, char *arg, | ||
149 | struct argp_state *state); | ||
133 | static error_t mu_common_argp_parser (int key, char *arg, | 150 | static error_t mu_common_argp_parser (int key, char *arg, |
134 | struct argp_state *state); | 151 | struct argp_state *state); |
135 | static error_t mu_daemon_argp_parser (int key, char *arg, | 152 | static error_t mu_daemon_argp_parser (int key, char *arg, |
136 | struct argp_state *state); | 153 | struct argp_state *state); |
137 | 154 | ||
155 | struct argp mu_locus_argp = { | ||
156 | mu_locus_argp_options, | ||
157 | mu_locus_argp_parser | ||
158 | }; | ||
159 | |||
138 | struct argp mu_common_argp = { | 160 | struct argp mu_common_argp = { |
139 | mu_common_argp_options, | 161 | mu_common_argp_options, |
140 | mu_common_argp_parser, | 162 | mu_common_argp_parser, |
141 | }; | 163 | }; |
142 | 164 | ||
165 | struct argp_child mu_locus_argp_child = { | ||
166 | &mu_locus_argp, | ||
167 | 0, | ||
168 | NULL, | ||
169 | 0, | ||
170 | }; | ||
171 | |||
143 | struct argp_child mu_common_argp_child = { | 172 | struct argp_child mu_common_argp_child = { |
144 | &mu_common_argp, | 173 | &mu_common_argp, |
145 | 0, | 174 | 0, |
... | @@ -382,6 +411,49 @@ mu_check_option (char *name) | ... | @@ -382,6 +411,49 @@ mu_check_option (char *name) |
382 | } | 411 | } |
383 | 412 | ||
384 | static error_t | 413 | static error_t |
414 | mu_locus_argp_parser (int key, char *arg, struct argp_state *state) | ||
415 | { | ||
416 | static char *file_name = NULL; | ||
417 | static char *line_num; | ||
418 | |||
419 | switch (key) | ||
420 | { | ||
421 | case ARGP_KEY_INIT: | ||
422 | state->flags |= ARGP_NO_ERRS; | ||
423 | break; | ||
424 | |||
425 | case ARG_FILE_OPTION: | ||
426 | free (file_name); | ||
427 | file_name = arg[0] ? arg : NULL; | ||
428 | /*FIXME: This doesn't work | ||
429 | if (!file_name) | ||
430 | state->flags &= ~(ARGP_NO_ERRS|ARGP_NO_EXIT);*/ | ||
431 | break; | ||
432 | |||
433 | case ARG_LINE_OPTION: | ||
434 | free (line_num); | ||
435 | line_num = arg; | ||
436 | break; | ||
437 | |||
438 | case ARGP_KEY_ERROR: | ||
439 | state->flags &= ~(ARGP_NO_ERRS|ARGP_NO_EXIT); | ||
440 | if (file_name) | ||
441 | argp_error(state, | ||
442 | "%s:%s: unknown option `%s'", file_name, line_num, | ||
443 | state->argv[state->next-1]); | ||
444 | else | ||
445 | argp_error(state, | ||
446 | "unknown option `%s'", | ||
447 | state->argv[state->next-1]); | ||
448 | /* FALL THROUGH */ | ||
449 | default: | ||
450 | return ARGP_ERR_UNKNOWN; | ||
451 | } | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | |||
456 | static error_t | ||
385 | mu_common_argp_parser (int key, char *arg, struct argp_state *state) | 457 | mu_common_argp_parser (int key, char *arg, struct argp_state *state) |
386 | { | 458 | { |
387 | int err = 0; | 459 | int err = 0; |
... | @@ -591,7 +663,16 @@ read_rc (const char *progname, const char *name, const char *capa[], | ... | @@ -591,7 +663,16 @@ read_rc (const char *progname, const char *name, const char *capa[], |
591 | int x_argc = *argc; | 663 | int x_argc = *argc; |
592 | char **x_argv = *argv; | 664 | char **x_argv = *argv; |
593 | char* rcfile = mu_tilde_expansion (name, "/", NULL); | 665 | char* rcfile = mu_tilde_expansion (name, "/", NULL); |
594 | 666 | size_t line = 0; | |
667 | |||
668 | #define XPAND(n) \ | ||
669 | x_argv = realloc (x_argv, (x_argc + n) * sizeof (x_argv[0])); \ | ||
670 | if (!x_argv) \ | ||
671 | { \ | ||
672 | fprintf (stderr, _("%s: not enough memory\n"), progname); \ | ||
673 | exit (1); \ | ||
674 | } | ||
675 | |||
595 | if (!rcfile) | 676 | if (!rcfile) |
596 | return; | 677 | return; |
597 | 678 | ||
... | @@ -601,12 +682,17 @@ read_rc (const char *progname, const char *name, const char *capa[], | ... | @@ -601,12 +682,17 @@ read_rc (const char *progname, const char *name, const char *capa[], |
601 | free(rcfile); | 682 | free(rcfile); |
602 | return; | 683 | return; |
603 | } | 684 | } |
604 | 685 | ||
686 | XPAND (2); | ||
687 | x_argv[x_argc++] = "--FILE"; | ||
688 | x_argv[x_argc++] = strdup (rcfile); | ||
689 | |||
605 | while (getline (&buf, &n, fp) > 0) | 690 | while (getline (&buf, &n, fp) > 0) |
606 | { | 691 | { |
607 | char *kwp, *p; | 692 | char *kwp, *p; |
608 | int len; | 693 | int len; |
609 | 694 | ||
695 | line++; | ||
610 | for (kwp = buf; *kwp && isspace (*kwp); kwp++) | 696 | for (kwp = buf; *kwp && isspace (*kwp); kwp++) |
611 | ; | 697 | ; |
612 | 698 | ||
... | @@ -662,7 +748,7 @@ read_rc (const char *progname, const char *name, const char *capa[], | ... | @@ -662,7 +748,7 @@ read_rc (const char *progname, const char *name, const char *capa[], |
662 | { | 748 | { |
663 | int i, n_argc = 0; | 749 | int i, n_argc = 0; |
664 | char **n_argv; | 750 | char **n_argv; |
665 | 751 | ||
666 | if (mu_argcv_get (p, "", NULL, &n_argc, &n_argv)) | 752 | if (mu_argcv_get (p, "", NULL, &n_argc, &n_argv)) |
667 | { | 753 | { |
668 | mu_argcv_free (n_argc, n_argv); | 754 | mu_argcv_free (n_argc, n_argv); |
... | @@ -671,14 +757,10 @@ read_rc (const char *progname, const char *name, const char *capa[], | ... | @@ -671,14 +757,10 @@ read_rc (const char *progname, const char *name, const char *capa[], |
671 | linebuf = NULL; | 757 | linebuf = NULL; |
672 | continue; | 758 | continue; |
673 | } | 759 | } |
674 | x_argv = realloc (x_argv, | 760 | |
675 | (x_argc + n_argc) * sizeof (x_argv[0])); | 761 | XPAND (n_argc + 2); |
676 | if (!x_argv) | 762 | x_argv[x_argc++] = "--LINE"; |
677 | { | 763 | x_argv[x_argc++] = strdup (mu_umaxtostr (0, line)); |
678 | fprintf (stderr, _("%s: not enough memory\n"), progname); | ||
679 | exit (1); | ||
680 | } | ||
681 | |||
682 | for (i = 0; i < n_argc; i++) | 764 | for (i = 0; i < n_argc; i++) |
683 | x_argv[x_argc++] = mu_tilde_expansion (n_argv[i], "/", NULL); | 765 | x_argv[x_argc++] = mu_tilde_expansion (n_argv[i], "/", NULL); |
684 | 766 | ||
... | @@ -689,8 +771,12 @@ read_rc (const char *progname, const char *name, const char *capa[], | ... | @@ -689,8 +771,12 @@ read_rc (const char *progname, const char *name, const char *capa[], |
689 | linebuf = NULL; | 771 | linebuf = NULL; |
690 | } | 772 | } |
691 | fclose (fp); | 773 | fclose (fp); |
692 | free(rcfile); | 774 | free (rcfile); |
693 | 775 | ||
776 | XPAND (2); | ||
777 | x_argv[x_argc++] = "--FILE"; | ||
778 | x_argv[x_argc++] = ""; | ||
779 | |||
694 | *argc = x_argc; | 780 | *argc = x_argc; |
695 | *argv = x_argv; | 781 | *argv = x_argv; |
696 | } | 782 | } |
... | @@ -817,6 +903,7 @@ struct argp_capa { | ... | @@ -817,6 +903,7 @@ struct argp_capa { |
817 | char *capability; | 903 | char *capability; |
818 | struct argp_child *child; | 904 | struct argp_child *child; |
819 | } mu_argp_capa[MU_MAX_CAPA] = { | 905 | } mu_argp_capa[MU_MAX_CAPA] = { |
906 | {"locus", &mu_locus_argp_child}, | ||
820 | {"common", &mu_common_argp_child}, | 907 | {"common", &mu_common_argp_child}, |
821 | {"license", &mu_license_argp_child}, | 908 | {"license", &mu_license_argp_child}, |
822 | {"mailbox", &mu_mailbox_argp_child}, | 909 | {"mailbox", &mu_mailbox_argp_child}, |
... | @@ -862,9 +949,10 @@ mu_build_argp (const struct argp *template, const char *capa[]) | ... | @@ -862,9 +949,10 @@ mu_build_argp (const struct argp *template, const char *capa[]) |
862 | const struct argp_option *opt; | 949 | const struct argp_option *opt; |
863 | struct argp *argp; | 950 | struct argp *argp; |
864 | int group = 0; | 951 | int group = 0; |
865 | 952 | const char *cs; | |
953 | |||
866 | /* Count the capabilities. */ | 954 | /* Count the capabilities. */ |
867 | for (n = 0; capa && capa[n]; n++) | 955 | for (n = 1; capa && capa[n]; n++) |
868 | ; | 956 | ; |
869 | if (template->children) | 957 | if (template->children) |
870 | for (; template->children[n].argp; n++) | 958 | for (; template->children[n].argp; n++) |
... | @@ -891,14 +979,15 @@ mu_build_argp (const struct argp *template, const char *capa[]) | ... | @@ -891,14 +979,15 @@ mu_build_argp (const struct argp *template, const char *capa[]) |
891 | 979 | ||
892 | group++; | 980 | group++; |
893 | 981 | ||
894 | /* Append any capabilities to the children or options, as appropriate. */ | 982 | /* Append any capabilities to the children or options, as appropriate. |
895 | for (n = 0; capa && capa[n]; n++) | 983 | "locus" is always added */ |
984 | for (cs = "locus", n = 0; cs; cs = capa[n++]) | ||
896 | { | 985 | { |
897 | struct argp_child *child = find_argp_child (capa[n]); | 986 | struct argp_child *child = find_argp_child (cs); |
898 | if (!child) | 987 | if (!child) |
899 | { | 988 | { |
900 | mu_error (_("INTERNAL ERROR: requested unknown argp capability %s (please report)"), | 989 | mu_error (_("INTERNAL ERROR: requested unknown argp capability %s (please report)"), |
901 | capa[n]); | 990 | cs); |
902 | abort (); | 991 | abort (); |
903 | } | 992 | } |
904 | ap[nchild] = *child; | 993 | ap[nchild] = *child; | ... | ... |
-
Please register or sign in to post a comment