1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2014 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,v 1.1.1.4 2014/06/15 20:04:01 misho Exp $ */
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: {
33: if (show_err)
34: {
35: fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1);
36: switch(err)
37: {
38: case OPTERRCOLON:
39: fprintf(stderr, ": in flags\n");
40: break;
41: case OPTERRNF:
42: fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
43: break;
44: case OPTERRARG:
45: fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]);
46: break;
47: default:
48: fprintf(stderr, "unknown\n");
49: break;
50: }
51: }
52: 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: {
60: static int optchr = 0;
61: static int dash = 0; /* have already seen the - */
62:
63: php_optidx = -1;
64:
65: if (*optind >= argc) {
66: return(EOF);
67: }
68: if (!dash) {
69: if ((argv[*optind][0] != '-')) {
70: return(EOF);
71: } else {
72: if (!argv[*optind][1])
73: {
74: /*
75: * use to specify stdin. Need to let pgm process this and
76: * the following args
77: */
78: return(EOF);
79: }
80: }
81: }
82: if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) {
83: char *pos;
84: int arg_end = strlen(argv[*optind])-1;
85:
86: /* '--' indicates end of args if not followed by a known long option name */
87: if (argv[*optind][2] == '\0') {
88: (*optind)++;
89: return(EOF);
90: }
91:
92: arg_start = 2;
93:
94: /* Check for <arg>=<val> */
95: if ((pos = php_memnstr(&argv[*optind][arg_start], "=", 1, argv[*optind]+arg_end)) != NULL) {
96: arg_end = pos-&argv[*optind][arg_start];
97: arg_start++;
98: } else {
99: arg_end--;
100: }
101:
102: while (1) {
103: php_optidx++;
104: if (opts[php_optidx].opt_char == '-') {
105: (*optind)++;
106: return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
107: } 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)) {
108: break;
109: }
110: }
111:
112: optchr = 0;
113: dash = 0;
114: arg_start += strlen(opts[php_optidx].opt_name);
115: } else {
116: if (!dash) {
117: dash = 1;
118: optchr = 1;
119: }
120: /* Check if the guy tries to do a -: kind of flag */
121: if (argv[*optind][optchr] == ':') {
122: dash = 0;
123: (*optind)++;
124: return (php_opt_error(argc, argv, *optind-1, optchr, OPTERRCOLON, show_err));
125: }
126: arg_start = 1 + optchr;
127: }
128: if (php_optidx < 0) {
129: while (1) {
130: php_optidx++;
131: if (opts[php_optidx].opt_char == '-') {
132: int errind = *optind;
133: int errchr = optchr;
134:
135: if (!argv[*optind][optchr+1]) {
136: dash = 0;
137: (*optind)++;
138: } else {
139: optchr++;
140: arg_start++;
141: }
142: return(php_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err));
143: } else if (argv[*optind][optchr] == opts[php_optidx].opt_char) {
144: break;
145: }
146: }
147: }
148: if (opts[php_optidx].need_param) {
149: /* Check for cases where the value of the argument
150: is in the form -<arg> <val>, -<arg>=<varl> or -<arg><val> */
151: dash = 0;
152: if (!argv[*optind][arg_start]) {
153: (*optind)++;
154: if (*optind == argc) {
155: /* Was the value required or is it optional? */
156: if (opts[php_optidx].need_param == 1) {
157: return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err));
158: }
159: /* Optional value is not supported with -<arg> <val> style */
160: } else if (opts[php_optidx].need_param == 1) {
161: *optarg = argv[(*optind)++];
162: }
163: } else if (argv[*optind][arg_start] == '=') {
164: arg_start++;
165: *optarg = &argv[*optind][arg_start];
166: (*optind)++;
167: } else {
168: *optarg = &argv[*optind][arg_start];
169: (*optind)++;
170: }
171: return opts[php_optidx].opt_char;
172: } else {
173: /* multiple options specified as one (exclude long opts) */
174: if (arg_start >= 2 && !((argv[*optind][0] == '-') && (argv[*optind][1] == '-'))) {
175: if (!argv[*optind][optchr+1])
176: {
177: dash = 0;
178: (*optind)++;
179: } else {
180: optchr++;
181: }
182: } else {
183: (*optind)++;
184: }
185: return opts[php_optidx].opt_char;
186: }
187: assert(0);
188: return(0); /* never reached */
189: }
190: /* }}} */
191:
192: /*
193: * Local variables:
194: * tab-width: 4
195: * c-basic-offset: 4
196: * End:
197: * vim600: sw=4 ts=4 fdm=marker
198: * vim<600: sw=4 ts=4
199: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>