stack.c revision 280849
1181834Sroberto 2280849Scy/** 3280849Scy * \file stack.c 4181834Sroberto * 5181834Sroberto * This is a special option processing routine that will save the 6181834Sroberto * argument to an option in a FIFO queue. 7280849Scy * 8280849Scy * @addtogroup autoopts 9280849Scy * @{ 10181834Sroberto */ 11181834Sroberto/* 12280849Scy * This file is part of AutoOpts, a companion to AutoGen. 13280849Scy * AutoOpts is free software. 14280849Scy * AutoOpts is Copyright (C) 1992-2014 by Bruce Korb - all rights reserved 15181834Sroberto * 16280849Scy * AutoOpts is available under any one of two licenses. The license 17280849Scy * in use must be one of these two and the choice is under the control 18280849Scy * of the user of the license. 19181834Sroberto * 20280849Scy * The GNU Lesser General Public License, version 3 or later 21280849Scy * See the files "COPYING.lgplv3" and "COPYING.gplv3" 22181834Sroberto * 23280849Scy * The Modified Berkeley Software Distribution License 24280849Scy * See the file "COPYING.mbsd" 25181834Sroberto * 26280849Scy * These files have the following sha256 sums: 27181834Sroberto * 28280849Scy * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 29280849Scy * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 30280849Scy * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd 31181834Sroberto */ 32181834Sroberto 33181834Sroberto#ifdef WITH_LIBREGEX 34181834Sroberto# include REGEX_HEADER 35181834Sroberto#endif 36181834Sroberto 37181834Sroberto/*=export_func optionUnstackArg 38181834Sroberto * private: 39181834Sroberto * 40181834Sroberto * what: Remove option args from a stack 41280849Scy * arg: + tOptions* + opts + program options descriptor + 42280849Scy * arg: + tOptDesc* + od + the descriptor for this arg + 43181834Sroberto * 44181834Sroberto * doc: 45181834Sroberto * Invoked for options that are equivalenced to stacked options. 46181834Sroberto=*/ 47181834Srobertovoid 48280849ScyoptionUnstackArg(tOptions * opts, tOptDesc * od) 49181834Sroberto{ 50280849Scy tArgList * arg_list; 51181834Sroberto 52280849Scy if (INQUERY_CALL(opts, od)) 53280849Scy return; 54280849Scy 55280849Scy arg_list = (tArgList*)od->optCookie; 56280849Scy 57181834Sroberto /* 58181834Sroberto * IF we don't have any stacked options, 59181834Sroberto * THEN indicate that we don't have any of these options 60181834Sroberto */ 61280849Scy if (arg_list == NULL) { 62280849Scy od->fOptState &= OPTST_PERSISTENT_MASK; 63280849Scy if ((od->fOptState & OPTST_INITENABLED) == 0) 64280849Scy od->fOptState |= OPTST_DISABLED; 65181834Sroberto return; 66181834Sroberto } 67181834Sroberto 68181834Sroberto#ifdef WITH_LIBREGEX 69181834Sroberto { 70181834Sroberto regex_t re; 71181834Sroberto int i, ct, dIdx; 72181834Sroberto 73280849Scy if (regcomp(&re, od->optArg.argString, REG_NOSUB) != 0) 74181834Sroberto return; 75181834Sroberto 76181834Sroberto /* 77181834Sroberto * search the list for the entry(s) to remove. Entries that 78181834Sroberto * are removed are *not* copied into the result. The source 79181834Sroberto * index is incremented every time. The destination only when 80181834Sroberto * we are keeping a define. 81181834Sroberto */ 82280849Scy for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { 83280849Scy char const * pzSrc = arg_list->apzArgs[ i ]; 84280849Scy char * pzEq = strchr(pzSrc, '='); 85280849Scy int res; 86181834Sroberto 87280849Scy 88181834Sroberto if (pzEq != NULL) 89181834Sroberto *pzEq = NUL; 90181834Sroberto 91280849Scy res = regexec(&re, pzSrc, (size_t)0, NULL, 0); 92181834Sroberto switch (res) { 93181834Sroberto case 0: 94181834Sroberto /* 95181834Sroberto * Remove this entry by reducing the in-use count 96181834Sroberto * and *not* putting the string pointer back into 97181834Sroberto * the list. 98181834Sroberto */ 99181834Sroberto AGFREE(pzSrc); 100280849Scy arg_list->useCt--; 101181834Sroberto break; 102181834Sroberto 103181834Sroberto default: 104181834Sroberto case REG_NOMATCH: 105181834Sroberto if (pzEq != NULL) 106181834Sroberto *pzEq = '='; 107181834Sroberto 108181834Sroberto /* 109181834Sroberto * IF we have dropped an entry 110181834Sroberto * THEN we have to move the current one. 111181834Sroberto */ 112181834Sroberto if (dIdx != i) 113280849Scy arg_list->apzArgs[ dIdx ] = pzSrc; 114181834Sroberto dIdx++; 115181834Sroberto } 116181834Sroberto } 117181834Sroberto 118280849Scy regfree(&re); 119181834Sroberto } 120181834Sroberto#else /* not WITH_LIBREGEX */ 121181834Sroberto { 122181834Sroberto int i, ct, dIdx; 123181834Sroberto 124181834Sroberto /* 125181834Sroberto * search the list for the entry(s) to remove. Entries that 126181834Sroberto * are removed are *not* copied into the result. The source 127181834Sroberto * index is incremented every time. The destination only when 128181834Sroberto * we are keeping a define. 129181834Sroberto */ 130280849Scy for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { 131280849Scy const char * pzSrc = arg_list->apzArgs[ i ]; 132280849Scy char * pzEq = strchr(pzSrc, '='); 133181834Sroberto 134181834Sroberto if (pzEq != NULL) 135181834Sroberto *pzEq = NUL; 136181834Sroberto 137280849Scy if (strcmp(pzSrc, od->optArg.argString) == 0) { 138181834Sroberto /* 139181834Sroberto * Remove this entry by reducing the in-use count 140181834Sroberto * and *not* putting the string pointer back into 141181834Sroberto * the list. 142181834Sroberto */ 143181834Sroberto AGFREE(pzSrc); 144280849Scy arg_list->useCt--; 145181834Sroberto } else { 146181834Sroberto if (pzEq != NULL) 147181834Sroberto *pzEq = '='; 148181834Sroberto 149181834Sroberto /* 150181834Sroberto * IF we have dropped an entry 151181834Sroberto * THEN we have to move the current one. 152181834Sroberto */ 153181834Sroberto if (dIdx != i) 154280849Scy arg_list->apzArgs[ dIdx ] = pzSrc; 155181834Sroberto dIdx++; 156181834Sroberto } 157181834Sroberto } 158181834Sroberto } 159181834Sroberto#endif /* WITH_LIBREGEX */ 160181834Sroberto /* 161181834Sroberto * IF we have unstacked everything, 162181834Sroberto * THEN indicate that we don't have any of these options 163181834Sroberto */ 164280849Scy if (arg_list->useCt == 0) { 165280849Scy od->fOptState &= OPTST_PERSISTENT_MASK; 166280849Scy if ((od->fOptState & OPTST_INITENABLED) == 0) 167280849Scy od->fOptState |= OPTST_DISABLED; 168280849Scy AGFREE((void *)arg_list); 169280849Scy od->optCookie = NULL; 170181834Sroberto } 171181834Sroberto} 172181834Sroberto 173181834Sroberto 174181834Sroberto/* 175181834Sroberto * Put an entry into an argument list. The first argument points to 176181834Sroberto * a pointer to the argument list structure. It gets passed around 177181834Sroberto * as an opaque address. 178181834Sroberto */ 179181834SrobertoLOCAL void 180280849ScyaddArgListEntry(void ** ppAL, void * entry) 181181834Sroberto{ 182181834Sroberto tArgList* pAL = *(void**)ppAL; 183181834Sroberto 184181834Sroberto /* 185181834Sroberto * IF we have never allocated one of these, 186181834Sroberto * THEN allocate one now 187181834Sroberto */ 188181834Sroberto if (pAL == NULL) { 189280849Scy pAL = (tArgList*)AGALOC(sizeof(*pAL), "new option arg stack"); 190181834Sroberto if (pAL == NULL) 191181834Sroberto return; 192181834Sroberto pAL->useCt = 0; 193181834Sroberto pAL->allocCt = MIN_ARG_ALLOC_CT; 194181834Sroberto *ppAL = (void*)pAL; 195181834Sroberto } 196181834Sroberto 197181834Sroberto /* 198181834Sroberto * ELSE if we are out of room 199181834Sroberto * THEN make it bigger 200181834Sroberto */ 201181834Sroberto else if (pAL->useCt >= pAL->allocCt) { 202280849Scy size_t sz = sizeof(*pAL); 203181834Sroberto pAL->allocCt += INCR_ARG_ALLOC_CT; 204181834Sroberto 205181834Sroberto /* 206181834Sroberto * The base structure contains space for MIN_ARG_ALLOC_CT 207181834Sroberto * pointers. We subtract it off to find our augment size. 208181834Sroberto */ 209280849Scy sz += sizeof(char*) * ((size_t)pAL->allocCt - MIN_ARG_ALLOC_CT); 210280849Scy pAL = (tArgList*)AGREALOC((void*)pAL, sz, "expanded opt arg stack"); 211181834Sroberto if (pAL == NULL) 212181834Sroberto return; 213181834Sroberto *ppAL = (void*)pAL; 214181834Sroberto } 215181834Sroberto 216181834Sroberto /* 217181834Sroberto * Insert the new argument into the list 218181834Sroberto */ 219181834Sroberto pAL->apzArgs[ (pAL->useCt)++ ] = entry; 220181834Sroberto} 221181834Sroberto 222181834Sroberto 223181834Sroberto/*=export_func optionStackArg 224181834Sroberto * private: 225181834Sroberto * 226181834Sroberto * what: put option args on a stack 227280849Scy * arg: + tOptions* + opts + program options descriptor + 228280849Scy * arg: + tOptDesc* + od + the descriptor for this arg + 229181834Sroberto * 230181834Sroberto * doc: 231181834Sroberto * Keep an entry-ordered list of option arguments. 232181834Sroberto=*/ 233181834Srobertovoid 234280849ScyoptionStackArg(tOptions * opts, tOptDesc * od) 235181834Sroberto{ 236181834Sroberto char * pz; 237181834Sroberto 238280849Scy if (INQUERY_CALL(opts, od)) 239181834Sroberto return; 240181834Sroberto 241280849Scy if ((od->fOptState & OPTST_RESET) != 0) { 242280849Scy tArgList * arg_list = (void*)od->optCookie; 243280849Scy int ix; 244280849Scy if (arg_list == NULL) 245280849Scy return; 246280849Scy 247280849Scy ix = arg_list->useCt; 248280849Scy while (--ix >= 0) 249280849Scy AGFREE(arg_list->apzArgs[ix]); 250280849Scy AGFREE(arg_list); 251280849Scy 252280849Scy } else { 253280849Scy if (od->optArg.argString == NULL) 254280849Scy return; 255280849Scy 256280849Scy AGDUPSTR(pz, od->optArg.argString, "stack arg"); 257280849Scy addArgListEntry(&(od->optCookie), (void*)pz); 258280849Scy } 259181834Sroberto} 260280849Scy/** @} 261280849Scy * 262181834Sroberto * Local Variables: 263181834Sroberto * mode: C 264181834Sroberto * c-file-style: "stroustrup" 265181834Sroberto * indent-tabs-mode: nil 266181834Sroberto * End: 267181834Sroberto * end of autoopts/stack.c */ 268