Line data Source code
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 : #define BADCH (int)'?'
43 : #define BADARG (int)':'
44 : #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 5626 : pg_getopt_start(pg_getopt_ctx *ctx, int nargc, char *const *nargv, const char *ostr)
55 : {
56 5626 : ctx->nargc = nargc;
57 5626 : ctx->nargv = nargv;
58 5626 : ctx->ostr = ostr;
59 :
60 5626 : ctx->optind = 1;
61 5626 : ctx->optarg = NULL;
62 5626 : ctx->opterr = 1; /* Caller may clear this after the call */
63 5626 : ctx->optopt = 0;
64 :
65 5626 : ctx->place = EMSG; /* option letter processing */
66 5626 : }
67 :
68 : /*
69 : * Parse next option in argc/argv argument vector
70 : */
71 : int
72 15493 : pg_getopt_next(pg_getopt_ctx *ctx)
73 : {
74 : const char *oli; /* option letter list index */
75 :
76 15493 : if (!*ctx->place)
77 : { /* update scanning pointer */
78 15493 : if (ctx->optind >= ctx->nargc || *(ctx->place = ctx->nargv[ctx->optind]) != '-')
79 : {
80 5598 : ctx->place = EMSG;
81 5598 : return -1;
82 : }
83 9895 : if (ctx->place[1] && *++ctx->place == '-' && ctx->place[1] == '\0')
84 : { /* found "--" */
85 0 : ++ctx->optind;
86 0 : ctx->place = EMSG;
87 0 : return -1;
88 : }
89 : } /* option letter okay? */
90 9895 : if ((ctx->optopt = (int) *ctx->place++) == (int) ':' ||
91 9895 : !(oli = strchr(ctx->ostr, ctx->optopt)))
92 : {
93 : /*
94 : * if the user didn't specify '-' as an option, assume it means -1.
95 : */
96 0 : if (ctx->optopt == (int) '-')
97 : {
98 0 : ctx->place = EMSG;
99 0 : return -1;
100 : }
101 0 : if (!*ctx->place)
102 0 : ++ctx->optind;
103 0 : if (ctx->opterr && *ctx->ostr != ':')
104 0 : (void) fprintf(stderr,
105 : "illegal option -- %c\n", ctx->optopt);
106 0 : return BADCH;
107 : }
108 9895 : if (*++oli != ':')
109 : { /* don't need argument */
110 591 : ctx->optarg = NULL;
111 591 : if (!*ctx->place)
112 591 : ++ctx->optind;
113 : }
114 : else
115 : { /* need an argument */
116 9304 : if (*ctx->place) /* no white space */
117 881 : ctx->optarg = ctx->place;
118 8423 : else if (ctx->nargc <= ++ctx->optind)
119 : { /* 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 : "option requires an argument -- %c\n",
126 : ctx->optopt);
127 0 : return BADCH;
128 : }
129 : else
130 : /* white space */
131 8423 : ctx->optarg = ctx->nargv[ctx->optind];
132 9304 : ctx->place = EMSG;
133 9304 : ++ctx->optind;
134 : }
135 9895 : return ctx->optopt; /* dump back option letter */
136 : }
|