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