/src/postgres/src/port/pg_getopt_ctx.c
Line | Count | Source |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * pg_getopt_ctx.c |
4 | | * Thread-safe implementation of getopt() |
5 | | * |
6 | | * Copyright (c) 1987, 1993, 1994 |
7 | | * The Regents of the University of California. All rights reserved. |
8 | | * |
9 | | * Redistribution and use in source and binary forms, with or without |
10 | | * modification, are permitted provided that the following conditions |
11 | | * are met: |
12 | | * 1. Redistributions of source code must retain the above copyright |
13 | | * notice, this list of conditions and the following disclaimer. |
14 | | * 2. Redistributions in binary form must reproduce the above copyright |
15 | | * notice, this list of conditions and the following disclaimer in the |
16 | | * documentation and/or other materials provided with the distribution. |
17 | | * 3. Neither the name of the University nor the names of its contributors |
18 | | * may be used to endorse or promote products derived from this software |
19 | | * without specific prior written permission. |
20 | | * |
21 | | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
22 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
25 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
26 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
27 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
28 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
29 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
30 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
31 | | * |
32 | | * IDENTIFICATION |
33 | | * src/port/pg_getopt_ctx.c |
34 | | * |
35 | | *------------------------------------------------------------------------- |
36 | | */ |
37 | | |
38 | | #include "c.h" |
39 | | |
40 | | #include "port/pg_getopt_ctx.h" |
41 | | |
42 | 0 | #define BADCH (int)'?' |
43 | 0 | #define BADARG (int)':' |
44 | 0 | #define EMSG "" |
45 | | |
46 | | /* |
47 | | * Start parsing argc/argv argument vector. |
48 | | * |
49 | | * This is a re-entrant version of the standard library getopt(3) function. |
50 | | * To use, first call pg_getopt_start() to initialize the state, and then call |
51 | | * pg_getopt_next() until it returns -1. |
52 | | */ |
53 | | void |
54 | | pg_getopt_start(pg_getopt_ctx *ctx, int nargc, char *const *nargv, const char *ostr) |
55 | 0 | { |
56 | 0 | ctx->nargc = nargc; |
57 | 0 | ctx->nargv = nargv; |
58 | 0 | ctx->ostr = ostr; |
59 | |
|
60 | 0 | ctx->optind = 1; |
61 | 0 | ctx->optarg = NULL; |
62 | 0 | ctx->opterr = 1; /* Caller may clear this after the call */ |
63 | 0 | ctx->optopt = 0; |
64 | |
|
65 | 0 | ctx->place = EMSG; /* option letter processing */ |
66 | 0 | } |
67 | | |
68 | | /* |
69 | | * Parse next option in argc/argv argument vector |
70 | | */ |
71 | | int |
72 | | pg_getopt_next(pg_getopt_ctx *ctx) |
73 | 0 | { |
74 | 0 | const char *oli; /* option letter list index */ |
75 | |
|
76 | 0 | if (!*ctx->place) |
77 | 0 | { /* update scanning pointer */ |
78 | 0 | if (ctx->optind >= ctx->nargc || *(ctx->place = ctx->nargv[ctx->optind]) != '-') |
79 | 0 | { |
80 | 0 | ctx->place = EMSG; |
81 | 0 | return -1; |
82 | 0 | } |
83 | 0 | if (ctx->place[1] && *++ctx->place == '-' && ctx->place[1] == '\0') |
84 | 0 | { /* found "--" */ |
85 | 0 | ++ctx->optind; |
86 | 0 | ctx->place = EMSG; |
87 | 0 | return -1; |
88 | 0 | } |
89 | 0 | } /* option letter okay? */ |
90 | 0 | if ((ctx->optopt = (int) *ctx->place++) == (int) ':' || |
91 | 0 | !(oli = strchr(ctx->ostr, ctx->optopt))) |
92 | 0 | { |
93 | | /* |
94 | | * if the user didn't specify '-' as an option, assume it means -1. |
95 | | */ |
96 | 0 | if (ctx->optopt == (int) '-') |
97 | 0 | { |
98 | 0 | ctx->place = EMSG; |
99 | 0 | return -1; |
100 | 0 | } |
101 | 0 | if (!*ctx->place) |
102 | 0 | ++ctx->optind; |
103 | 0 | if (ctx->opterr && *ctx->ostr != ':') |
104 | 0 | (void) fprintf(stderr, |
105 | 0 | "illegal option -- %c\n", ctx->optopt); |
106 | 0 | return BADCH; |
107 | 0 | } |
108 | 0 | if (*++oli != ':') |
109 | 0 | { /* don't need argument */ |
110 | 0 | ctx->optarg = NULL; |
111 | 0 | if (!*ctx->place) |
112 | 0 | ++ctx->optind; |
113 | 0 | } |
114 | 0 | else |
115 | 0 | { /* need an argument */ |
116 | 0 | if (*ctx->place) /* no white space */ |
117 | 0 | ctx->optarg = ctx->place; |
118 | 0 | else if (ctx->nargc <= ++ctx->optind) |
119 | 0 | { /* no arg */ |
120 | 0 | ctx->place = EMSG; |
121 | 0 | if (*ctx->ostr == ':') |
122 | 0 | return BADARG; |
123 | 0 | if (ctx->opterr) |
124 | 0 | (void) fprintf(stderr, |
125 | 0 | "option requires an argument -- %c\n", |
126 | 0 | ctx->optopt); |
127 | 0 | return BADCH; |
128 | 0 | } |
129 | 0 | else |
130 | | /* white space */ |
131 | 0 | ctx->optarg = ctx->nargv[ctx->optind]; |
132 | 0 | ctx->place = EMSG; |
133 | 0 | ++ctx->optind; |
134 | 0 | } |
135 | 0 | return ctx->optopt; /* dump back option letter */ |
136 | 0 | } |