PostgreSQL Source Code  git master
getopt_long.c
Go to the documentation of this file.
1 /*
2  * getopt_long() -- long options parser
3  *
4  * Portions Copyright (c) 1987, 1993, 1994
5  * The Regents of the University of California. All rights reserved.
6  *
7  * Portions Copyright (c) 2003
8  * PostgreSQL Global Development Group
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * src/port/getopt_long.c
35  */
36 
37 #include "c.h"
38 
39 #include "getopt_long.h"
40 
41 #define BADCH '?'
42 #define BADARG ':'
43 #define EMSG ""
44 
45 
46 /*
47  * getopt_long
48  * Parse argc/argv argument vector, with long options.
49  *
50  * This implementation does not use optreset. Instead, we guarantee that
51  * it can be restarted on a new argv array after a previous call returned -1,
52  * if the caller resets optind to 1 before the first call of the new series.
53  * (Internally, this means we must be sure to reset "place" to EMSG before
54  * returning -1.)
55  */
56 int
57 getopt_long(int argc, char *const argv[],
58  const char *optstring,
59  const struct option *longopts, int *longindex)
60 {
61  static char *place = EMSG; /* option letter processing */
62  char *oli; /* option letter list index */
63 
64  if (!*place)
65  { /* update scanning pointer */
66  if (optind >= argc)
67  {
68  place = EMSG;
69  return -1;
70  }
71 
72  place = argv[optind];
73 
74  if (place[0] != '-')
75  {
76  place = EMSG;
77  return -1;
78  }
79 
80  place++;
81 
82  if (!*place)
83  {
84  /* treat "-" as not being an option */
85  place = EMSG;
86  return -1;
87  }
88 
89  if (place[0] == '-' && place[1] == '\0')
90  {
91  /* found "--", treat it as end of options */
92  ++optind;
93  place = EMSG;
94  return -1;
95  }
96 
97  if (place[0] == '-' && place[1])
98  {
99  /* long option */
100  size_t namelen;
101  int i;
102 
103  place++;
104 
105  namelen = strcspn(place, "=");
106  for (i = 0; longopts[i].name != NULL; i++)
107  {
108  if (strlen(longopts[i].name) == namelen
109  && strncmp(place, longopts[i].name, namelen) == 0)
110  {
111  int has_arg = longopts[i].has_arg;
112 
113  if (has_arg != no_argument)
114  {
115  if (place[namelen] == '=')
116  optarg = place + namelen + 1;
117  else if (optind < argc - 1 &&
118  has_arg == required_argument)
119  {
120  optind++;
121  optarg = argv[optind];
122  }
123  else
124  {
125  if (optstring[0] == ':')
126  return BADARG;
127 
128  if (opterr && has_arg == required_argument)
129  fprintf(stderr,
130  "%s: option requires an argument -- %s\n",
131  argv[0], place);
132 
133  place = EMSG;
134  optind++;
135 
136  if (has_arg == required_argument)
137  return BADCH;
138  optarg = NULL;
139  }
140  }
141  else
142  {
143  optarg = NULL;
144  if (place[namelen] != 0)
145  {
146  /* XXX error? */
147  }
148  }
149 
150  optind++;
151 
152  if (longindex)
153  *longindex = i;
154 
155  place = EMSG;
156 
157  if (longopts[i].flag == NULL)
158  return longopts[i].val;
159  else
160  {
161  *longopts[i].flag = longopts[i].val;
162  return 0;
163  }
164  }
165  }
166 
167  if (opterr && optstring[0] != ':')
168  fprintf(stderr,
169  "%s: illegal option -- %s\n", argv[0], place);
170  place = EMSG;
171  optind++;
172  return BADCH;
173  }
174  }
175 
176  /* short option */
177  optopt = (int) *place++;
178 
179  oli = strchr(optstring, optopt);
180  if (!oli)
181  {
182  if (!*place)
183  ++optind;
184  if (opterr && *optstring != ':')
185  fprintf(stderr,
186  "%s: illegal option -- %c\n", argv[0], optopt);
187  return BADCH;
188  }
189 
190  if (oli[1] != ':')
191  { /* don't need argument */
192  optarg = NULL;
193  if (!*place)
194  ++optind;
195  }
196  else
197  { /* need an argument */
198  if (*place) /* no white space */
199  optarg = place;
200  else if (argc <= ++optind)
201  { /* no arg */
202  place = EMSG;
203  if (*optstring == ':')
204  return BADARG;
205  if (opterr)
206  fprintf(stderr,
207  "%s: option requires an argument -- %c\n",
208  argv[0], optopt);
209  return BADCH;
210  }
211  else
212  /* white space */
213  optarg = argv[optind];
214  place = EMSG;
215  ++optind;
216  }
217  return optopt;
218 }
int val
Definition: getopt_long.h:21
#define fprintf
Definition: port.h:197
#define BADCH
Definition: getopt_long.c:41
#define required_argument
Definition: getopt_long.h:25
int optind
Definition: getopt.c:50
int optopt
Definition: getopt.c:50
char * flag(int b)
Definition: test-ctype.c:33
int opterr
Definition: getopt.c:49
const char * name
Definition: getopt_long.h:18
#define no_argument
Definition: getopt_long.h:24
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
int * flag
Definition: getopt_long.h:20
#define EMSG
Definition: getopt_long.c:43
const char * name
Definition: encode.c:521
char * optarg
Definition: getopt.c:52
int i
#define BADARG
Definition: getopt_long.c:42
int has_arg
Definition: getopt_long.h:19