1 2/* 3 * stack.c 4 * $Id: 9d4a7c1c6ae364a6134dc5ff01f58f08b52f1a16 $ 5 * Time-stamp: "2008-07-30 16:56:32 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-2009 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=*/ 45void 46optionUnstackArg( 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 */ 178LOCAL void 179addArgListEntry( 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=*/ 232void 233optionStackArg( 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 */ 265