1181834Sroberto 2285612Sdelphij/** 3285612Sdelphij * \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. 7285612Sdelphij * 8285612Sdelphij * @addtogroup autoopts 9285612Sdelphij * @{ 10181834Sroberto */ 11181834Sroberto/* 12285612Sdelphij * This file is part of AutoOpts, a companion to AutoGen. 13285612Sdelphij * AutoOpts is free software. 14285612Sdelphij * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved 15181834Sroberto * 16285612Sdelphij * AutoOpts is available under any one of two licenses. The license 17285612Sdelphij * in use must be one of these two and the choice is under the control 18285612Sdelphij * of the user of the license. 19181834Sroberto * 20285612Sdelphij * The GNU Lesser General Public License, version 3 or later 21285612Sdelphij * See the files "COPYING.lgplv3" and "COPYING.gplv3" 22181834Sroberto * 23285612Sdelphij * The Modified Berkeley Software Distribution License 24285612Sdelphij * See the file "COPYING.mbsd" 25181834Sroberto * 26285612Sdelphij * These files have the following sha256 sums: 27181834Sroberto * 28285612Sdelphij * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 29285612Sdelphij * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 30285612Sdelphij * 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 41285612Sdelphij * arg: + tOptions * + opts + program options descriptor + 42285612Sdelphij * arg: + tOptDesc * + od + the descriptor for this arg + 43181834Sroberto * 44181834Sroberto * doc: 45181834Sroberto * Invoked for options that are equivalenced to stacked options. 46181834Sroberto=*/ 47181834Srobertovoid 48285612SdelphijoptionUnstackArg(tOptions * opts, tOptDesc * od) 49181834Sroberto{ 50285612Sdelphij tArgList * arg_list; 51181834Sroberto 52285612Sdelphij if (INQUERY_CALL(opts, od)) 53285612Sdelphij return; 54285612Sdelphij 55285612Sdelphij arg_list = (tArgList *)od->optCookie; 56285612Sdelphij 57181834Sroberto /* 58181834Sroberto * IF we don't have any stacked options, 59181834Sroberto * THEN indicate that we don't have any of these options 60181834Sroberto */ 61285612Sdelphij if (arg_list == NULL) { 62285612Sdelphij od->fOptState &= OPTST_PERSISTENT_MASK; 63285612Sdelphij if ((od->fOptState & OPTST_INITENABLED) == 0) 64285612Sdelphij od->fOptState |= OPTST_DISABLED; 65181834Sroberto return; 66181834Sroberto } 67181834Sroberto 68181834Sroberto#ifdef WITH_LIBREGEX 69181834Sroberto { 70181834Sroberto regex_t re; 71181834Sroberto int i, ct, dIdx; 72181834Sroberto 73285612Sdelphij 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 */ 82285612Sdelphij for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { 83285612Sdelphij char const * pzSrc = arg_list->apzArgs[ i ]; 84285612Sdelphij char * pzEq = strchr(pzSrc, '='); 85285612Sdelphij int res; 86181834Sroberto 87285612Sdelphij 88181834Sroberto if (pzEq != NULL) 89181834Sroberto *pzEq = NUL; 90181834Sroberto 91285612Sdelphij 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); 100285612Sdelphij 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) 113285612Sdelphij arg_list->apzArgs[ dIdx ] = pzSrc; 114181834Sroberto dIdx++; 115181834Sroberto } 116181834Sroberto } 117181834Sroberto 118285612Sdelphij 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 */ 130285612Sdelphij for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { 131285612Sdelphij const char * pzSrc = arg_list->apzArgs[ i ]; 132285612Sdelphij char * pzEq = strchr(pzSrc, '='); 133181834Sroberto 134181834Sroberto if (pzEq != NULL) 135181834Sroberto *pzEq = NUL; 136181834Sroberto 137285612Sdelphij 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); 144285612Sdelphij 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) 154285612Sdelphij 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 */ 164285612Sdelphij if (arg_list->useCt == 0) { 165285612Sdelphij od->fOptState &= OPTST_PERSISTENT_MASK; 166285612Sdelphij if ((od->fOptState & OPTST_INITENABLED) == 0) 167285612Sdelphij od->fOptState |= OPTST_DISABLED; 168285612Sdelphij AGFREE(arg_list); 169285612Sdelphij 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 180285612SdelphijaddArgListEntry(void ** ppAL, void * entry) 181181834Sroberto{ 182285612Sdelphij 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) { 189285612Sdelphij 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; 194285612Sdelphij *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) { 202285612Sdelphij 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 */ 209285612Sdelphij sz += sizeof(char *) * ((size_t)pAL->allocCt - MIN_ARG_ALLOC_CT); 210285612Sdelphij pAL = (tArgList *)AGREALOC(VOIDP(pAL), sz, "expanded opt arg stack"); 211181834Sroberto if (pAL == NULL) 212181834Sroberto return; 213285612Sdelphij *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 227285612Sdelphij * arg: + tOptions * + opts + program options descriptor + 228285612Sdelphij * arg: + tOptDesc * + od + the descriptor for this arg + 229181834Sroberto * 230181834Sroberto * doc: 231181834Sroberto * Keep an entry-ordered list of option arguments. 232181834Sroberto=*/ 233181834Srobertovoid 234285612SdelphijoptionStackArg(tOptions * opts, tOptDesc * od) 235181834Sroberto{ 236181834Sroberto char * pz; 237181834Sroberto 238285612Sdelphij if (INQUERY_CALL(opts, od)) 239181834Sroberto return; 240181834Sroberto 241285612Sdelphij if ((od->fOptState & OPTST_RESET) != 0) { 242285612Sdelphij tArgList * arg_list = od->optCookie; 243285612Sdelphij int ix; 244285612Sdelphij if (arg_list == NULL) 245285612Sdelphij return; 246285612Sdelphij 247285612Sdelphij ix = arg_list->useCt; 248285612Sdelphij while (--ix >= 0) 249285612Sdelphij AGFREE(arg_list->apzArgs[ix]); 250285612Sdelphij AGFREE(arg_list); 251285612Sdelphij 252285612Sdelphij } else { 253285612Sdelphij if (od->optArg.argString == NULL) 254285612Sdelphij return; 255285612Sdelphij 256285612Sdelphij AGDUPSTR(pz, od->optArg.argString, "stack arg"); 257285612Sdelphij addArgListEntry(&(od->optCookie), VOIDP(pz)); 258285612Sdelphij } 259181834Sroberto} 260285612Sdelphij/** @} 261285612Sdelphij * 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