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