summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorHartmut Holzgraefe <hholzgra@php.net>2002-10-21 16:07:21 +0000
committerHartmut Holzgraefe <hholzgra@php.net>2002-10-21 16:07:21 +0000
commitb67b00efcdd8bd6feed6d861bdc2bd7ece0f9761 (patch)
treea2c5d2f9b152da7b9a7565e0befdab0d22d92c92 /ext
parent3e99daca3948417335b4a55b77716150c4345b86 (diff)
downloadphp-git-b67b00efcdd8bd6feed6d861bdc2bd7ece0f9761.tar.gz
getopt() now supports long options on platforms that have getopt_long()
getopt() now working independant of register_argc_argv settings
Diffstat (limited to 'ext')
-rw-r--r--ext/standard/basic_functions.c118
-rw-r--r--ext/standard/config.m42
2 files changed, 107 insertions, 13 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index c8d5aa505a..177c0766a5 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -73,6 +73,10 @@
# include <sys/mman.h>
#endif
+#ifdef HAVE_GETOPT_LONG
+#include <getopt.h>
+#endif
+
#include "safe_mode.h"
#ifdef PHP_WIN32
@@ -1367,17 +1371,40 @@ static void free_argv(char **argv, int argc)
}
/* }}} */
-/* {{{ proto array getopt(string options)
+#ifdef HAVE_GETOPT_LONG
+/* {{{ free_longopts
+ Free the memory allocated to an longopt array. */
+static void free_longopts(struct option *longopts)
+{
+ struct option *p;
+
+ if(longopts) {
+ for(p=longopts; p->name; p++) {
+ efree((char *)(p->name));
+ }
+
+ efree(longopts);
+ }
+}
+/* }}} */
+#endif
+
+/* {{{ proto array getopt(string options [, array longopts])
Get options from the command line argument list */
PHP_FUNCTION(getopt)
{
char *options = NULL, **argv = NULL;
char opt[2] = { '\0' };
+ char *optname;
int argc = 0, options_len = 0, o;
- zval *val, **args = NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
- &options, &options_len) == FAILURE) {
+ zval *val, **args = NULL, *p_longopts = NULL;
+#ifdef HAVE_GETOPT_LONG
+ struct option *longopts = NULL;
+ int longindex = 0;
+#endif
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a",
+ &options, &options_len, &p_longopts) == FAILURE) {
RETURN_FALSE;
}
@@ -1386,7 +1413,8 @@ PHP_FUNCTION(getopt)
* in order to be on the safe side, even though it is also available
* from the symbol table.
*/
- if (zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"),
+ // TODO take fromm trackvars instead
+ if (zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv"),
(void **) &args) != FAILURE) {
int pos = 0;
zval **arg;
@@ -1421,6 +1449,50 @@ PHP_FUNCTION(getopt)
RETURN_FALSE;
}
+ if(p_longopts) {
+#ifdef HAVE_GETOPT_LONG
+ int len, c = zend_hash_num_elements(Z_ARRVAL_P(p_longopts));
+ struct option *p;
+ zval **arg;
+ char *name;
+
+ longopts = (struct option *)ecalloc(c+1, sizeof(struct option));
+
+ if(!longopts) RETURN_FALSE;
+
+ /* Reset the array indexes. */
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(p_longopts));
+ p = longopts;
+
+ /* Iterate over the hash to construct the argv array. */
+ while (zend_hash_get_current_data(Z_ARRVAL_P(p_longopts),
+ (void **)&arg) == SUCCESS) {
+
+ // todo check for : and ::, strip'em, efrees ...
+ p->has_arg = 0;
+ name = estrdup(Z_STRVAL_PP(arg));
+ len = strlen(name);
+ if((len > 0) && (name[len-1] == ':')) {
+ p->has_arg++;
+ name[len-1] = '\0';
+ if((len > 1) && (name[len-2] == ':')) {
+ p->has_arg++;
+ name[len-2] = '\0';
+ }
+ }
+
+ p->name = name;
+ p->flag = NULL;
+ p->val = 0;
+
+ zend_hash_move_forward(Z_ARRVAL_P(p_longopts));
+ p++;
+ }
+#else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No support for long options in this build");
+#endif
+ }
+
/* Initialize the return value as an array. */
if (array_init(return_value)) {
RETURN_FALSE;
@@ -1429,16 +1501,29 @@ PHP_FUNCTION(getopt)
/* Disable getopt()'s error messages. */
opterr = 0;
+ /* reset option parser position */
+ optind = 0;
+
/* Invoke getopt(3) on the argument array. */
+#ifdef HAVE_GETOPT_LONG
+ while ((o = getopt_long(argc, argv, options, longopts, &longindex)) != -1) {
+#else
while ((o = getopt(argc, argv, options)) != -1) {
-
+#endif
/* Skip unknown arguments. */
if (o == '?') {
+ // TODO bailout?
continue;
}
/* Prepare the option character and the argument string. */
- opt[0] = o;
+ if(o == 0) {
+ optname = (char *)longopts[longindex].name;
+ } else {
+ if(o == 1) o = '-';
+ opt[0] = o;
+ optname = opt;
+ }
MAKE_STD_ZVAL(val);
if (optarg != NULL) {
@@ -1448,14 +1533,21 @@ PHP_FUNCTION(getopt)
}
/* Add this option / argument pair to the result hash. */
- if (zend_hash_add(HASH_OF(return_value), opt, sizeof(opt), (void *)&val,
- sizeof(zval *), NULL) == FAILURE) {
- free_argv(argv, argc);
- RETURN_FALSE;
+ if(zend_hash_find(HASH_OF(return_value), optname, strlen(optname)+1, (void **)&args) != FAILURE) {
+ if(Z_TYPE_PP(args) != IS_ARRAY) {
+ convert_to_array_ex(args);
+ }
+ zend_hash_next_index_insert(HASH_OF(*args), (void *)&val, sizeof(zval *), NULL);
+ } else {
+ zend_hash_add(HASH_OF(return_value), optname, strlen(optname)+1, (void *)&val,
+ sizeof(zval *), NULL);
}
}
free_argv(argv, argc);
+#ifdef HAVE_GETOPT_LONG
+ free_longopts(longopts);
+#endif
}
/* }}} */
#endif
@@ -1716,7 +1808,7 @@ PHP_FUNCTION(call_user_func)
}
if (!zend_is_callable(*params[0], 0, &name)) {
- php_error_docref1(NULL TSRMLS_CC, name, E_WARNING, "First argumented is expected to be a valid callback");
+ php_error_docref1(NULL TSRMLS_CC, name, E_WARNING, "First argument is expected to be a valid callback");
efree(name);
efree(params);
RETURN_NULL();
diff --git a/ext/standard/config.m4 b/ext/standard/config.m4
index f3c246e7dc..2fcf362c0b 100644
--- a/ext/standard/config.m4
+++ b/ext/standard/config.m4
@@ -228,6 +228,8 @@ AC_CHECK_FUNCS(glob)
AC_CHECK_FUNCS(strfmon)
+AC_CHECK_FUNCS(getopt_long getopt_long_only)
+
if test "$PHP_SAPI" = "cgi"; then
AC_DEFINE(ENABLE_CHROOT_FUNC, 1, [Whether to enable chroot() function])
fi