1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Marcus Boerger <helly@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: getopt.c 276986 2009-03-10 23:40:06Z helly $ */
20 :
21 : #include <stdio.h>
22 : #include <string.h>
23 : #include <assert.h>
24 : #include <stdlib.h>
25 : #include "php_getopt.h"
26 :
27 : #define OPTERRCOLON (1)
28 : #define OPTERRNF (2)
29 : #define OPTERRARG (3)
30 :
31 : static int php_opt_error(int argc, char * const *argv, int oint, int optchr, int err, int show_err) /* {{{ */
32 3 : {
33 3 : if (show_err)
34 : {
35 0 : fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1);
36 0 : switch(err)
37 : {
38 : case OPTERRCOLON:
39 0 : fprintf(stderr, ": in flags\n");
40 0 : break;
41 : case OPTERRNF:
42 0 : fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
43 0 : break;
44 : case OPTERRARG:
45 0 : fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]);
46 0 : break;
47 : default:
48 0 : fprintf(stderr, "unknown\n");
49 : break;
50 : }
51 : }
52 3 : return('?');
53 : }
54 : /* }}} */
55 :
56 : PHPAPI int php_optidx = -1;
57 :
58 : PHPAPI int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err, int arg_start) /* {{{ */
59 1677722 : {
60 : static int optchr = 0;
61 : static int dash = 0; /* have already seen the - */
62 :
63 1677722 : php_optidx = -1;
64 :
65 1677722 : if (*optind >= argc) {
66 30822 : return(EOF);
67 : }
68 1646900 : if (!dash) {
69 1646884 : if ((argv[*optind][0] != '-')) {
70 19957 : return(EOF);
71 : } else {
72 1626927 : if (!argv[*optind][1])
73 : {
74 : /*
75 : * use to specify stdin. Need to let pgm process this and
76 : * the following args
77 : */
78 0 : return(EOF);
79 : }
80 : }
81 : }
82 1626991 : if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) {
83 : char *pos;
84 74 : int arg_end = strlen(argv[*optind])-1;
85 :
86 : /* '--' indicates end of args if not followed by a known long option name */
87 74 : if (argv[*optind][2] == '\0') {
88 24 : (*optind)++;
89 24 : return(EOF);
90 : }
91 :
92 50 : arg_start = 2;
93 :
94 : /* Check for <arg>=<val> */
95 50 : if ((pos = php_memnstr(&argv[*optind][arg_start], "=", 1, argv[*optind]+arg_end)) != NULL) {
96 2 : arg_end = pos-&argv[*optind][arg_start];
97 2 : arg_start++;
98 : }
99 :
100 :
101 : while (1) {
102 1141 : php_optidx++;
103 1141 : if (opts[php_optidx].opt_char == '-') {
104 2 : (*optind)++;
105 2 : return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
106 1139 : } else if (opts[php_optidx].opt_name && !strncmp(&argv[*optind][2], opts[php_optidx].opt_name, arg_end)) {
107 48 : break;
108 : }
109 1091 : }
110 48 : optchr = 0;
111 48 : dash = 0;
112 48 : arg_start += strlen(opts[php_optidx].opt_name);
113 : } else {
114 1626869 : if (!dash) {
115 1626853 : dash = 1;
116 1626853 : optchr = 1;
117 : }
118 : /* Check if the guy tries to do a -: kind of flag */
119 1626869 : if (argv[*optind][optchr] == ':') {
120 0 : dash = 0;
121 0 : (*optind)++;
122 0 : return (php_opt_error(argc, argv, *optind-1, optchr, OPTERRCOLON, show_err));
123 : }
124 1626869 : arg_start = 1 + optchr;
125 : }
126 1626917 : if (php_optidx < 0) {
127 : while (1) {
128 8457264 : php_optidx++;
129 8457264 : if (opts[php_optidx].opt_char == '-') {
130 0 : int errind = *optind;
131 0 : int errchr = optchr;
132 :
133 0 : if (!argv[*optind][optchr+1]) {
134 0 : dash = 0;
135 0 : (*optind)++;
136 : } else {
137 0 : optchr++;
138 0 : arg_start++;
139 : }
140 0 : return(php_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err));
141 8457264 : } else if (argv[*optind][optchr] == opts[php_optidx].opt_char) {
142 1626869 : break;
143 : }
144 6830395 : }
145 : }
146 1626917 : if (opts[php_optidx].need_param) {
147 : /* Check for cases where the value of the argument
148 : is in the form -<arg> <val>, -<arg>=<varl> or -<arg><val> */
149 1605890 : dash = 0;
150 1605890 : if (!argv[*optind][arg_start]) {
151 1605818 : (*optind)++;
152 1605818 : if (*optind == argc) {
153 : /* Was the value required or is it optional? */
154 1 : if (opts[php_optidx].need_param == 1) {
155 1 : return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
156 : }
157 : /* Optional value is not supported with -<arg> <val> style */
158 1605817 : } else if (opts[php_optidx].need_param == 1) {
159 1605815 : *optarg = argv[(*optind)++];
160 : }
161 72 : } else if (argv[*optind][arg_start] == '=') {
162 2 : arg_start++;
163 2 : *optarg = &argv[*optind][arg_start];
164 2 : (*optind)++;
165 : } else {
166 70 : *optarg = &argv[*optind][arg_start];
167 70 : (*optind)++;
168 : }
169 1605889 : return opts[php_optidx].opt_char;
170 : } else {
171 : /* multiple options specified as one (exclude long opts) */
172 42044 : if (arg_start >= 2 && !((argv[*optind][0] == '-') && (argv[*optind][1] == '-'))) {
173 21017 : if (!argv[*optind][optchr+1])
174 : {
175 21001 : dash = 0;
176 21001 : (*optind)++;
177 : } else {
178 16 : optchr++;
179 : }
180 : } else {
181 10 : (*optind)++;
182 : }
183 21027 : return opts[php_optidx].opt_char;
184 : }
185 : assert(0);
186 : return(0); /* never reached */
187 : }
188 : /* }}} */
189 :
190 : /*
191 : * Local variables:
192 : * tab-width: 4
193 : * c-basic-offset: 4
194 : * End:
195 : * vim600: sw=4 ts=4 fdm=marker
196 : * vim<600: sw=4 ts=4
197 : */
|