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