xref: /freebsd/contrib/ntp/sntp/libopts/stack.c (revision a466cc55)
1ea906c41SOllivier Robert 
22b15cb3dSCy Schubert /**
32b15cb3dSCy Schubert  * \file stack.c
4ea906c41SOllivier Robert  *
5ea906c41SOllivier Robert  *  This is a special option processing routine that will save the
6ea906c41SOllivier Robert  *  argument to an option in a FIFO queue.
72b15cb3dSCy Schubert  *
82b15cb3dSCy Schubert  * @addtogroup autoopts
92b15cb3dSCy Schubert  * @{
10ea906c41SOllivier Robert  */
11ea906c41SOllivier Robert /*
122b15cb3dSCy Schubert  *  This file is part of AutoOpts, a companion to AutoGen.
132b15cb3dSCy Schubert  *  AutoOpts is free software.
14*a466cc55SCy Schubert  *  AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
15ea906c41SOllivier Robert  *
162b15cb3dSCy Schubert  *  AutoOpts is available under any one of two licenses.  The license
172b15cb3dSCy Schubert  *  in use must be one of these two and the choice is under the control
182b15cb3dSCy Schubert  *  of the user of the license.
19ea906c41SOllivier Robert  *
202b15cb3dSCy Schubert  *   The GNU Lesser General Public License, version 3 or later
212b15cb3dSCy Schubert  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
22ea906c41SOllivier Robert  *
232b15cb3dSCy Schubert  *   The Modified Berkeley Software Distribution License
242b15cb3dSCy Schubert  *      See the file "COPYING.mbsd"
25ea906c41SOllivier Robert  *
262b15cb3dSCy Schubert  *  These files have the following sha256 sums:
27ea906c41SOllivier Robert  *
282b15cb3dSCy Schubert  *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
292b15cb3dSCy Schubert  *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
302b15cb3dSCy Schubert  *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
31ea906c41SOllivier Robert  */
32ea906c41SOllivier Robert 
33ea906c41SOllivier Robert #ifdef WITH_LIBREGEX
34ea906c41SOllivier Robert #  include REGEX_HEADER
35ea906c41SOllivier Robert #endif
36ea906c41SOllivier Robert 
37ea906c41SOllivier Robert /*=export_func  optionUnstackArg
38ea906c41SOllivier Robert  * private:
39ea906c41SOllivier Robert  *
40ea906c41SOllivier Robert  * what:  Remove option args from a stack
412b15cb3dSCy Schubert  * arg:   + tOptions * + opts + program options descriptor +
422b15cb3dSCy Schubert  * arg:   + tOptDesc * + od   + the descriptor for this arg +
43ea906c41SOllivier Robert  *
44ea906c41SOllivier Robert  * doc:
45ea906c41SOllivier Robert  *  Invoked for options that are equivalenced to stacked options.
46ea906c41SOllivier Robert =*/
47ea906c41SOllivier Robert void
optionUnstackArg(tOptions * opts,tOptDesc * od)482b15cb3dSCy Schubert optionUnstackArg(tOptions * opts, tOptDesc * od)
49ea906c41SOllivier Robert {
502b15cb3dSCy Schubert     tArgList * arg_list;
51ea906c41SOllivier Robert 
522b15cb3dSCy Schubert     if (INQUERY_CALL(opts, od))
532b15cb3dSCy Schubert         return;
542b15cb3dSCy Schubert 
552b15cb3dSCy Schubert     arg_list = (tArgList *)od->optCookie;
562b15cb3dSCy Schubert 
57ea906c41SOllivier Robert     /*
58ea906c41SOllivier Robert      *  IF we don't have any stacked options,
59ea906c41SOllivier Robert      *  THEN indicate that we don't have any of these options
60ea906c41SOllivier Robert      */
612b15cb3dSCy Schubert     if (arg_list == NULL) {
622b15cb3dSCy Schubert         od->fOptState &= OPTST_PERSISTENT_MASK;
632b15cb3dSCy Schubert         if ((od->fOptState & OPTST_INITENABLED) == 0)
642b15cb3dSCy Schubert             od->fOptState |= OPTST_DISABLED;
65ea906c41SOllivier Robert         return;
66ea906c41SOllivier Robert     }
67ea906c41SOllivier Robert 
68ea906c41SOllivier Robert #ifdef WITH_LIBREGEX
69ea906c41SOllivier Robert     {
70ea906c41SOllivier Robert         regex_t   re;
71ea906c41SOllivier Robert         int       i, ct, dIdx;
72ea906c41SOllivier Robert 
732b15cb3dSCy Schubert         if (regcomp(&re, od->optArg.argString, REG_NOSUB) != 0)
74ea906c41SOllivier Robert             return;
75ea906c41SOllivier Robert 
76ea906c41SOllivier Robert         /*
77ea906c41SOllivier Robert          *  search the list for the entry(s) to remove.  Entries that
78ea906c41SOllivier Robert          *  are removed are *not* copied into the result.  The source
79ea906c41SOllivier Robert          *  index is incremented every time.  The destination only when
80ea906c41SOllivier Robert          *  we are keeping a define.
81ea906c41SOllivier Robert          */
822b15cb3dSCy Schubert         for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) {
832b15cb3dSCy Schubert             char const * pzSrc = arg_list->apzArgs[ i ];
84ea906c41SOllivier Robert             char *       pzEq  = strchr(pzSrc, '=');
852b15cb3dSCy Schubert             int          res;
862b15cb3dSCy Schubert 
87ea906c41SOllivier Robert 
88ea906c41SOllivier Robert             if (pzEq != NULL)
89ea906c41SOllivier Robert                 *pzEq = NUL;
90ea906c41SOllivier Robert 
91ea906c41SOllivier Robert             res = regexec(&re, pzSrc, (size_t)0, NULL, 0);
92ea906c41SOllivier Robert             switch (res) {
93ea906c41SOllivier Robert             case 0:
94ea906c41SOllivier Robert                 /*
95ea906c41SOllivier Robert                  *  Remove this entry by reducing the in-use count
96ea906c41SOllivier Robert                  *  and *not* putting the string pointer back into
97ea906c41SOllivier Robert                  *  the list.
98ea906c41SOllivier Robert                  */
99ea906c41SOllivier Robert                 AGFREE(pzSrc);
1002b15cb3dSCy Schubert                 arg_list->useCt--;
101ea906c41SOllivier Robert                 break;
102ea906c41SOllivier Robert 
103ea906c41SOllivier Robert             default:
104ea906c41SOllivier Robert             case REG_NOMATCH:
105ea906c41SOllivier Robert                 if (pzEq != NULL)
106ea906c41SOllivier Robert                     *pzEq = '=';
107ea906c41SOllivier Robert 
108ea906c41SOllivier Robert                 /*
109ea906c41SOllivier Robert                  *  IF we have dropped an entry
110ea906c41SOllivier Robert                  *  THEN we have to move the current one.
111ea906c41SOllivier Robert                  */
112ea906c41SOllivier Robert                 if (dIdx != i)
1132b15cb3dSCy Schubert                     arg_list->apzArgs[ dIdx ] = pzSrc;
114ea906c41SOllivier Robert                 dIdx++;
115ea906c41SOllivier Robert             }
116ea906c41SOllivier Robert         }
117ea906c41SOllivier Robert 
118ea906c41SOllivier Robert         regfree(&re);
119ea906c41SOllivier Robert     }
120ea906c41SOllivier Robert #else  /* not WITH_LIBREGEX */
121ea906c41SOllivier Robert     {
122ea906c41SOllivier Robert         int i, ct, dIdx;
123ea906c41SOllivier Robert 
124ea906c41SOllivier Robert         /*
125ea906c41SOllivier Robert          *  search the list for the entry(s) to remove.  Entries that
126ea906c41SOllivier Robert          *  are removed are *not* copied into the result.  The source
127ea906c41SOllivier Robert          *  index is incremented every time.  The destination only when
128ea906c41SOllivier Robert          *  we are keeping a define.
129ea906c41SOllivier Robert          */
1302b15cb3dSCy Schubert         for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) {
1312b15cb3dSCy Schubert             const char * pzSrc = arg_list->apzArgs[ i ];
132ea906c41SOllivier Robert             char *       pzEq  = strchr(pzSrc, '=');
133ea906c41SOllivier Robert 
134ea906c41SOllivier Robert             if (pzEq != NULL)
135ea906c41SOllivier Robert                 *pzEq = NUL;
136ea906c41SOllivier Robert 
1372b15cb3dSCy Schubert             if (strcmp(pzSrc, od->optArg.argString) == 0) {
138ea906c41SOllivier Robert                 /*
139ea906c41SOllivier Robert                  *  Remove this entry by reducing the in-use count
140ea906c41SOllivier Robert                  *  and *not* putting the string pointer back into
141ea906c41SOllivier Robert                  *  the list.
142ea906c41SOllivier Robert                  */
143ea906c41SOllivier Robert                 AGFREE(pzSrc);
1442b15cb3dSCy Schubert                 arg_list->useCt--;
145ea906c41SOllivier Robert             } else {
146ea906c41SOllivier Robert                 if (pzEq != NULL)
147ea906c41SOllivier Robert                     *pzEq = '=';
148ea906c41SOllivier Robert 
149ea906c41SOllivier Robert                 /*
150ea906c41SOllivier Robert                  *  IF we have dropped an entry
151ea906c41SOllivier Robert                  *  THEN we have to move the current one.
152ea906c41SOllivier Robert                  */
153ea906c41SOllivier Robert                 if (dIdx != i)
1542b15cb3dSCy Schubert                     arg_list->apzArgs[ dIdx ] = pzSrc;
155ea906c41SOllivier Robert                 dIdx++;
156ea906c41SOllivier Robert             }
157ea906c41SOllivier Robert         }
158ea906c41SOllivier Robert     }
159ea906c41SOllivier Robert #endif /* WITH_LIBREGEX */
160ea906c41SOllivier Robert     /*
161ea906c41SOllivier Robert      *  IF we have unstacked everything,
162ea906c41SOllivier Robert      *  THEN indicate that we don't have any of these options
163ea906c41SOllivier Robert      */
1642b15cb3dSCy Schubert     if (arg_list->useCt == 0) {
1652b15cb3dSCy Schubert         od->fOptState &= OPTST_PERSISTENT_MASK;
1662b15cb3dSCy Schubert         if ((od->fOptState & OPTST_INITENABLED) == 0)
1672b15cb3dSCy Schubert             od->fOptState |= OPTST_DISABLED;
168276da39aSCy Schubert         AGFREE(arg_list);
1692b15cb3dSCy Schubert         od->optCookie = NULL;
170ea906c41SOllivier Robert     }
171ea906c41SOllivier Robert }
172ea906c41SOllivier Robert 
173ea906c41SOllivier Robert 
174ea906c41SOllivier Robert /*
175ea906c41SOllivier Robert  *  Put an entry into an argument list.  The first argument points to
176ea906c41SOllivier Robert  *  a pointer to the argument list structure.  It gets passed around
177ea906c41SOllivier Robert  *  as an opaque address.
178ea906c41SOllivier Robert  */
179*a466cc55SCy Schubert static void
addArgListEntry(void ** ppAL,void * entry)180ea906c41SOllivier Robert addArgListEntry(void ** ppAL, void * entry)
181ea906c41SOllivier Robert {
182ea906c41SOllivier Robert     tArgList * pAL = *(void **)ppAL;
183ea906c41SOllivier Robert 
184ea906c41SOllivier Robert     /*
185ea906c41SOllivier Robert      *  IF we have never allocated one of these,
186ea906c41SOllivier Robert      *  THEN allocate one now
187ea906c41SOllivier Robert      */
188ea906c41SOllivier Robert     if (pAL == NULL) {
189ea906c41SOllivier Robert         pAL = (tArgList *)AGALOC(sizeof(*pAL), "new option arg stack");
190ea906c41SOllivier Robert         if (pAL == NULL)
191ea906c41SOllivier Robert             return;
192ea906c41SOllivier Robert         pAL->useCt   = 0;
193ea906c41SOllivier Robert         pAL->allocCt = MIN_ARG_ALLOC_CT;
194276da39aSCy Schubert         *ppAL = VOIDP(pAL);
195ea906c41SOllivier Robert     }
196ea906c41SOllivier Robert 
197ea906c41SOllivier Robert     /*
198ea906c41SOllivier Robert      *  ELSE if we are out of room
199ea906c41SOllivier Robert      *  THEN make it bigger
200ea906c41SOllivier Robert      */
201ea906c41SOllivier Robert     else if (pAL->useCt >= pAL->allocCt) {
202ea906c41SOllivier Robert         size_t sz = sizeof(*pAL);
203ea906c41SOllivier Robert         pAL->allocCt += INCR_ARG_ALLOC_CT;
204ea906c41SOllivier Robert 
205ea906c41SOllivier Robert         /*
206ea906c41SOllivier Robert          *  The base structure contains space for MIN_ARG_ALLOC_CT
207ea906c41SOllivier Robert          *  pointers.  We subtract it off to find our augment size.
208ea906c41SOllivier Robert          */
2092b15cb3dSCy Schubert         sz += sizeof(char *) * ((size_t)pAL->allocCt - MIN_ARG_ALLOC_CT);
210276da39aSCy Schubert         pAL = (tArgList *)AGREALOC(VOIDP(pAL), sz, "expanded opt arg stack");
211ea906c41SOllivier Robert         if (pAL == NULL)
212ea906c41SOllivier Robert             return;
213276da39aSCy Schubert         *ppAL = VOIDP(pAL);
214ea906c41SOllivier Robert     }
215ea906c41SOllivier Robert 
216ea906c41SOllivier Robert     /*
217ea906c41SOllivier Robert      *  Insert the new argument into the list
218ea906c41SOllivier Robert      */
219ea906c41SOllivier Robert     pAL->apzArgs[ (pAL->useCt)++ ] = entry;
220ea906c41SOllivier Robert }
221ea906c41SOllivier Robert 
222ea906c41SOllivier Robert 
223ea906c41SOllivier Robert /*=export_func  optionStackArg
224ea906c41SOllivier Robert  * private:
225ea906c41SOllivier Robert  *
226ea906c41SOllivier Robert  * what:  put option args on a stack
2272b15cb3dSCy Schubert  * arg:   + tOptions * + opts + program options descriptor +
2282b15cb3dSCy Schubert  * arg:   + tOptDesc * + od   + the descriptor for this arg +
229ea906c41SOllivier Robert  *
230ea906c41SOllivier Robert  * doc:
231ea906c41SOllivier Robert  *  Keep an entry-ordered list of option arguments.
232ea906c41SOllivier Robert =*/
233ea906c41SOllivier Robert void
optionStackArg(tOptions * opts,tOptDesc * od)2342b15cb3dSCy Schubert optionStackArg(tOptions * opts, tOptDesc * od)
235ea906c41SOllivier Robert {
236ea906c41SOllivier Robert     char * pz;
237ea906c41SOllivier Robert 
2382b15cb3dSCy Schubert     if (INQUERY_CALL(opts, od))
239ea906c41SOllivier Robert         return;
240ea906c41SOllivier Robert 
2412b15cb3dSCy Schubert     if ((od->fOptState & OPTST_RESET) != 0) {
242276da39aSCy Schubert         tArgList * arg_list = od->optCookie;
2432b15cb3dSCy Schubert         int ix;
2442b15cb3dSCy Schubert         if (arg_list == NULL)
2452b15cb3dSCy Schubert             return;
2462b15cb3dSCy Schubert 
2472b15cb3dSCy Schubert         ix = arg_list->useCt;
2482b15cb3dSCy Schubert         while (--ix >= 0)
2492b15cb3dSCy Schubert             AGFREE(arg_list->apzArgs[ix]);
2502b15cb3dSCy Schubert         AGFREE(arg_list);
2512b15cb3dSCy Schubert 
2522b15cb3dSCy Schubert     } else {
2532b15cb3dSCy Schubert         if (od->optArg.argString == NULL)
2542b15cb3dSCy Schubert             return;
2552b15cb3dSCy Schubert 
2562b15cb3dSCy Schubert         AGDUPSTR(pz, od->optArg.argString, "stack arg");
257276da39aSCy Schubert         addArgListEntry(&(od->optCookie), VOIDP(pz));
258ea906c41SOllivier Robert     }
2592b15cb3dSCy Schubert }
2602b15cb3dSCy Schubert /** @}
2612b15cb3dSCy Schubert  *
262ea906c41SOllivier Robert  * Local Variables:
263ea906c41SOllivier Robert  * mode: C
264ea906c41SOllivier Robert  * c-file-style: "stroustrup"
265ea906c41SOllivier Robert  * indent-tabs-mode: nil
266ea906c41SOllivier Robert  * End:
267ea906c41SOllivier Robert  * end of autoopts/stack.c */
268