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