1181834Sroberto 2290000Sglebius/** 3290000Sglebius * \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. 7290000Sglebius * 8290000Sglebius * @addtogroup autoopts 9290000Sglebius * @{ 10181834Sroberto */ 11181834Sroberto/* 12290000Sglebius * This file is part of AutoOpts, a companion to AutoGen. 13290000Sglebius * AutoOpts is free software. 14290000Sglebius * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved 15181834Sroberto * 16290000Sglebius * AutoOpts is available under any one of two licenses. The license 17290000Sglebius * in use must be one of these two and the choice is under the control 18290000Sglebius * of the user of the license. 19181834Sroberto * 20290000Sglebius * The GNU Lesser General Public License, version 3 or later 21290000Sglebius * See the files "COPYING.lgplv3" and "COPYING.gplv3" 22181834Sroberto * 23290000Sglebius * The Modified Berkeley Software Distribution License 24290000Sglebius * See the file "COPYING.mbsd" 25181834Sroberto * 26290000Sglebius * These files have the following sha256 sums: 27181834Sroberto * 28290000Sglebius * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 29290000Sglebius * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 30290000Sglebius * 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 41290000Sglebius * arg: + tOptions * + opts + program options descriptor + 42290000Sglebius * arg: + tOptDesc * + od + the descriptor for this arg + 43181834Sroberto * 44181834Sroberto * doc: 45181834Sroberto * Invoked for options that are equivalenced to stacked options. 46181834Sroberto=*/ 47181834Srobertovoid 48290000SglebiusoptionUnstackArg(tOptions * opts, tOptDesc * od) 49181834Sroberto{ 50290000Sglebius tArgList * arg_list; 51181834Sroberto 52290000Sglebius if (INQUERY_CALL(opts, od)) 53290000Sglebius return; 54290000Sglebius 55290000Sglebius arg_list = (tArgList *)od->optCookie; 56290000Sglebius 57181834Sroberto /* 58181834Sroberto * IF we don't have any stacked options, 59181834Sroberto * THEN indicate that we don't have any of these options 60181834Sroberto */ 61290000Sglebius if (arg_list == NULL) { 62290000Sglebius od->fOptState &= OPTST_PERSISTENT_MASK; 63290000Sglebius if ((od->fOptState & OPTST_INITENABLED) == 0) 64290000Sglebius od->fOptState |= OPTST_DISABLED; 65181834Sroberto return; 66181834Sroberto } 67181834Sroberto 68181834Sroberto#ifdef WITH_LIBREGEX 69181834Sroberto { 70181834Sroberto regex_t re; 71181834Sroberto int i, ct, dIdx; 72181834Sroberto 73290000Sglebius 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 */ 82290000Sglebius for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { 83290000Sglebius char const * pzSrc = arg_list->apzArgs[ i ]; 84290000Sglebius char * pzEq = strchr(pzSrc, '='); 85290000Sglebius int res; 86181834Sroberto 87290000Sglebius 88181834Sroberto if (pzEq != NULL) 89181834Sroberto *pzEq = NUL; 90181834Sroberto 91290000Sglebius 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); 100290000Sglebius 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) 113290000Sglebius arg_list->apzArgs[ dIdx ] = pzSrc; 114181834Sroberto dIdx++; 115181834Sroberto } 116181834Sroberto } 117181834Sroberto 118290000Sglebius 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 */ 130290000Sglebius for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { 131290000Sglebius const char * pzSrc = arg_list->apzArgs[ i ]; 132290000Sglebius char * pzEq = strchr(pzSrc, '='); 133181834Sroberto 134181834Sroberto if (pzEq != NULL) 135181834Sroberto *pzEq = NUL; 136181834Sroberto 137290000Sglebius 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); 144290000Sglebius 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) 154290000Sglebius 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 */ 164290000Sglebius if (arg_list->useCt == 0) { 165290000Sglebius od->fOptState &= OPTST_PERSISTENT_MASK; 166290000Sglebius if ((od->fOptState & OPTST_INITENABLED) == 0) 167290000Sglebius od->fOptState |= OPTST_DISABLED; 168290000Sglebius AGFREE(arg_list); 169290000Sglebius 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 180290000SglebiusaddArgListEntry(void ** ppAL, void * entry) 181181834Sroberto{ 182290000Sglebius 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) { 189290000Sglebius 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; 194290000Sglebius *ppAL = VOIDP(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) { 202290000Sglebius 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 */ 209290000Sglebius sz += sizeof(char *) * ((size_t)pAL->allocCt - MIN_ARG_ALLOC_CT); 210290000Sglebius pAL = (tArgList *)AGREALOC(VOIDP(pAL), sz, "expanded opt arg stack"); 211181834Sroberto if (pAL == NULL) 212181834Sroberto return; 213290000Sglebius *ppAL = VOIDP(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 227290000Sglebius * arg: + tOptions * + opts + program options descriptor + 228290000Sglebius * arg: + tOptDesc * + od + the descriptor for this arg + 229181834Sroberto * 230181834Sroberto * doc: 231181834Sroberto * Keep an entry-ordered list of option arguments. 232181834Sroberto=*/ 233181834Srobertovoid 234290000SglebiusoptionStackArg(tOptions * opts, tOptDesc * od) 235181834Sroberto{ 236181834Sroberto char * pz; 237181834Sroberto 238290000Sglebius if (INQUERY_CALL(opts, od)) 239181834Sroberto return; 240181834Sroberto 241290000Sglebius if ((od->fOptState & OPTST_RESET) != 0) { 242290000Sglebius tArgList * arg_list = od->optCookie; 243290000Sglebius int ix; 244290000Sglebius if (arg_list == NULL) 245290000Sglebius return; 246290000Sglebius 247290000Sglebius ix = arg_list->useCt; 248290000Sglebius while (--ix >= 0) 249290000Sglebius AGFREE(arg_list->apzArgs[ix]); 250290000Sglebius AGFREE(arg_list); 251290000Sglebius 252290000Sglebius } else { 253290000Sglebius if (od->optArg.argString == NULL) 254290000Sglebius return; 255290000Sglebius 256290000Sglebius AGDUPSTR(pz, od->optArg.argString, "stack arg"); 257290000Sglebius addArgListEntry(&(od->optCookie), VOIDP(pz)); 258290000Sglebius } 259181834Sroberto} 260290000Sglebius/** @} 261290000Sglebius * 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