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