/src/ntp-dev/sntp/libopts/stack.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /** |
3 | | * \file stack.c |
4 | | * |
5 | | * This is a special option processing routine that will save the |
6 | | * argument to an option in a FIFO queue. |
7 | | * |
8 | | * @addtogroup autoopts |
9 | | * @{ |
10 | | */ |
11 | | /* |
12 | | * This file is part of AutoOpts, a companion to AutoGen. |
13 | | * AutoOpts is free software. |
14 | | * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved |
15 | | * |
16 | | * AutoOpts is available under any one of two licenses. The license |
17 | | * in use must be one of these two and the choice is under the control |
18 | | * of the user of the license. |
19 | | * |
20 | | * The GNU Lesser General Public License, version 3 or later |
21 | | * See the files "COPYING.lgplv3" and "COPYING.gplv3" |
22 | | * |
23 | | * The Modified Berkeley Software Distribution License |
24 | | * See the file "COPYING.mbsd" |
25 | | * |
26 | | * These files have the following sha256 sums: |
27 | | * |
28 | | * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 |
29 | | * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 |
30 | | * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd |
31 | | */ |
32 | | |
33 | | #ifdef WITH_LIBREGEX |
34 | | # include REGEX_HEADER |
35 | | #endif |
36 | | |
37 | | /*=export_func optionUnstackArg |
38 | | * private: |
39 | | * |
40 | | * what: Remove option args from a stack |
41 | | * arg: + tOptions * + opts + program options descriptor + |
42 | | * arg: + tOptDesc * + od + the descriptor for this arg + |
43 | | * |
44 | | * doc: |
45 | | * Invoked for options that are equivalenced to stacked options. |
46 | | =*/ |
47 | | void |
48 | | optionUnstackArg(tOptions * opts, tOptDesc * od) |
49 | 0 | { |
50 | 0 | tArgList * arg_list; |
51 | |
|
52 | 0 | if (INQUERY_CALL(opts, od)) |
53 | 0 | return; |
54 | | |
55 | 0 | arg_list = (tArgList *)od->optCookie; |
56 | | |
57 | | /* |
58 | | * IF we don't have any stacked options, |
59 | | * THEN indicate that we don't have any of these options |
60 | | */ |
61 | 0 | if (arg_list == NULL) { |
62 | 0 | od->fOptState &= OPTST_PERSISTENT_MASK; |
63 | 0 | if ((od->fOptState & OPTST_INITENABLED) == 0) |
64 | 0 | od->fOptState |= OPTST_DISABLED; |
65 | 0 | return; |
66 | 0 | } |
67 | | |
68 | 0 | #ifdef WITH_LIBREGEX |
69 | 0 | { |
70 | 0 | regex_t re; |
71 | 0 | int i, ct, dIdx; |
72 | |
|
73 | 0 | if (regcomp(&re, od->optArg.argString, REG_NOSUB) != 0) |
74 | 0 | return; |
75 | | |
76 | | /* |
77 | | * search the list for the entry(s) to remove. Entries that |
78 | | * are removed are *not* copied into the result. The source |
79 | | * index is incremented every time. The destination only when |
80 | | * we are keeping a define. |
81 | | */ |
82 | 0 | for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { |
83 | 0 | char const * pzSrc = arg_list->apzArgs[ i ]; |
84 | 0 | char * pzEq = strchr(pzSrc, '='); |
85 | 0 | int res; |
86 | | |
87 | |
|
88 | 0 | if (pzEq != NULL) |
89 | 0 | *pzEq = NUL; |
90 | |
|
91 | 0 | res = regexec(&re, pzSrc, (size_t)0, NULL, 0); |
92 | 0 | switch (res) { |
93 | 0 | case 0: |
94 | | /* |
95 | | * Remove this entry by reducing the in-use count |
96 | | * and *not* putting the string pointer back into |
97 | | * the list. |
98 | | */ |
99 | 0 | AGFREE(pzSrc); |
100 | 0 | arg_list->useCt--; |
101 | 0 | break; |
102 | | |
103 | 0 | default: |
104 | 0 | case REG_NOMATCH: |
105 | 0 | if (pzEq != NULL) |
106 | 0 | *pzEq = '='; |
107 | | |
108 | | /* |
109 | | * IF we have dropped an entry |
110 | | * THEN we have to move the current one. |
111 | | */ |
112 | 0 | if (dIdx != i) |
113 | 0 | arg_list->apzArgs[ dIdx ] = pzSrc; |
114 | 0 | dIdx++; |
115 | 0 | } |
116 | 0 | } |
117 | | |
118 | 0 | regfree(&re); |
119 | 0 | } |
120 | | #else /* not WITH_LIBREGEX */ |
121 | | { |
122 | | int i, ct, dIdx; |
123 | | |
124 | | /* |
125 | | * search the list for the entry(s) to remove. Entries that |
126 | | * are removed are *not* copied into the result. The source |
127 | | * index is incremented every time. The destination only when |
128 | | * we are keeping a define. |
129 | | */ |
130 | | for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { |
131 | | const char * pzSrc = arg_list->apzArgs[ i ]; |
132 | | char * pzEq = strchr(pzSrc, '='); |
133 | | |
134 | | if (pzEq != NULL) |
135 | | *pzEq = NUL; |
136 | | |
137 | | if (strcmp(pzSrc, od->optArg.argString) == 0) { |
138 | | /* |
139 | | * Remove this entry by reducing the in-use count |
140 | | * and *not* putting the string pointer back into |
141 | | * the list. |
142 | | */ |
143 | | AGFREE(pzSrc); |
144 | | arg_list->useCt--; |
145 | | } else { |
146 | | if (pzEq != NULL) |
147 | | *pzEq = '='; |
148 | | |
149 | | /* |
150 | | * IF we have dropped an entry |
151 | | * THEN we have to move the current one. |
152 | | */ |
153 | | if (dIdx != i) |
154 | | arg_list->apzArgs[ dIdx ] = pzSrc; |
155 | | dIdx++; |
156 | | } |
157 | | } |
158 | | } |
159 | | #endif /* WITH_LIBREGEX */ |
160 | | /* |
161 | | * IF we have unstacked everything, |
162 | | * THEN indicate that we don't have any of these options |
163 | | */ |
164 | 0 | if (arg_list->useCt == 0) { |
165 | 0 | od->fOptState &= OPTST_PERSISTENT_MASK; |
166 | 0 | if ((od->fOptState & OPTST_INITENABLED) == 0) |
167 | 0 | od->fOptState |= OPTST_DISABLED; |
168 | 0 | AGFREE(arg_list); |
169 | 0 | od->optCookie = NULL; |
170 | 0 | } |
171 | 0 | } |
172 | | |
173 | | |
174 | | /* |
175 | | * Put an entry into an argument list. The first argument points to |
176 | | * a pointer to the argument list structure. It gets passed around |
177 | | * as an opaque address. |
178 | | */ |
179 | | LOCAL void |
180 | | addArgListEntry(void ** ppAL, void * entry) |
181 | 0 | { |
182 | 0 | tArgList * pAL = *(void **)ppAL; |
183 | | |
184 | | /* |
185 | | * IF we have never allocated one of these, |
186 | | * THEN allocate one now |
187 | | */ |
188 | 0 | if (pAL == NULL) { |
189 | 0 | pAL = (tArgList *)AGALOC(sizeof(*pAL), "new option arg stack"); |
190 | 0 | if (pAL == NULL) |
191 | 0 | return; |
192 | 0 | pAL->useCt = 0; |
193 | 0 | pAL->allocCt = MIN_ARG_ALLOC_CT; |
194 | 0 | *ppAL = VOIDP(pAL); |
195 | 0 | } |
196 | | |
197 | | /* |
198 | | * ELSE if we are out of room |
199 | | * THEN make it bigger |
200 | | */ |
201 | 0 | else if (pAL->useCt >= pAL->allocCt) { |
202 | 0 | size_t sz = sizeof(*pAL); |
203 | 0 | pAL->allocCt += INCR_ARG_ALLOC_CT; |
204 | | |
205 | | /* |
206 | | * The base structure contains space for MIN_ARG_ALLOC_CT |
207 | | * pointers. We subtract it off to find our augment size. |
208 | | */ |
209 | 0 | sz += sizeof(char *) * ((size_t)pAL->allocCt - MIN_ARG_ALLOC_CT); |
210 | 0 | pAL = (tArgList *)AGREALOC(VOIDP(pAL), sz, "expanded opt arg stack"); |
211 | 0 | if (pAL == NULL) |
212 | 0 | return; |
213 | 0 | *ppAL = VOIDP(pAL); |
214 | 0 | } |
215 | | |
216 | | /* |
217 | | * Insert the new argument into the list |
218 | | */ |
219 | 0 | pAL->apzArgs[ (pAL->useCt)++ ] = entry; |
220 | 0 | } |
221 | | |
222 | | |
223 | | /*=export_func optionStackArg |
224 | | * private: |
225 | | * |
226 | | * what: put option args on a stack |
227 | | * arg: + tOptions * + opts + program options descriptor + |
228 | | * arg: + tOptDesc * + od + the descriptor for this arg + |
229 | | * |
230 | | * doc: |
231 | | * Keep an entry-ordered list of option arguments. |
232 | | =*/ |
233 | | void |
234 | | optionStackArg(tOptions * opts, tOptDesc * od) |
235 | 0 | { |
236 | 0 | char * pz; |
237 | |
|
238 | 0 | if (INQUERY_CALL(opts, od)) |
239 | 0 | return; |
240 | | |
241 | 0 | if ((od->fOptState & OPTST_RESET) != 0) { |
242 | 0 | tArgList * arg_list = od->optCookie; |
243 | 0 | int ix; |
244 | 0 | if (arg_list == NULL) |
245 | 0 | return; |
246 | | |
247 | 0 | ix = arg_list->useCt; |
248 | 0 | while (--ix >= 0) |
249 | 0 | AGFREE(arg_list->apzArgs[ix]); |
250 | 0 | AGFREE(arg_list); |
251 | |
|
252 | 0 | } else { |
253 | 0 | if (od->optArg.argString == NULL) |
254 | 0 | return; |
255 | | |
256 | 0 | AGDUPSTR(pz, od->optArg.argString, "stack arg"); |
257 | 0 | addArgListEntry(&(od->optCookie), VOIDP(pz)); |
258 | 0 | } |
259 | 0 | } |
260 | | /** @} |
261 | | * |
262 | | * Local Variables: |
263 | | * mode: C |
264 | | * c-file-style: "stroustrup" |
265 | | * indent-tabs-mode: nil |
266 | | * End: |
267 | | * end of autoopts/stack.c */ |