Fossil SCM
Merged in double-dash-flag2 branch, which adds conventional -- handling to the vast majority of commands (the exception being those few which don't call verify_all_arguments()).
Commit
5cca46469f24d7c862f04cff94c9ede557d26cf5e9396ded0d6eca462e4b0676
Parent
a92d5a514d7ffd5…
2 files changed
+53
-12
+1
-1
+53
-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,12 @@ | ||
| 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 "--" without consuming it. | |
| 939 | + verify_all_options() will consume this flag. */ | |
| 927 | 940 | break; |
| 928 | 941 | } |
| 929 | 942 | z++; |
| 930 | 943 | } |
| 931 | 944 | if( strncmp(z,zLong,nLong)==0 ){ |
| @@ -955,11 +968,17 @@ | ||
| 955 | 968 | int n = (int)strlen(zOption); |
| 956 | 969 | for(i=1; i<g.argc; i++){ |
| 957 | 970 | char *z = g.argv[i]; |
| 958 | 971 | if( z[0]!='-' ) continue; |
| 959 | 972 | z++; |
| 960 | - if( z[0]=='-' ) z++; | |
| 973 | + if( z[0]=='-' ){ | |
| 974 | + if( z[1]==0 ){ | |
| 975 | + /* Stop processing at "--" */ | |
| 976 | + break; | |
| 977 | + } | |
| 978 | + z++; | |
| 979 | + } | |
| 961 | 980 | if( strncmp(z,zOption,n)==0 && (z[n]==0 || z[n]=='=') ) return 1; |
| 962 | 981 | } |
| 963 | 982 | return 0; |
| 964 | 983 | } |
| 965 | 984 | |
| @@ -969,11 +988,14 @@ | ||
| 969 | 988 | ** |
| 970 | 989 | ** Return a malloc allocated array of pointers to the arguments. |
| 971 | 990 | ** |
| 972 | 991 | ** pnUsedArgs is used to store the number of matched arguments. |
| 973 | 992 | ** |
| 974 | -** Caller is responsible to free allocated memory. | |
| 993 | +** Caller is responsible for freeing allocated memory by passing the | |
| 994 | +** head of the array (not each entry) to fossil_free(). (The | |
| 995 | +** individual entries have the same lifetime as values returned from | |
| 996 | +** find_option().) | |
| 975 | 997 | */ |
| 976 | 998 | const char **find_repeatable_option( |
| 977 | 999 | const char *zLong, |
| 978 | 1000 | const char *zShort, |
| 979 | 1001 | int *pnUsedArgs |
| @@ -1013,22 +1035,41 @@ | ||
| 1013 | 1035 | |
| 1014 | 1036 | /* |
| 1015 | 1037 | ** Verify that there are no unprocessed command-line options. If |
| 1016 | 1038 | ** Any remaining command-line argument begins with "-" print |
| 1017 | 1039 | ** an error message and quit. |
| 1040 | +** | |
| 1041 | +** Exception: if "--" is encountered, it is consumed from the argument | |
| 1042 | +** list and this function immediately returns. The effect is to treat | |
| 1043 | +** all arguments after "--" as non-flags (conventionally used to | |
| 1044 | +** enable passing-in of filenames which start with a dash). | |
| 1045 | +** | |
| 1046 | +** This function must normally only be called one time per app | |
| 1047 | +** invokation. The exception is commands which process their | |
| 1048 | +** arguments, call this to confirm that there are no extraneous flags, | |
| 1049 | +** then modify the arguments list for forwarding to another | |
| 1050 | +** (sub)command (which itself will call this to confirm its own | |
| 1051 | +** arguments). | |
| 1018 | 1052 | */ |
| 1019 | 1053 | void verify_all_options(void){ |
| 1020 | 1054 | int i; |
| 1021 | 1055 | 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]); | |
| 1056 | + const char * arg = g.argv[i]; | |
| 1057 | + if( arg[0]=='-' ){ | |
| 1058 | + if( arg[1]=='-' && arg[2]==0 ){ | |
| 1059 | + /* Remove "--" from the list and treat all following | |
| 1060 | + ** arguments as non-flags. */ | |
| 1061 | + remove_from_argv(i, 1); | |
| 1062 | + break; | |
| 1063 | + }else if( arg[1]!=0 ){ | |
| 1064 | + fossil_fatal( | |
| 1065 | + "unrecognized command-line option or missing argument: %s", | |
| 1066 | + arg); | |
| 1067 | + } | |
| 1026 | 1068 | } |
| 1027 | 1069 | } |
| 1028 | 1070 | } |
| 1029 | - | |
| 1030 | 1071 | |
| 1031 | 1072 | /* |
| 1032 | 1073 | ** This function returns a human readable version string. |
| 1033 | 1074 | */ |
| 1034 | 1075 | const char *get_version(){ |
| 1035 | 1076 |
| --- 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,12 @@ | |
| 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 +968,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 +988,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 +1035,41 @@ | |
| 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,12 @@ | |
| 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 "--" without consuming it. |
| 939 | verify_all_options() will consume this flag. */ |
| 940 | break; |
| 941 | } |
| 942 | z++; |
| 943 | } |
| 944 | if( strncmp(z,zLong,nLong)==0 ){ |
| @@ -955,11 +968,17 @@ | |
| 968 | int n = (int)strlen(zOption); |
| 969 | for(i=1; i<g.argc; i++){ |
| 970 | char *z = g.argv[i]; |
| 971 | if( z[0]!='-' ) continue; |
| 972 | z++; |
| 973 | if( z[0]=='-' ){ |
| 974 | if( z[1]==0 ){ |
| 975 | /* Stop processing at "--" */ |
| 976 | break; |
| 977 | } |
| 978 | z++; |
| 979 | } |
| 980 | if( strncmp(z,zOption,n)==0 && (z[n]==0 || z[n]=='=') ) return 1; |
| 981 | } |
| 982 | return 0; |
| 983 | } |
| 984 | |
| @@ -969,11 +988,14 @@ | |
| 988 | ** |
| 989 | ** Return a malloc allocated array of pointers to the arguments. |
| 990 | ** |
| 991 | ** pnUsedArgs is used to store the number of matched arguments. |
| 992 | ** |
| 993 | ** Caller is responsible for freeing allocated memory by passing the |
| 994 | ** head of the array (not each entry) to fossil_free(). (The |
| 995 | ** individual entries have the same lifetime as values returned from |
| 996 | ** find_option().) |
| 997 | */ |
| 998 | const char **find_repeatable_option( |
| 999 | const char *zLong, |
| 1000 | const char *zShort, |
| 1001 | int *pnUsedArgs |
| @@ -1013,22 +1035,41 @@ | |
| 1035 | |
| 1036 | /* |
| 1037 | ** Verify that there are no unprocessed command-line options. If |
| 1038 | ** Any remaining command-line argument begins with "-" print |
| 1039 | ** an error message and quit. |
| 1040 | ** |
| 1041 | ** Exception: if "--" is encountered, it is consumed from the argument |
| 1042 | ** list and this function immediately returns. The effect is to treat |
| 1043 | ** all arguments after "--" as non-flags (conventionally used to |
| 1044 | ** enable passing-in of filenames which start with a dash). |
| 1045 | ** |
| 1046 | ** This function must normally only be called one time per app |
| 1047 | ** invokation. The exception is commands which process their |
| 1048 | ** arguments, call this to confirm that there are no extraneous flags, |
| 1049 | ** then modify the arguments list for forwarding to another |
| 1050 | ** (sub)command (which itself will call this to confirm its own |
| 1051 | ** arguments). |
| 1052 | */ |
| 1053 | void verify_all_options(void){ |
| 1054 | int i; |
| 1055 | for(i=1; i<g.argc; i++){ |
| 1056 | const char * arg = g.argv[i]; |
| 1057 | if( arg[0]=='-' ){ |
| 1058 | if( arg[1]=='-' && arg[2]==0 ){ |
| 1059 | /* Remove "--" from the list and treat all following |
| 1060 | ** arguments as non-flags. */ |
| 1061 | remove_from_argv(i, 1); |
| 1062 | break; |
| 1063 | }else if( arg[1]!=0 ){ |
| 1064 | fossil_fatal( |
| 1065 | "unrecognized command-line option or missing argument: %s", |
| 1066 | arg); |
| 1067 | } |
| 1068 | } |
| 1069 | } |
| 1070 | } |
| 1071 | |
| 1072 | /* |
| 1073 | ** This function returns a human readable version string. |
| 1074 | */ |
| 1075 | const char *get_version(){ |
| 1076 |
+1
-1
| --- src/unversioned.c | ||
| +++ src/unversioned.c | ||
| @@ -291,12 +291,12 @@ | ||
| 291 | 291 | const char *zAs; |
| 292 | 292 | Blob file; |
| 293 | 293 | int i; |
| 294 | 294 | |
| 295 | 295 | zAs = find_option("as",0,1); |
| 296 | - if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE"); | |
| 297 | 296 | verify_all_options(); |
| 297 | + if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE"); | |
| 298 | 298 | db_begin_transaction(); |
| 299 | 299 | content_rcvid_init("#!fossil unversioned add"); |
| 300 | 300 | for(i=3; i<g.argc; i++){ |
| 301 | 301 | zIn = zAs ? zAs : g.argv[i]; |
| 302 | 302 | if( zIn[0]==0 ){ |
| 303 | 303 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -291,12 +291,12 @@ | |
| 291 | const char *zAs; |
| 292 | Blob file; |
| 293 | int i; |
| 294 | |
| 295 | zAs = find_option("as",0,1); |
| 296 | if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE"); |
| 297 | verify_all_options(); |
| 298 | db_begin_transaction(); |
| 299 | content_rcvid_init("#!fossil unversioned add"); |
| 300 | for(i=3; i<g.argc; i++){ |
| 301 | zIn = zAs ? zAs : g.argv[i]; |
| 302 | if( zIn[0]==0 ){ |
| 303 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -291,12 +291,12 @@ | |
| 291 | const char *zAs; |
| 292 | Blob file; |
| 293 | int i; |
| 294 | |
| 295 | zAs = find_option("as",0,1); |
| 296 | verify_all_options(); |
| 297 | if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE"); |
| 298 | db_begin_transaction(); |
| 299 | content_rcvid_init("#!fossil unversioned add"); |
| 300 | for(i=3; i<g.argc; i++){ |
| 301 | zIn = zAs ? zAs : g.argv[i]; |
| 302 | if( zIn[0]==0 ){ |
| 303 |