1ea906c41SOllivier Robert 2ea906c41SOllivier Robert /* 3ea906c41SOllivier Robert * restore.c $Id: restore.c,v 4.10 2007/02/04 17:44:12 bkorb Exp $ 4ea906c41SOllivier Robert * Time-stamp: "2007-01-13 14:13:17 bkorb" 5ea906c41SOllivier Robert * 6ea906c41SOllivier Robert * This module's routines will save the current option state to memory 7ea906c41SOllivier Robert * and restore it. If saved prior to the initial optionProcess call, 8ea906c41SOllivier Robert * then the initial state will be restored. 9ea906c41SOllivier Robert */ 10ea906c41SOllivier Robert 11ea906c41SOllivier Robert /* 12ea906c41SOllivier Robert * Automated Options copyright 1992-2007 Bruce Korb 13ea906c41SOllivier Robert * 14ea906c41SOllivier Robert * Automated Options is free software. 15ea906c41SOllivier Robert * You may redistribute it and/or modify it under the terms of the 16ea906c41SOllivier Robert * GNU General Public License, as published by the Free Software 17ea906c41SOllivier Robert * Foundation; either version 2, or (at your option) any later version. 18ea906c41SOllivier Robert * 19ea906c41SOllivier Robert * Automated Options is distributed in the hope that it will be useful, 20ea906c41SOllivier Robert * but WITHOUT ANY WARRANTY; without even the implied warranty of 21ea906c41SOllivier Robert * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22ea906c41SOllivier Robert * GNU General Public License for more details. 23ea906c41SOllivier Robert * 24ea906c41SOllivier Robert * You should have received a copy of the GNU General Public License 25ea906c41SOllivier Robert * along with Automated Options. See the file "COPYING". If not, 26ea906c41SOllivier Robert * write to: The Free Software Foundation, Inc., 27ea906c41SOllivier Robert * 51 Franklin Street, Fifth Floor, 28ea906c41SOllivier Robert * Boston, MA 02110-1301, USA. 29ea906c41SOllivier Robert * 30ea906c41SOllivier Robert * As a special exception, Bruce Korb gives permission for additional 31ea906c41SOllivier Robert * uses of the text contained in his release of AutoOpts. 32ea906c41SOllivier Robert * 33ea906c41SOllivier Robert * The exception is that, if you link the AutoOpts library with other 34ea906c41SOllivier Robert * files to produce an executable, this does not by itself cause the 35ea906c41SOllivier Robert * resulting executable to be covered by the GNU General Public License. 36ea906c41SOllivier Robert * Your use of that executable is in no way restricted on account of 37ea906c41SOllivier Robert * linking the AutoOpts library code into it. 38ea906c41SOllivier Robert * 39ea906c41SOllivier Robert * This exception does not however invalidate any other reasons why 40ea906c41SOllivier Robert * the executable file might be covered by the GNU General Public License. 41ea906c41SOllivier Robert * 42ea906c41SOllivier Robert * This exception applies only to the code released by Bruce Korb under 43ea906c41SOllivier Robert * the name AutoOpts. If you copy code from other sources under the 44ea906c41SOllivier Robert * General Public License into a copy of AutoOpts, as the General Public 45ea906c41SOllivier Robert * License permits, the exception does not apply to the code that you add 46ea906c41SOllivier Robert * in this way. To avoid misleading anyone as to the status of such 47ea906c41SOllivier Robert * modified files, you must delete this exception notice from them. 48ea906c41SOllivier Robert * 49ea906c41SOllivier Robert * If you write modifications of your own for AutoOpts, it is your choice 50ea906c41SOllivier Robert * whether to permit this exception to apply to your modifications. 51ea906c41SOllivier Robert * If you do not wish that, delete this exception notice. 52ea906c41SOllivier Robert */ 53ea906c41SOllivier Robert 54ea906c41SOllivier Robert /* 55ea906c41SOllivier Robert * optionFixupSavedOpts Really, it just wipes out option state for 56ea906c41SOllivier Robert * options that are troublesome to copy. viz., stacked strings and 57ea906c41SOllivier Robert * hierarcicaly valued option args. We do duplicate string args that 58ea906c41SOllivier Robert * have been marked as allocated though. 59ea906c41SOllivier Robert */ 60ea906c41SOllivier Robert static void 61ea906c41SOllivier Robert fixupSavedOptionArgs(tOptions* pOpts) 62ea906c41SOllivier Robert { 63ea906c41SOllivier Robert tOptions* p = pOpts->pSavedState; 64ea906c41SOllivier Robert tOptDesc* pOD = pOpts->pOptDesc; 65ea906c41SOllivier Robert int ct = pOpts->optCt; 66ea906c41SOllivier Robert 67ea906c41SOllivier Robert /* 68ea906c41SOllivier Robert * Make sure that allocated stuff is only referenced in the 69ea906c41SOllivier Robert * archived copy of the data. 70ea906c41SOllivier Robert */ 71ea906c41SOllivier Robert for (; ct-- > 0; pOD++) { 72ea906c41SOllivier Robert switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { 73ea906c41SOllivier Robert case OPARG_TYPE_STRING: 74ea906c41SOllivier Robert if (pOD->fOptState & OPTST_STACKED) { 75ea906c41SOllivier Robert tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc); 76ea906c41SOllivier Robert q->optCookie = NULL; 77ea906c41SOllivier Robert } 78ea906c41SOllivier Robert if (pOD->fOptState & OPTST_ALLOC_ARG) { 79ea906c41SOllivier Robert tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc); 80ea906c41SOllivier Robert AGDUPSTR(q->optArg.argString, pOD->optArg.argString, "arg"); 81ea906c41SOllivier Robert } 82ea906c41SOllivier Robert break; 83ea906c41SOllivier Robert 84ea906c41SOllivier Robert case OPARG_TYPE_HIERARCHY: 85ea906c41SOllivier Robert { 86ea906c41SOllivier Robert tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc); 87ea906c41SOllivier Robert q->optCookie = NULL; 88ea906c41SOllivier Robert } 89ea906c41SOllivier Robert } 90ea906c41SOllivier Robert } 91ea906c41SOllivier Robert } 92ea906c41SOllivier Robert 93ea906c41SOllivier Robert /*=export_func optionSaveState 94ea906c41SOllivier Robert * 95ea906c41SOllivier Robert * what: saves the option state to memory 96ea906c41SOllivier Robert * arg: tOptions*, pOpts, program options descriptor 97ea906c41SOllivier Robert * 98ea906c41SOllivier Robert * doc: 99ea906c41SOllivier Robert * 100ea906c41SOllivier Robert * This routine will allocate enough memory to save the current option 101ea906c41SOllivier Robert * processing state. If this routine has been called before, that memory 102ea906c41SOllivier Robert * will be reused. You may only save one copy of the option state. This 103ea906c41SOllivier Robert * routine may be called before optionProcess(3AO). If you do call it 104ea906c41SOllivier Robert * before the first call to optionProcess, then you may also change the 105ea906c41SOllivier Robert * contents of argc/argv after you call optionRestore(3AO) 106ea906c41SOllivier Robert * 107ea906c41SOllivier Robert * In fact, more strongly put: it is safest to only use this function 108ea906c41SOllivier Robert * before having processed any options. In particular, the saving and 109ea906c41SOllivier Robert * restoring of stacked string arguments and hierarchical values is 110ea906c41SOllivier Robert * disabled. The values are not saved. 111ea906c41SOllivier Robert * 112ea906c41SOllivier Robert * err: If it fails to allocate the memory, 113ea906c41SOllivier Robert * it will print a message to stderr and exit. 114ea906c41SOllivier Robert * Otherwise, it will always succeed. 115ea906c41SOllivier Robert =*/ 116ea906c41SOllivier Robert void 117ea906c41SOllivier Robert optionSaveState(tOptions* pOpts) 118ea906c41SOllivier Robert { 119ea906c41SOllivier Robert tOptions* p = (tOptions*)pOpts->pSavedState; 120ea906c41SOllivier Robert 121ea906c41SOllivier Robert if (p == NULL) { 122ea906c41SOllivier Robert size_t sz = sizeof( *pOpts ) + (pOpts->optCt * sizeof( tOptDesc )); 123ea906c41SOllivier Robert p = AGALOC( sz, "saved option state" ); 124ea906c41SOllivier Robert if (p == NULL) { 125ea906c41SOllivier Robert tCC* pzName = pOpts->pzProgName; 126ea906c41SOllivier Robert if (pzName == NULL) { 127ea906c41SOllivier Robert pzName = pOpts->pzPROGNAME; 128ea906c41SOllivier Robert if (pzName == NULL) 129ea906c41SOllivier Robert pzName = zNil; 130ea906c41SOllivier Robert } 131ea906c41SOllivier Robert fprintf( stderr, zCantSave, pzName, sz ); 132ea906c41SOllivier Robert exit( EXIT_FAILURE ); 133ea906c41SOllivier Robert } 134ea906c41SOllivier Robert 135ea906c41SOllivier Robert pOpts->pSavedState = p; 136ea906c41SOllivier Robert } 137ea906c41SOllivier Robert 138ea906c41SOllivier Robert memcpy( p, pOpts, sizeof( *p )); 139ea906c41SOllivier Robert memcpy( p + 1, pOpts->pOptDesc, p->optCt * sizeof( tOptDesc )); 140ea906c41SOllivier Robert 141ea906c41SOllivier Robert fixupSavedOptionArgs(pOpts); 142ea906c41SOllivier Robert } 143ea906c41SOllivier Robert 144ea906c41SOllivier Robert 145ea906c41SOllivier Robert /*=export_func optionRestore 146ea906c41SOllivier Robert * 147ea906c41SOllivier Robert * what: restore option state from memory copy 148ea906c41SOllivier Robert * arg: tOptions*, pOpts, program options descriptor 149ea906c41SOllivier Robert * 150ea906c41SOllivier Robert * doc: Copy back the option state from saved memory. 151ea906c41SOllivier Robert * The allocated memory is left intact, so this routine can be 152ea906c41SOllivier Robert * called repeatedly without having to call optionSaveState again. 153ea906c41SOllivier Robert * If you are restoring a state that was saved before the first call 154ea906c41SOllivier Robert * to optionProcess(3AO), then you may change the contents of the 155ea906c41SOllivier Robert * argc/argv parameters to optionProcess. 156ea906c41SOllivier Robert * 157ea906c41SOllivier Robert * err: If you have not called @code{optionSaveState} before, a diagnostic is 158ea906c41SOllivier Robert * printed to @code{stderr} and exit is called. 159ea906c41SOllivier Robert =*/ 160ea906c41SOllivier Robert void 161ea906c41SOllivier Robert optionRestore( tOptions* pOpts ) 162ea906c41SOllivier Robert { 163ea906c41SOllivier Robert tOptions* p = (tOptions*)pOpts->pSavedState; 164ea906c41SOllivier Robert 165ea906c41SOllivier Robert if (p == NULL) { 166ea906c41SOllivier Robert tCC* pzName = pOpts->pzProgName; 167ea906c41SOllivier Robert if (pzName == NULL) { 168ea906c41SOllivier Robert pzName = pOpts->pzPROGNAME; 169ea906c41SOllivier Robert if (pzName == NULL) 170ea906c41SOllivier Robert pzName = zNil; 171ea906c41SOllivier Robert } 172ea906c41SOllivier Robert fprintf( stderr, zNoState, pzName ); 173ea906c41SOllivier Robert exit( EXIT_FAILURE ); 174ea906c41SOllivier Robert } 175ea906c41SOllivier Robert 176ea906c41SOllivier Robert pOpts->pSavedState = NULL; 177ea906c41SOllivier Robert optionFree(pOpts); 178ea906c41SOllivier Robert 179ea906c41SOllivier Robert memcpy( pOpts, p, sizeof( *p )); 180ea906c41SOllivier Robert memcpy( pOpts->pOptDesc, p+1, p->optCt * sizeof( tOptDesc )); 181ea906c41SOllivier Robert pOpts->pSavedState = p; 182ea906c41SOllivier Robert 183ea906c41SOllivier Robert fixupSavedOptionArgs(pOpts); 184ea906c41SOllivier Robert } 185ea906c41SOllivier Robert 186ea906c41SOllivier Robert /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ 187ea906c41SOllivier Robert 188ea906c41SOllivier Robert /*=export_func optionFree 189ea906c41SOllivier Robert * 190ea906c41SOllivier Robert * what: free allocated option processing memory 191ea906c41SOllivier Robert * arg: tOptions*, pOpts, program options descriptor 192ea906c41SOllivier Robert * 193ea906c41SOllivier Robert * doc: AutoOpts sometimes allocates memory and puts pointers to it in the 194ea906c41SOllivier Robert * option state structures. This routine deallocates all such memory. 195ea906c41SOllivier Robert * 196ea906c41SOllivier Robert * err: As long as memory has not been corrupted, 197ea906c41SOllivier Robert * this routine is always successful. 198ea906c41SOllivier Robert =*/ 199ea906c41SOllivier Robert void 200ea906c41SOllivier Robert optionFree( tOptions* pOpts ) 201ea906c41SOllivier Robert { 202ea906c41SOllivier Robert free_saved_state: 203ea906c41SOllivier Robert { 204ea906c41SOllivier Robert tOptDesc* p = pOpts->pOptDesc; 205ea906c41SOllivier Robert int ct = pOpts->optCt; 206ea906c41SOllivier Robert do { 207ea906c41SOllivier Robert if (p->fOptState & OPTST_ALLOC_ARG) { 208ea906c41SOllivier Robert AGFREE(p->optArg.argString); 209ea906c41SOllivier Robert p->optArg.argString = NULL; 210ea906c41SOllivier Robert p->fOptState &= ~OPTST_ALLOC_ARG; 211ea906c41SOllivier Robert } 212ea906c41SOllivier Robert 213ea906c41SOllivier Robert switch (OPTST_GET_ARGTYPE(p->fOptState)) { 214ea906c41SOllivier Robert case OPARG_TYPE_STRING: 215ea906c41SOllivier Robert #ifdef WITH_LIBREGEX 216ea906c41SOllivier Robert if ( (p->fOptState & OPTST_STACKED) 217ea906c41SOllivier Robert && (p->optCookie != NULL)) { 218ea906c41SOllivier Robert p->optArg.argString = ".*"; 219ea906c41SOllivier Robert optionUnstackArg(pOpts, p); 220ea906c41SOllivier Robert } 221ea906c41SOllivier Robert #else 222ea906c41SOllivier Robert /* leak memory */; 223ea906c41SOllivier Robert #endif 224ea906c41SOllivier Robert break; 225ea906c41SOllivier Robert 226ea906c41SOllivier Robert case OPARG_TYPE_HIERARCHY: 227ea906c41SOllivier Robert if (p->optCookie != NULL) 228ea906c41SOllivier Robert unloadNestedArglist(p->optCookie); 229ea906c41SOllivier Robert break; 230ea906c41SOllivier Robert } 231ea906c41SOllivier Robert 232ea906c41SOllivier Robert p->optCookie = NULL; 233ea906c41SOllivier Robert } while (p++, --ct > 0); 234ea906c41SOllivier Robert } 235ea906c41SOllivier Robert if (pOpts->pSavedState != NULL) { 236ea906c41SOllivier Robert tOptions * p = (tOptions*)pOpts->pSavedState; 237ea906c41SOllivier Robert memcpy( pOpts, p, sizeof( *p )); 238ea906c41SOllivier Robert memcpy( pOpts->pOptDesc, p+1, p->optCt * sizeof( tOptDesc )); 239ea906c41SOllivier Robert AGFREE( pOpts->pSavedState ); 240ea906c41SOllivier Robert pOpts->pSavedState = NULL; 241ea906c41SOllivier Robert goto free_saved_state; 242ea906c41SOllivier Robert } 243ea906c41SOllivier Robert } 244ea906c41SOllivier Robert /* 245ea906c41SOllivier Robert * Local Variables: 246ea906c41SOllivier Robert * mode: C 247ea906c41SOllivier Robert * c-file-style: "stroustrup" 248ea906c41SOllivier Robert * indent-tabs-mode: nil 249ea906c41SOllivier Robert * End: 250ea906c41SOllivier Robert * end of autoopts/restore.c */ 251