summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/basic_functions.c4
-rw-r--r--ext/standard/tests/general_functions/getopt_004.phpt29
-rw-r--r--ext/standard/tests/general_functions/getopt_005.phpt32
-rw-r--r--main/getopt.c33
4 files changed, 92 insertions, 6 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 09db3e3566..f63887646c 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -4532,6 +4532,10 @@ static int parse_opts(char * opts, opt_struct ** result)
paras->opt_name = NULL;
if (paras->need_param == 1) {
opts++;
+ if (*opts == ':') {
+ paras->need_param++;
+ opts++;
+ }
}
paras++;
}
diff --git a/ext/standard/tests/general_functions/getopt_004.phpt b/ext/standard/tests/general_functions/getopt_004.phpt
new file mode 100644
index 0000000000..193bd40f4d
--- /dev/null
+++ b/ext/standard/tests/general_functions/getopt_004.phpt
@@ -0,0 +1,29 @@
+--TEST--
+getopt#004 (Optional values)
+--ARGS--
+-v -v1 -v=10 --v --v=100
+--INI--
+register_argc_argv=On
+variables_order=GPS
+--FILE--
+<?php
+ var_dump(getopt("v::", array("v::")));
+?>
+--EXPECT--
+array(1) {
+ ["v"]=>
+ array(5) {
+ [0]=>
+ bool(false)
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(2) "10"
+ [3]=>
+ bool(false)
+ [4]=>
+ string(3) "100"
+ }
+}
+
+
diff --git a/ext/standard/tests/general_functions/getopt_005.phpt b/ext/standard/tests/general_functions/getopt_005.phpt
new file mode 100644
index 0000000000..fe43a025e9
--- /dev/null
+++ b/ext/standard/tests/general_functions/getopt_005.phpt
@@ -0,0 +1,32 @@
+--TEST--
+getopt#005 (Required values)
+--ARGS--
+--arg value --arg=value -avalue -a=value -a value
+--INI--
+register_argc_argv=On
+variables_order=GPS
+--FILE--
+<?php
+ var_dump(getopt("a:", array("arg:")));
+?>
+--EXPECT--
+array(2) {
+ ["arg"]=>
+ array(2) {
+ [0]=>
+ string(5) "value"
+ [1]=>
+ string(5) "value"
+ }
+ ["a"]=>
+ array(3) {
+ [0]=>
+ string(5) "value"
+ [1]=>
+ string(5) "value"
+ [2]=>
+ string(5) "value"
+ }
+}
+
+
diff --git a/main/getopt.c b/main/getopt.c
index 2c00920e95..8841610fc6 100644
--- a/main/getopt.c
+++ b/main/getopt.c
@@ -80,24 +80,36 @@ PHPAPI int php_getopt(int argc, char* const *argv, const opt_struct opts[], char
}
}
if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) {
+ char *pos;
+ int arg_end = strlen(argv[*optind])-1;
+
/* '--' indicates end of args if not followed by a known long option name */
if (argv[*optind][2] == '\0') {
(*optind)++;
return(EOF);
}
+ arg_start = 2;
+
+ /* Check for <arg>=<val> */
+ if ((pos = php_memnstr(&argv[*optind][arg_start], "=", 1, argv[*optind]+arg_end)) != NULL) {
+ arg_end = pos-&argv[*optind][arg_start];
+ arg_start++;
+ }
+
+
while (1) {
php_optidx++;
if (opts[php_optidx].opt_char == '-') {
(*optind)++;
return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
- } else if (opts[php_optidx].opt_name && !strcmp(&argv[*optind][2], opts[php_optidx].opt_name)) {
+ } else if (opts[php_optidx].opt_name && !strncmp(&argv[*optind][2], opts[php_optidx].opt_name, arg_end)) {
break;
}
}
optchr = 0;
dash = 0;
- arg_start = 2 + strlen(opts[php_optidx].opt_name);
+ arg_start += strlen(opts[php_optidx].opt_name);
} else {
if (!dash) {
dash = 1;
@@ -133,14 +145,23 @@ PHPAPI int php_getopt(int argc, char* const *argv, const opt_struct opts[], char
}
if (opts[php_optidx].need_param) {
/* Check for cases where the value of the argument
- is in the form -<arg> <val> or in the form -<arg><val> */
+ is in the form -<arg> <val>, -<arg>=<varl> or -<arg><val> */
dash = 0;
if (!argv[*optind][arg_start]) {
(*optind)++;
if (*optind == argc) {
- return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
- }
- *optarg = argv[(*optind)++];
+ /* Was the value required or is it optional? */
+ if (opts[php_optidx].need_param == 1) {
+ return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
+ }
+ /* Optional value is not supported with -<arg> <val> style */
+ } else if (opts[php_optidx].need_param == 1) {
+ *optarg = argv[(*optind)++];
+ }
+ } else if (argv[*optind][arg_start] == '=') {
+ arg_start++;
+ *optarg = &argv[*optind][arg_start];
+ (*optind)++;
} else {
*optarg = &argv[*optind][arg_start];
(*optind)++;