1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
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 272374 2008-12-31 11:17:49Z sebastian $ */
20 :
21 : #include <stdio.h>
22 : #include <string.h>
23 : #include <assert.h>
24 : #include <stdlib.h>
25 : #include "php_getopt.h"
26 : #define OPTERRCOLON (1)
27 : #define OPTERRNF (2)
28 : #define OPTERRARG (3)
29 :
30 :
31 : static int php_opt_error(int argc, char * const *argv, int oint, int optchr, int err, int show_err) /* {{{ */
32 2 : {
33 2 : 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 2 : return('?');
53 : }
54 : /* }}} */
55 :
56 : int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err) /* {{{ */
57 1290879 : {
58 : static int optchr = 0;
59 : static int dash = 0; /* have already seen the - */
60 1290879 : int arg_start = 2;
61 :
62 1290879 : int opts_idx = -1;
63 :
64 1290879 : if (*optind >= argc) {
65 25342 : return(EOF);
66 : }
67 1265537 : if (!dash) {
68 1265531 : if ((argv[*optind][0] != '-')) {
69 14999 : return(EOF);
70 : } else {
71 1250532 : if (!argv[*optind][1])
72 : {
73 : /*
74 : * use to specify stdin. Need to let pgm process this and
75 : * the following args
76 : */
77 0 : return(EOF);
78 : }
79 : }
80 : }
81 1250569 : if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) {
82 : /* '--' indicates end of args if not followed by a known long option name */
83 45 : if (argv[*optind][2] == '\0') {
84 12 : (*optind)++;
85 12 : return(EOF);
86 : }
87 :
88 : while (1) {
89 889 : opts_idx++;
90 889 : if (opts[opts_idx].opt_char == '-') {
91 2 : (*optind)++;
92 2 : return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
93 887 : } else if (opts[opts_idx].opt_name && !strcmp(&argv[*optind][2], opts[opts_idx].opt_name)) {
94 31 : break;
95 : }
96 856 : }
97 31 : optchr = 0;
98 31 : dash = 0;
99 31 : arg_start = 2 + strlen(opts[opts_idx].opt_name);
100 : } else {
101 1250493 : if (!dash) {
102 1250487 : dash = 1;
103 1250487 : optchr = 1;
104 : }
105 : /* Check if the guy tries to do a -: kind of flag */
106 1250493 : if (argv[*optind][optchr] == ':') {
107 0 : dash = 0;
108 0 : (*optind)++;
109 0 : return (php_opt_error(argc, argv, *optind-1, optchr, OPTERRCOLON, show_err));
110 : }
111 1250493 : arg_start = 1 + optchr;
112 : }
113 1250524 : if (opts_idx < 0) {
114 : while (1) {
115 6506616 : opts_idx++;
116 6506616 : if (opts[opts_idx].opt_char == '-') {
117 0 : int errind = *optind;
118 0 : int errchr = optchr;
119 :
120 0 : if (!argv[*optind][optchr+1]) {
121 0 : dash = 0;
122 0 : (*optind)++;
123 : } else {
124 0 : optchr++;
125 0 : arg_start++;
126 : }
127 0 : return(php_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err));
128 6506616 : } else if (argv[*optind][optchr] == opts[opts_idx].opt_char) {
129 1250493 : break;
130 : }
131 5256123 : }
132 : }
133 1250524 : if (opts[opts_idx].need_param) {
134 : /* Check for cases where the value of the argument
135 : is in the form -<arg> <val> or in the form -<arg><val> */
136 1235283 : dash = 0;
137 1235283 : if(!argv[*optind][arg_start]) {
138 1235274 : (*optind)++;
139 1235274 : if (*optind == argc) {
140 0 : return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
141 : }
142 1235274 : *optarg = argv[(*optind)++];
143 : } else {
144 9 : *optarg = &argv[*optind][arg_start];
145 9 : (*optind)++;
146 : }
147 1235283 : return opts[opts_idx].opt_char;
148 : } else {
149 : /* multiple options specified as one (exclude long opts) */
150 30478 : if (arg_start >= 2 && !((argv[*optind][0] == '-') && (argv[*optind][1] == '-'))) {
151 15237 : if (!argv[*optind][optchr+1])
152 : {
153 15231 : dash = 0;
154 15231 : (*optind)++;
155 : } else {
156 6 : optchr++;
157 : }
158 : } else {
159 4 : (*optind)++;
160 : }
161 15241 : return opts[opts_idx].opt_char;
162 : }
163 : assert(0);
164 : return(0); /* never reached */
165 : }
166 : /* }}} */
167 :
168 : /*
169 : * Local variables:
170 : * tab-width: 4
171 : * c-basic-offset: 4
172 : * End:
173 : * vim600: sw=4 ts=4 fdm=marker
174 : * vim<600: sw=4 ts=4
175 : */
|