Back to index

php5  5.3.10
getopt.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Marcus Boerger <helly@php.net>                               |
00016    +----------------------------------------------------------------------+
00017 */
00018 
00019 /* $Id: getopt.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <assert.h>
00024 #include <stdlib.h>
00025 #include "php_getopt.h"
00026 
00027 #define OPTERRCOLON (1)
00028 #define OPTERRNF (2)
00029 #define OPTERRARG (3)
00030 
00031 static int php_opt_error(int argc, char * const *argv, int oint, int optchr, int err, int show_err) /* {{{ */
00032 {
00033        if (show_err)
00034        {
00035               fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1);
00036               switch(err)
00037               {
00038               case OPTERRCOLON:
00039                      fprintf(stderr, ": in flags\n");
00040                      break;
00041               case OPTERRNF:
00042                      fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
00043                      break;
00044               case OPTERRARG:
00045                      fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]);
00046                      break;
00047               default:
00048                      fprintf(stderr, "unknown\n");
00049                      break;
00050               }
00051        }
00052        return('?');
00053 }
00054 /* }}} */
00055 
00056 PHPAPI int php_optidx = -1;
00057 
00058 PHPAPI int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err, int arg_start) /* {{{ */
00059 {
00060        static int optchr = 0;
00061        static int dash = 0; /* have already seen the - */
00062 
00063        php_optidx = -1;
00064 
00065        if (*optind >= argc) {
00066               return(EOF);
00067        }
00068        if (!dash) {
00069               if ((argv[*optind][0] !=  '-')) {
00070                      return(EOF);
00071               } else {
00072                      if (!argv[*optind][1])
00073                      {
00074                             /*
00075                             * use to specify stdin. Need to let pgm process this and
00076                             * the following args
00077                             */
00078                             return(EOF);
00079                      }
00080               }
00081        }
00082        if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) {
00083               char *pos;
00084               int arg_end = strlen(argv[*optind])-1;
00085 
00086               /* '--' indicates end of args if not followed by a known long option name */
00087               if (argv[*optind][2] == '\0') {
00088                      (*optind)++;
00089                      return(EOF);
00090               }
00091 
00092               arg_start = 2;
00093 
00094               /* Check for <arg>=<val> */
00095               if ((pos = php_memnstr(&argv[*optind][arg_start], "=", 1, argv[*optind]+arg_end)) != NULL) {
00096                      arg_end = pos-&argv[*optind][arg_start];
00097                      arg_start++;
00098               } else {
00099                      arg_end--;
00100               }
00101 
00102               while (1) {
00103                      php_optidx++;
00104                      if (opts[php_optidx].opt_char == '-') {
00105                             (*optind)++;
00106                             return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
00107                      } else if (opts[php_optidx].opt_name && !strncmp(&argv[*optind][2], opts[php_optidx].opt_name, arg_end) && arg_end == strlen(opts[php_optidx].opt_name)) {
00108                             break;
00109                      }
00110               }
00111 
00112               optchr = 0;
00113               dash = 0;
00114               arg_start += strlen(opts[php_optidx].opt_name);
00115        } else {
00116               if (!dash) {
00117                      dash = 1;
00118                      optchr = 1;
00119               }
00120               /* Check if the guy tries to do a -: kind of flag */
00121               if (argv[*optind][optchr] == ':') {
00122                      dash = 0;
00123                      (*optind)++;
00124                      return (php_opt_error(argc, argv, *optind-1, optchr, OPTERRCOLON, show_err));
00125               }
00126               arg_start = 1 + optchr;
00127        }
00128        if (php_optidx < 0) {
00129               while (1) {
00130                      php_optidx++;
00131                      if (opts[php_optidx].opt_char == '-') {
00132                             int errind = *optind;
00133                             int errchr = optchr;
00134 
00135                             if (!argv[*optind][optchr+1]) {
00136                                    dash = 0;
00137                                    (*optind)++;
00138                             } else {
00139                                    optchr++;
00140                                    arg_start++;
00141                             }
00142                             return(php_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err));
00143                      } else if (argv[*optind][optchr] == opts[php_optidx].opt_char) {
00144                             break;
00145                      }
00146               }
00147        }
00148        if (opts[php_optidx].need_param) {
00149               /* Check for cases where the value of the argument
00150               is in the form -<arg> <val>, -<arg>=<varl> or -<arg><val> */
00151               dash = 0;
00152               if (!argv[*optind][arg_start]) {
00153                      (*optind)++;
00154                      if (*optind == argc) {
00155                             /* Was the value required or is it optional? */
00156                             if (opts[php_optidx].need_param == 1) {
00157                                    return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
00158                             }
00159                      /* Optional value is not supported with -<arg> <val> style */
00160                      } else if (opts[php_optidx].need_param == 1) {
00161                             *optarg = argv[(*optind)++];
00162                      }
00163               } else if (argv[*optind][arg_start] == '=') {
00164                      arg_start++;
00165                      *optarg = &argv[*optind][arg_start];
00166                      (*optind)++;
00167               } else {
00168                      *optarg = &argv[*optind][arg_start];
00169                      (*optind)++;
00170               }
00171               return opts[php_optidx].opt_char;
00172        } else {
00173               /* multiple options specified as one (exclude long opts) */
00174               if (arg_start >= 2 && !((argv[*optind][0] == '-') && (argv[*optind][1] == '-'))) {
00175                      if (!argv[*optind][optchr+1])
00176                      {
00177                             dash = 0;
00178                             (*optind)++;
00179                      } else {
00180                             optchr++;
00181                      }
00182               } else {
00183                      (*optind)++;
00184               }
00185               return opts[php_optidx].opt_char;
00186        }
00187        assert(0);
00188        return(0);    /* never reached */
00189 }
00190 /* }}} */
00191 
00192 /*
00193  * Local variables:
00194  * tab-width: 4
00195  * c-basic-offset: 4
00196  * End:
00197  * vim600: sw=4 ts=4 fdm=marker
00198  * vim<600: sw=4 ts=4
00199  */