diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-03-15 10:16:42 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-03-15 11:14:58 +0100 |
commit | 164eed8f5171824cf27b318afeab12f8c6ba9262 (patch) | |
tree | c84580c2569579cd554bf2f1426010eadaef0f90 /src/util | |
parent | 30eb0faa8d4894659cc90c76cc634148df86eab9 (diff) | |
download | gnunet-164eed8f5171824cf27b318afeab12f8c6ba9262.tar.gz gnunet-164eed8f5171824cf27b318afeab12f8c6ba9262.zip |
fix test case, implement base32 argument parser logic
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/getopt.c | 56 | ||||
-rw-r--r-- | src/util/getopt_helpers.c | 105 | ||||
-rw-r--r-- | src/util/test_getopt.c | 30 |
3 files changed, 161 insertions, 30 deletions
diff --git a/src/util/getopt.c b/src/util/getopt.c index ff62dba9b..85f67500c 100644 --- a/src/util/getopt.c +++ b/src/util/getopt.c | |||
@@ -26,7 +26,7 @@ USA. | |||
26 | 26 | ||
27 | 27 | ||
28 | This code was heavily modified for GNUnet. | 28 | This code was heavily modified for GNUnet. |
29 | Copyright Copyright (C) 2006 Christian Grothoff | 29 | Copyright Copyright (C) 2006, 2017 Christian Grothoff |
30 | */ | 30 | */ |
31 | 31 | ||
32 | /** | 32 | /** |
@@ -845,9 +845,13 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
845 | } | 845 | } |
846 | } | 846 | } |
847 | 847 | ||
848 | |||
848 | static int | 849 | static int |
849 | GNgetopt_long (int argc, char *const *argv, const char *options, | 850 | GNgetopt_long (int argc, |
850 | const struct GNoption *long_options, int *opt_index) | 851 | char *const *argv, |
852 | const char *options, | ||
853 | const struct GNoption *long_options, | ||
854 | int *opt_index) | ||
851 | { | 855 | { |
852 | return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0); | 856 | return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0); |
853 | } | 857 | } |
@@ -867,12 +871,12 @@ GNgetopt_long (int argc, char *const *argv, const char *options, | |||
867 | int | 871 | int |
868 | GNUNET_GETOPT_run (const char *binaryOptions, | 872 | GNUNET_GETOPT_run (const char *binaryOptions, |
869 | const struct GNUNET_GETOPT_CommandLineOption *allOptions, | 873 | const struct GNUNET_GETOPT_CommandLineOption *allOptions, |
870 | unsigned int argc, char *const *argv) | 874 | unsigned int argc, |
875 | char *const *argv) | ||
871 | { | 876 | { |
872 | struct GNoption *long_options; | 877 | struct GNoption *long_options; |
873 | struct GNUNET_GETOPT_CommandLineProcessorContext clpc; | 878 | struct GNUNET_GETOPT_CommandLineProcessorContext clpc; |
874 | int count; | 879 | int count; |
875 | int i; | ||
876 | char *shorts; | 880 | char *shorts; |
877 | int spos; | 881 | int spos; |
878 | int cont; | 882 | int cont; |
@@ -885,13 +889,13 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
885 | clpc.allOptions = allOptions; | 889 | clpc.allOptions = allOptions; |
886 | clpc.argv = argv; | 890 | clpc.argv = argv; |
887 | clpc.argc = argc; | 891 | clpc.argc = argc; |
888 | count = 0; | 892 | for (count = 0; NULL != allOptions[count].name; count++) ; |
889 | while (allOptions[count].name != NULL) | 893 | |
890 | count++; | 894 | long_options = GNUNET_new_array (count + 1, |
891 | long_options = GNUNET_malloc (sizeof (struct GNoption) * (count + 1)); | 895 | struct GNoption); |
892 | shorts = GNUNET_malloc (count * 2 + 1); | 896 | shorts = GNUNET_malloc (count * 2 + 1); |
893 | spos = 0; | 897 | spos = 0; |
894 | for (i = 0; i < count; i++) | 898 | for (unsigned i = 0; i < count; i++) |
895 | { | 899 | { |
896 | long_options[i].name = allOptions[i].name; | 900 | long_options[i].name = allOptions[i].name; |
897 | long_options[i].has_arg = allOptions[i].require_argument; | 901 | long_options[i].has_arg = allOptions[i].require_argument; |
@@ -907,13 +911,17 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
907 | long_options[count].val = '\0'; | 911 | long_options[count].val = '\0'; |
908 | shorts[spos] = '\0'; | 912 | shorts[spos] = '\0'; |
909 | cont = GNUNET_OK; | 913 | cont = GNUNET_OK; |
914 | |||
910 | /* main getopt loop */ | 915 | /* main getopt loop */ |
911 | while (cont == GNUNET_OK) | 916 | while (GNUNET_OK == cont) |
912 | { | 917 | { |
913 | int option_index = 0; | 918 | int option_index = 0; |
919 | unsigned int i; | ||
914 | 920 | ||
915 | c = GNgetopt_long (argc, argv, shorts, long_options, &option_index); | 921 | c = GNgetopt_long (argc, argv, |
916 | 922 | shorts, | |
923 | long_options, | ||
924 | &option_index); | ||
917 | if (c == GNUNET_SYSERR) | 925 | if (c == GNUNET_SYSERR) |
918 | break; /* No more flags to process */ | 926 | break; /* No more flags to process */ |
919 | 927 | ||
@@ -922,25 +930,31 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
922 | clpc.currentArgument = GNoptind - 1; | 930 | clpc.currentArgument = GNoptind - 1; |
923 | if ((char) c == allOptions[i].shortName) | 931 | if ((char) c == allOptions[i].shortName) |
924 | { | 932 | { |
925 | cont = | 933 | cont = allOptions[i].processor (&clpc, |
926 | allOptions[i].processor (&clpc, allOptions[i].scls, | 934 | allOptions[i].scls, |
927 | allOptions[i].name, GNoptarg); | 935 | allOptions[i].name, |
936 | GNoptarg); | ||
928 | break; | 937 | break; |
929 | } | 938 | } |
930 | } | 939 | } |
931 | if (i == count) | 940 | if (i == count) |
932 | { | 941 | { |
933 | FPRINTF (stderr, _("Use %s to get a list of options.\n"), "--help"); | 942 | FPRINTF (stderr, |
943 | _("Use %s to get a list of options.\n"), | ||
944 | "--help"); | ||
934 | cont = GNUNET_SYSERR; | 945 | cont = GNUNET_SYSERR; |
935 | } | 946 | } |
936 | } | 947 | } |
937 | |||
938 | GNUNET_free (shorts); | 948 | GNUNET_free (shorts); |
939 | GNUNET_free (long_options); | 949 | GNUNET_free (long_options); |
940 | if (cont != GNUNET_OK) | 950 | |
941 | { | 951 | /* call cleaners, if available */ |
952 | for (count = 0; NULL != allOptions[count].name; count++) | ||
953 | if (NULL != allOptions[count].cleaner) | ||
954 | allOptions[count].cleaner (allOptions[count].scls); | ||
955 | |||
956 | if (GNUNET_OK != cont) | ||
942 | return cont; | 957 | return cont; |
943 | } | ||
944 | return GNoptind; | 958 | return GNoptind; |
945 | } | 959 | } |
946 | 960 | ||
diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c index 234f5371f..9f6f4c764 100644 --- a/src/util/getopt_helpers.c +++ b/src/util/getopt_helpers.c | |||
@@ -266,7 +266,7 @@ GNUNET_GETOPT_OPTION_INCREMENT_VALUE (char shortName, | |||
266 | * @param[out] level set to the verbosity level | 266 | * @param[out] level set to the verbosity level |
267 | */ | 267 | */ |
268 | struct GNUNET_GETOPT_CommandLineOption | 268 | struct GNUNET_GETOPT_CommandLineOption |
269 | GNUNET_GETOPT_OPTION_VERBOSE (int *level) | 269 | GNUNET_GETOPT_OPTION_VERBOSE (unsigned int *level) |
270 | { | 270 | { |
271 | struct GNUNET_GETOPT_CommandLineOption clo = { | 271 | struct GNUNET_GETOPT_CommandLineOption clo = { |
272 | .shortName = 'V', | 272 | .shortName = 'V', |
@@ -710,4 +710,107 @@ GNUNET_GETOPT_OPTION_SET_UINT (char shortName, | |||
710 | } | 710 | } |
711 | 711 | ||
712 | 712 | ||
713 | /** | ||
714 | * Closure for #set_base32(). | ||
715 | */ | ||
716 | struct Base32Context | ||
717 | { | ||
718 | /** | ||
719 | * Value to initialize (already allocated) | ||
720 | */ | ||
721 | void *val; | ||
722 | |||
723 | /** | ||
724 | * Number of bytes expected for @e val. | ||
725 | */ | ||
726 | size_t val_size; | ||
727 | }; | ||
728 | |||
729 | |||
730 | /** | ||
731 | * Set an option of type 'unsigned int' from the command line. | ||
732 | * A pointer to this function should be passed as part of the | ||
733 | * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options | ||
734 | * of this type. It should be followed by a pointer to a value of | ||
735 | * type 'unsigned int'. | ||
736 | * | ||
737 | * @param ctx command line processing context | ||
738 | * @param scls additional closure (will point to the 'unsigned int') | ||
739 | * @param option name of the option | ||
740 | * @param value actual value of the option as a string. | ||
741 | * @return #GNUNET_OK if parsing the value worked | ||
742 | */ | ||
743 | static int | ||
744 | set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | ||
745 | void *scls, | ||
746 | const char *option, | ||
747 | const char *value) | ||
748 | { | ||
749 | struct Base32Context *bc = scls; | ||
750 | |||
751 | if (GNUNET_OK != | ||
752 | GNUNET_STRINGS_string_to_data (value, | ||
753 | strlen (value), | ||
754 | bc->val, | ||
755 | bc->val_size)) | ||
756 | { | ||
757 | fprintf (stderr, | ||
758 | _("Argument `%s' malformed. Expected base32 (Crockford) encoded value.\n"), | ||
759 | option); | ||
760 | return GNUNET_SYSERR; | ||
761 | } | ||
762 | return GNUNET_OK; | ||
763 | } | ||
764 | |||
765 | |||
766 | /** | ||
767 | * Helper function to clean up after | ||
768 | * #GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE. | ||
769 | * | ||
770 | * @param cls value to GNUNET_free() | ||
771 | */ | ||
772 | static void | ||
773 | free_bc (void *cls) | ||
774 | { | ||
775 | GNUNET_free (cls); | ||
776 | } | ||
777 | |||
778 | |||
779 | /** | ||
780 | * Allow user to specify a binary value using Crockford | ||
781 | * Base32 encoding. | ||
782 | * | ||
783 | * @param shortName short name of the option | ||
784 | * @param name long name of the option | ||
785 | * @param argumentHelp help text for the option argument | ||
786 | * @param description long help text for the option | ||
787 | * @param[out] val binary value decoded from Crockford Base32-encoded argument | ||
788 | * @param val_size size of @a val in bytes | ||
789 | */ | ||
790 | struct GNUNET_GETOPT_CommandLineOption | ||
791 | GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE (char shortName, | ||
792 | const char *name, | ||
793 | const char *argumentHelp, | ||
794 | const char *description, | ||
795 | void *val, | ||
796 | size_t val_size) | ||
797 | { | ||
798 | struct Base32Context *bc = GNUNET_new (struct Base32Context); | ||
799 | struct GNUNET_GETOPT_CommandLineOption clo = { | ||
800 | .shortName = shortName, | ||
801 | .name = name, | ||
802 | .argumentHelp = argumentHelp, | ||
803 | .description = description, | ||
804 | .require_argument = 1, | ||
805 | .processor = &set_base32, | ||
806 | .cleaner = &free_bc, | ||
807 | .scls = (void *) bc | ||
808 | }; | ||
809 | |||
810 | bc->val = val; | ||
811 | bc->val_size = val_size; | ||
812 | return clo; | ||
813 | } | ||
814 | |||
815 | |||
713 | /* end of getopt_helpers.c */ | 816 | /* end of getopt_helpers.c */ |
diff --git a/src/util/test_getopt.c b/src/util/test_getopt.c index 8e578640d..faa6a07a1 100644 --- a/src/util/test_getopt.c +++ b/src/util/test_getopt.c | |||
@@ -170,21 +170,35 @@ testFlagNum () | |||
170 | unsigned long long lnum = 0; | 170 | unsigned long long lnum = 0; |
171 | 171 | ||
172 | const struct GNUNET_GETOPT_CommandLineOption logoptionlist[] = { | 172 | const struct GNUNET_GETOPT_CommandLineOption logoptionlist[] = { |
173 | {'f', "--flag", NULL, "helptext", 0, &GNUNET_GETOPT_set_one, | 173 | GNUNET_GETOPT_OPTION_SET_ONE ('f', |
174 | (void *) &flag}, | 174 | "--flag", |
175 | {'n', "--num", "ARG", "helptext", 1, &GNUNET_GETOPT_set_uint, | 175 | "helptext", |
176 | (void *) &num}, | 176 | &flag), |
177 | {'N', "--lnum", "ARG", "helptext", 1, &GNUNET_GETOPT_set_ulong, | 177 | GNUNET_GETOPT_OPTION_SET_UINT ('n', |
178 | (void *) &lnum}, | 178 | "--num", |
179 | "ARG", | ||
180 | "helptext", | ||
181 | &num), | ||
182 | GNUNET_GETOPT_OPTION_SET_ULONG ('N', | ||
183 | "--lnum", | ||
184 | "ARG", | ||
185 | "helptext", | ||
186 | &lnum), | ||
179 | GNUNET_GETOPT_OPTION_END | 187 | GNUNET_GETOPT_OPTION_END |
180 | }; | 188 | }; |
181 | 189 | ||
182 | if (6 != GNUNET_GETOPT_run ("test_getopt", logoptionlist, 6, myargv)) | 190 | if (6 != |
191 | GNUNET_GETOPT_run ("test_getopt", | ||
192 | logoptionlist, | ||
193 | 6, | ||
194 | myargv)) | ||
183 | { | 195 | { |
184 | GNUNET_break (0); | 196 | GNUNET_break (0); |
185 | return 1; | 197 | return 1; |
186 | } | 198 | } |
187 | if ((1 != flag) || (42 != num) || (42 != lnum)) | 199 | if ( (1 != flag) || |
200 | (42 != num) || | ||
201 | (42 != lnum)) | ||
188 | { | 202 | { |
189 | GNUNET_break (0); | 203 | GNUNET_break (0); |
190 | return 1; | 204 | return 1; |