Fossil SCM
Initial work on unified "--" flag support, as requested in https://fossil-scm.org/forum/forumpost/64acc6b653. There's still lots to do here.
Commit
d8ebbd76cc9ae94b6f9ffb8ef6856b3afd5ee2b5a14063d923fd567206f08ad3
Parent
f6e635308c0c03f…
1 file changed
+63
-12
+63
-12
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -900,16 +900,28 @@ | ||
| 900 | 900 | g.argc = i; |
| 901 | 901 | } |
| 902 | 902 | |
| 903 | 903 | |
| 904 | 904 | /* |
| 905 | -** Look for a command-line option. If present, return a pointer. | |
| 906 | -** Return NULL if missing. | |
| 905 | +** Look for a command-line option. If present, remove it from the | |
| 906 | +** argument list and return a pointer to either the flag's name (if | |
| 907 | +** hasArg==0), sans leading - or --, or its value (if hasArg==1). | |
| 908 | +** Return NULL if the flag is not found. | |
| 909 | +** | |
| 910 | +** zLong is the "long" form of the flag and zShort is the | |
| 911 | +** short/abbreviated form (typically a single letter, but it may be | |
| 912 | +** longer). zLong must not be NULL, but zShort may be. | |
| 907 | 913 | ** |
| 908 | 914 | ** hasArg==0 means the option is a flag. It is either present or not. |
| 909 | -** hasArg==1 means the option has an argument. Return a pointer to the | |
| 910 | -** argument. | |
| 915 | +** hasArg==1 means the option has an argument, in which case a pointer | |
| 916 | +** to the argument's value is returned. For zLong, a flag value (if | |
| 917 | +** hasValue==1) may either be in the form (--flag=value) or (--flag | |
| 918 | +** value). For zShort, only the latter form is accepted. | |
| 919 | +** | |
| 920 | +** If a standalone argument of "--" is encountered in the argument | |
| 921 | +** list while searching for the given flag(s), this routine stops | |
| 922 | +** searching and NULL is returned. | |
| 911 | 923 | */ |
| 912 | 924 | const char *find_option(const char *zLong, const char *zShort, int hasArg){ |
| 913 | 925 | int i; |
| 914 | 926 | int nLong; |
| 915 | 927 | const char *zReturn = 0; |
| @@ -921,11 +933,11 @@ | ||
| 921 | 933 | z = g.argv[i]; |
| 922 | 934 | if( z[0]!='-' ) continue; |
| 923 | 935 | z++; |
| 924 | 936 | if( z[0]=='-' ){ |
| 925 | 937 | if( z[1]==0 ){ |
| 926 | - remove_from_argv(i, 1); | |
| 938 | + /* Stop processing at "--" */ | |
| 927 | 939 | break; |
| 928 | 940 | } |
| 929 | 941 | z++; |
| 930 | 942 | } |
| 931 | 943 | if( strncmp(z,zLong,nLong)==0 ){ |
| @@ -955,11 +967,17 @@ | ||
| 955 | 967 | int n = (int)strlen(zOption); |
| 956 | 968 | for(i=1; i<g.argc; i++){ |
| 957 | 969 | char *z = g.argv[i]; |
| 958 | 970 | if( z[0]!='-' ) continue; |
| 959 | 971 | z++; |
| 960 | - if( z[0]=='-' ) z++; | |
| 972 | + if( z[0]=='-' ){ | |
| 973 | + z++; | |
| 974 | + if( z[0]==0 ){ | |
| 975 | + /* Stop searching at "--" */ | |
| 976 | + break; | |
| 977 | + } | |
| 978 | + } | |
| 961 | 979 | if( strncmp(z,zOption,n)==0 && (z[n]==0 || z[n]=='=') ) return 1; |
| 962 | 980 | } |
| 963 | 981 | return 0; |
| 964 | 982 | } |
| 965 | 983 | |
| @@ -969,11 +987,14 @@ | ||
| 969 | 987 | ** |
| 970 | 988 | ** Return a malloc allocated array of pointers to the arguments. |
| 971 | 989 | ** |
| 972 | 990 | ** pnUsedArgs is used to store the number of matched arguments. |
| 973 | 991 | ** |
| 974 | -** Caller is responsible to free allocated memory. | |
| 992 | +** Caller is responsible for freeing allocated memory by passing the | |
| 993 | +** head of the array (not each entry) to fossil_free(). (The | |
| 994 | +** individual entries have the same lifetime as values returned from | |
| 995 | +** find_option().) | |
| 975 | 996 | */ |
| 976 | 997 | const char **find_repeatable_option( |
| 977 | 998 | const char *zLong, |
| 978 | 999 | const char *zShort, |
| 979 | 1000 | int *pnUsedArgs |
| @@ -1013,22 +1034,52 @@ | ||
| 1013 | 1034 | |
| 1014 | 1035 | /* |
| 1015 | 1036 | ** Verify that there are no unprocessed command-line options. If |
| 1016 | 1037 | ** Any remaining command-line argument begins with "-" print |
| 1017 | 1038 | ** an error message and quit. |
| 1039 | +** | |
| 1040 | +** If fAllowDoubleDash is true then if the flag "--" is found, it is | |
| 1041 | +** removed from the list and arguments after that flag are not | |
| 1042 | +** inspected by this function (they are assumed to be filenames, even | |
| 1043 | +** if they syntactically look like flags). If fAllowDoubleDash is | |
| 1044 | +** false then the "--" flag will trigger a fatal error exactly as if | |
| 1045 | +** an unprocessed flag were encountered. | |
| 1046 | +** | |
| 1047 | +** Sidebar: the question of whether fAllowDoubleDash should be true or | |
| 1048 | +** false would seem to boil down to: does the calling routine | |
| 1049 | +** expect/allow arbitrary file/page/branch/whatever name arguments | |
| 1050 | +** after its required arguments? | |
| 1051 | +** | |
| 1052 | +** Once the "--" support is completed, this function will be renamed | |
| 1053 | +** (back) to verify_all_options(). | |
| 1018 | 1054 | */ |
| 1019 | -void verify_all_options(void){ | |
| 1055 | +void verify_all_options_porting_crutch(int fAllowDoubleDash){ | |
| 1020 | 1056 | int i; |
| 1021 | 1057 | for(i=1; i<g.argc; i++){ |
| 1022 | - if( g.argv[i][0]=='-' && g.argv[i][1]!=0 ){ | |
| 1023 | - fossil_fatal( | |
| 1024 | - "unrecognized command-line option, or missing argument: %s", | |
| 1025 | - g.argv[i]); | |
| 1058 | + const char * arg = g.argv[i]; | |
| 1059 | + if( arg[0]=='-' ){ | |
| 1060 | + if( arg[1]=='-' && arg[2]==0 ){ | |
| 1061 | + if(fAllowDoubleDash){ | |
| 1062 | + /* Remove "--" from the list and assume any following | |
| 1063 | + ** arguments are file names. */ | |
| 1064 | + remove_from_argv(i, 1); | |
| 1065 | + break; | |
| 1066 | + }else{ | |
| 1067 | + fossil_fatal("The -- flag is not allowed here."); | |
| 1068 | + } | |
| 1069 | + }else if( arg[1]!=0 ){ | |
| 1070 | + fossil_fatal( | |
| 1071 | + "unrecognized command-line option, or missing argument: %s", | |
| 1072 | + arg); | |
| 1073 | + } | |
| 1026 | 1074 | } |
| 1027 | 1075 | } |
| 1028 | 1076 | } |
| 1029 | 1077 | |
| 1078 | +void verify_all_options(void){ | |
| 1079 | + verify_all_options_porting_crutch(0); | |
| 1080 | +} | |
| 1030 | 1081 | |
| 1031 | 1082 | /* |
| 1032 | 1083 | ** This function returns a human readable version string. |
| 1033 | 1084 | */ |
| 1034 | 1085 | const char *get_version(){ |
| 1035 | 1086 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -900,16 +900,28 @@ | |
| 900 | g.argc = i; |
| 901 | } |
| 902 | |
| 903 | |
| 904 | /* |
| 905 | ** Look for a command-line option. If present, return a pointer. |
| 906 | ** Return NULL if missing. |
| 907 | ** |
| 908 | ** hasArg==0 means the option is a flag. It is either present or not. |
| 909 | ** hasArg==1 means the option has an argument. Return a pointer to the |
| 910 | ** argument. |
| 911 | */ |
| 912 | const char *find_option(const char *zLong, const char *zShort, int hasArg){ |
| 913 | int i; |
| 914 | int nLong; |
| 915 | const char *zReturn = 0; |
| @@ -921,11 +933,11 @@ | |
| 921 | z = g.argv[i]; |
| 922 | if( z[0]!='-' ) continue; |
| 923 | z++; |
| 924 | if( z[0]=='-' ){ |
| 925 | if( z[1]==0 ){ |
| 926 | remove_from_argv(i, 1); |
| 927 | break; |
| 928 | } |
| 929 | z++; |
| 930 | } |
| 931 | if( strncmp(z,zLong,nLong)==0 ){ |
| @@ -955,11 +967,17 @@ | |
| 955 | int n = (int)strlen(zOption); |
| 956 | for(i=1; i<g.argc; i++){ |
| 957 | char *z = g.argv[i]; |
| 958 | if( z[0]!='-' ) continue; |
| 959 | z++; |
| 960 | if( z[0]=='-' ) z++; |
| 961 | if( strncmp(z,zOption,n)==0 && (z[n]==0 || z[n]=='=') ) return 1; |
| 962 | } |
| 963 | return 0; |
| 964 | } |
| 965 | |
| @@ -969,11 +987,14 @@ | |
| 969 | ** |
| 970 | ** Return a malloc allocated array of pointers to the arguments. |
| 971 | ** |
| 972 | ** pnUsedArgs is used to store the number of matched arguments. |
| 973 | ** |
| 974 | ** Caller is responsible to free allocated memory. |
| 975 | */ |
| 976 | const char **find_repeatable_option( |
| 977 | const char *zLong, |
| 978 | const char *zShort, |
| 979 | int *pnUsedArgs |
| @@ -1013,22 +1034,52 @@ | |
| 1013 | |
| 1014 | /* |
| 1015 | ** Verify that there are no unprocessed command-line options. If |
| 1016 | ** Any remaining command-line argument begins with "-" print |
| 1017 | ** an error message and quit. |
| 1018 | */ |
| 1019 | void verify_all_options(void){ |
| 1020 | int i; |
| 1021 | for(i=1; i<g.argc; i++){ |
| 1022 | if( g.argv[i][0]=='-' && g.argv[i][1]!=0 ){ |
| 1023 | fossil_fatal( |
| 1024 | "unrecognized command-line option, or missing argument: %s", |
| 1025 | g.argv[i]); |
| 1026 | } |
| 1027 | } |
| 1028 | } |
| 1029 | |
| 1030 | |
| 1031 | /* |
| 1032 | ** This function returns a human readable version string. |
| 1033 | */ |
| 1034 | const char *get_version(){ |
| 1035 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -900,16 +900,28 @@ | |
| 900 | g.argc = i; |
| 901 | } |
| 902 | |
| 903 | |
| 904 | /* |
| 905 | ** Look for a command-line option. If present, remove it from the |
| 906 | ** argument list and return a pointer to either the flag's name (if |
| 907 | ** hasArg==0), sans leading - or --, or its value (if hasArg==1). |
| 908 | ** Return NULL if the flag is not found. |
| 909 | ** |
| 910 | ** zLong is the "long" form of the flag and zShort is the |
| 911 | ** short/abbreviated form (typically a single letter, but it may be |
| 912 | ** longer). zLong must not be NULL, but zShort may be. |
| 913 | ** |
| 914 | ** hasArg==0 means the option is a flag. It is either present or not. |
| 915 | ** hasArg==1 means the option has an argument, in which case a pointer |
| 916 | ** to the argument's value is returned. For zLong, a flag value (if |
| 917 | ** hasValue==1) may either be in the form (--flag=value) or (--flag |
| 918 | ** value). For zShort, only the latter form is accepted. |
| 919 | ** |
| 920 | ** If a standalone argument of "--" is encountered in the argument |
| 921 | ** list while searching for the given flag(s), this routine stops |
| 922 | ** searching and NULL is returned. |
| 923 | */ |
| 924 | const char *find_option(const char *zLong, const char *zShort, int hasArg){ |
| 925 | int i; |
| 926 | int nLong; |
| 927 | const char *zReturn = 0; |
| @@ -921,11 +933,11 @@ | |
| 933 | z = g.argv[i]; |
| 934 | if( z[0]!='-' ) continue; |
| 935 | z++; |
| 936 | if( z[0]=='-' ){ |
| 937 | if( z[1]==0 ){ |
| 938 | /* Stop processing at "--" */ |
| 939 | break; |
| 940 | } |
| 941 | z++; |
| 942 | } |
| 943 | if( strncmp(z,zLong,nLong)==0 ){ |
| @@ -955,11 +967,17 @@ | |
| 967 | int n = (int)strlen(zOption); |
| 968 | for(i=1; i<g.argc; i++){ |
| 969 | char *z = g.argv[i]; |
| 970 | if( z[0]!='-' ) continue; |
| 971 | z++; |
| 972 | if( z[0]=='-' ){ |
| 973 | z++; |
| 974 | if( z[0]==0 ){ |
| 975 | /* Stop searching at "--" */ |
| 976 | break; |
| 977 | } |
| 978 | } |
| 979 | if( strncmp(z,zOption,n)==0 && (z[n]==0 || z[n]=='=') ) return 1; |
| 980 | } |
| 981 | return 0; |
| 982 | } |
| 983 | |
| @@ -969,11 +987,14 @@ | |
| 987 | ** |
| 988 | ** Return a malloc allocated array of pointers to the arguments. |
| 989 | ** |
| 990 | ** pnUsedArgs is used to store the number of matched arguments. |
| 991 | ** |
| 992 | ** Caller is responsible for freeing allocated memory by passing the |
| 993 | ** head of the array (not each entry) to fossil_free(). (The |
| 994 | ** individual entries have the same lifetime as values returned from |
| 995 | ** find_option().) |
| 996 | */ |
| 997 | const char **find_repeatable_option( |
| 998 | const char *zLong, |
| 999 | const char *zShort, |
| 1000 | int *pnUsedArgs |
| @@ -1013,22 +1034,52 @@ | |
| 1034 | |
| 1035 | /* |
| 1036 | ** Verify that there are no unprocessed command-line options. If |
| 1037 | ** Any remaining command-line argument begins with "-" print |
| 1038 | ** an error message and quit. |
| 1039 | ** |
| 1040 | ** If fAllowDoubleDash is true then if the flag "--" is found, it is |
| 1041 | ** removed from the list and arguments after that flag are not |
| 1042 | ** inspected by this function (they are assumed to be filenames, even |
| 1043 | ** if they syntactically look like flags). If fAllowDoubleDash is |
| 1044 | ** false then the "--" flag will trigger a fatal error exactly as if |
| 1045 | ** an unprocessed flag were encountered. |
| 1046 | ** |
| 1047 | ** Sidebar: the question of whether fAllowDoubleDash should be true or |
| 1048 | ** false would seem to boil down to: does the calling routine |
| 1049 | ** expect/allow arbitrary file/page/branch/whatever name arguments |
| 1050 | ** after its required arguments? |
| 1051 | ** |
| 1052 | ** Once the "--" support is completed, this function will be renamed |
| 1053 | ** (back) to verify_all_options(). |
| 1054 | */ |
| 1055 | void verify_all_options_porting_crutch(int fAllowDoubleDash){ |
| 1056 | int i; |
| 1057 | for(i=1; i<g.argc; i++){ |
| 1058 | const char * arg = g.argv[i]; |
| 1059 | if( arg[0]=='-' ){ |
| 1060 | if( arg[1]=='-' && arg[2]==0 ){ |
| 1061 | if(fAllowDoubleDash){ |
| 1062 | /* Remove "--" from the list and assume any following |
| 1063 | ** arguments are file names. */ |
| 1064 | remove_from_argv(i, 1); |
| 1065 | break; |
| 1066 | }else{ |
| 1067 | fossil_fatal("The -- flag is not allowed here."); |
| 1068 | } |
| 1069 | }else if( arg[1]!=0 ){ |
| 1070 | fossil_fatal( |
| 1071 | "unrecognized command-line option, or missing argument: %s", |
| 1072 | arg); |
| 1073 | } |
| 1074 | } |
| 1075 | } |
| 1076 | } |
| 1077 | |
| 1078 | void verify_all_options(void){ |
| 1079 | verify_all_options_porting_crutch(0); |
| 1080 | } |
| 1081 | |
| 1082 | /* |
| 1083 | ** This function returns a human readable version string. |
| 1084 | */ |
| 1085 | const char *get_version(){ |
| 1086 |