PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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[0] && place[0] == '-' && place[1] == '\0')
83  { /* found "--" */
84  ++optind;
85  place = EMSG;
86  return -1;
87  }
88 
89  if (place[0] && place[0] == '-' && place[1])
90  {
91  /* long option */
92  size_t namelen;
93  int i;
94 
95  place++;
96 
97  namelen = strcspn(place, "=");
98  for (i = 0; longopts[i].name != NULL; i++)
99  {
100  if (strlen(longopts[i].name) == namelen
101  && strncmp(place, longopts[i].name, namelen) == 0)
102  {
103  int has_arg = longopts[i].has_arg;
104 
105  if (has_arg != no_argument)
106  {
107  if (place[namelen] == '=')
108  optarg = place + namelen + 1;
109  else if (optind < argc - 1 &&
110  has_arg == required_argument)
111  {
112  optind++;
113  optarg = argv[optind];
114  }
115  else
116  {
117  if (optstring[0] == ':')
118  return BADARG;
119 
120  if (opterr && has_arg == required_argument)
121  fprintf(stderr,
122  "%s: option requires an argument -- %s\n",
123  argv[0], place);
124 
125  place = EMSG;
126  optind++;
127 
128  if (has_arg == required_argument)
129  return BADCH;
130  optarg = NULL;
131  }
132  }
133  else
134  {
135  optarg = NULL;
136  if (place[namelen] != 0)
137  {
138  /* XXX error? */
139  }
140  }
141 
142  optind++;
143 
144  if (longindex)
145  *longindex = i;
146 
147  place = EMSG;
148 
149  if (longopts[i].flag == NULL)
150  return longopts[i].val;
151  else
152  {
153  *longopts[i].flag = longopts[i].val;
154  return 0;
155  }
156  }
157  }
158 
159  if (opterr && optstring[0] != ':')
160  fprintf(stderr,
161  "%s: illegal option -- %s\n", argv[0], place);
162  place = EMSG;
163  optind++;
164  return BADCH;
165  }
166  }
167 
168  /* short option */
169  optopt = (int) *place++;
170 
171  oli = strchr(optstring, optopt);
172  if (!oli)
173  {
174  if (!*place)
175  ++optind;
176  if (opterr && *optstring != ':')
177  fprintf(stderr,
178  "%s: illegal option -- %c\n", argv[0], optopt);
179  return BADCH;
180  }
181 
182  if (oli[1] != ':')
183  { /* don't need argument */
184  optarg = NULL;
185  if (!*place)
186  ++optind;
187  }
188  else
189  { /* need an argument */
190  if (*place) /* no white space */
191  optarg = place;
192  else if (argc <= ++optind)
193  { /* no arg */
194  place = EMSG;
195  if (*optstring == ':')
196  return BADARG;
197  if (opterr)
198  fprintf(stderr,
199  "%s: option requires an argument -- %c\n",
200  argv[0], optopt);
201  return BADCH;
202  }
203  else
204  /* white space */
205  optarg = argv[optind];
206  place = EMSG;
207  ++optind;
208  }
209  return optopt;
210 }
int val
Definition: getopt_long.h:21
#define BADCH
Definition: getopt_long.c:41
#define required_argument
Definition: getopt_long.h:25
int optind
Definition: getopt.c:51
int optopt
Definition: getopt.c:51
char * flag(int b)
Definition: test-ctype.c:33
int opterr
Definition: getopt.c:50
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
#define NULL
Definition: c.h:226
const char * name
Definition: encode.c:521
char * optarg
Definition: getopt.c:53
int i
#define BADARG
Definition: getopt_long.c:42
int has_arg
Definition: getopt_long.h:19