Commit e3932d9c e3932d9cceb767fbd4d457ba7e71a0fbd4c318e5 by Sergey Poznyakoff

Improve diagnostics of errors in rc files.

1 parent e106e7f9
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;
......