5 * restore.c Id: 6f5237ba2586755d8ca354f325fc00e7fa1395ec
6 * Time-stamp: "2007-07-04 11:34:40 bkorb"
8 * This module's routines will save the current option state to memory
9 * and restore it. If saved prior to the initial optionProcess call,
10 * then the initial state will be restored.
12 * This file is part of AutoOpts, a companion to AutoGen.
13 * AutoOpts is free software.
14 * AutoOpts is copyright (c) 1992-2009 by Bruce Korb - all rights reserved
16 * AutoOpts is available under any one of two licenses. The license
17 * in use must be one of these two and the choice is under the control
18 * of the user of the license.
20 * The GNU Lesser General Public License, version 3 or later
21 * See the files "COPYING.lgplv3" and "COPYING.gplv3"
23 * The Modified Berkeley Software Distribution License
24 * See the file "COPYING.mbsd"
26 * These files have the following md5sums:
28 * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
29 * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
30 * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
34 * optionFixupSavedOpts Really, it just wipes out option state for
35 * options that are troublesome to copy. viz., stacked strings and
36 * hierarcicaly valued option args. We do duplicate string args that
37 * have been marked as allocated though.
40 fixupSavedOptionArgs(tOptions
* pOpts
)
42 tOptions
* p
= pOpts
->pSavedState
;
43 tOptDesc
* pOD
= pOpts
->pOptDesc
;
44 int ct
= pOpts
->optCt
;
47 * Make sure that allocated stuff is only referenced in the
48 * archived copy of the data.
50 for (; ct
-- > 0; pOD
++) {
51 switch (OPTST_GET_ARGTYPE(pOD
->fOptState
)) {
52 case OPARG_TYPE_STRING
:
53 if (pOD
->fOptState
& OPTST_STACKED
) {
54 tOptDesc
* q
= p
->pOptDesc
+ (pOD
- pOpts
->pOptDesc
);
57 if (pOD
->fOptState
& OPTST_ALLOC_ARG
) {
58 tOptDesc
* q
= p
->pOptDesc
+ (pOD
- pOpts
->pOptDesc
);
59 AGDUPSTR(q
->optArg
.argString
, pOD
->optArg
.argString
, "arg");
63 case OPARG_TYPE_HIERARCHY
:
65 tOptDesc
* q
= p
->pOptDesc
+ (pOD
- pOpts
->pOptDesc
);
72 /*=export_func optionSaveState
74 * what: saves the option state to memory
75 * arg: tOptions*, pOpts, program options descriptor
79 * This routine will allocate enough memory to save the current option
80 * processing state. If this routine has been called before, that memory
81 * will be reused. You may only save one copy of the option state. This
82 * routine may be called before optionProcess(3AO). If you do call it
83 * before the first call to optionProcess, then you may also change the
84 * contents of argc/argv after you call optionRestore(3AO)
86 * In fact, more strongly put: it is safest to only use this function
87 * before having processed any options. In particular, the saving and
88 * restoring of stacked string arguments and hierarchical values is
89 * disabled. The values are not saved.
91 * err: If it fails to allocate the memory,
92 * it will print a message to stderr and exit.
93 * Otherwise, it will always succeed.
96 optionSaveState(tOptions
* pOpts
)
98 tOptions
* p
= (tOptions
*)pOpts
->pSavedState
;
101 size_t sz
= sizeof( *pOpts
) + (pOpts
->optCt
* sizeof( tOptDesc
));
102 p
= AGALOC( sz
, "saved option state" );
104 tCC
* pzName
= pOpts
->pzProgName
;
105 if (pzName
== NULL
) {
106 pzName
= pOpts
->pzPROGNAME
;
110 fprintf( stderr
, zCantSave
, pzName
, sz
);
111 exit( EXIT_FAILURE
);
114 pOpts
->pSavedState
= p
;
117 memcpy( p
, pOpts
, sizeof( *p
));
118 memcpy( p
+ 1, pOpts
->pOptDesc
, p
->optCt
* sizeof( tOptDesc
));
120 fixupSavedOptionArgs(pOpts
);
124 /*=export_func optionRestore
126 * what: restore option state from memory copy
127 * arg: tOptions*, pOpts, program options descriptor
129 * doc: Copy back the option state from saved memory.
130 * The allocated memory is left intact, so this routine can be
131 * called repeatedly without having to call optionSaveState again.
132 * If you are restoring a state that was saved before the first call
133 * to optionProcess(3AO), then you may change the contents of the
134 * argc/argv parameters to optionProcess.
136 * err: If you have not called @code{optionSaveState} before, a diagnostic is
137 * printed to @code{stderr} and exit is called.
140 optionRestore( tOptions
* pOpts
)
142 tOptions
* p
= (tOptions
*)pOpts
->pSavedState
;
145 tCC
* pzName
= pOpts
->pzProgName
;
146 if (pzName
== NULL
) {
147 pzName
= pOpts
->pzPROGNAME
;
151 fprintf( stderr
, zNoState
, pzName
);
152 exit( EXIT_FAILURE
);
155 pOpts
->pSavedState
= NULL
;
158 memcpy( pOpts
, p
, sizeof( *p
));
159 memcpy( pOpts
->pOptDesc
, p
+1, p
->optCt
* sizeof( tOptDesc
));
160 pOpts
->pSavedState
= p
;
162 fixupSavedOptionArgs(pOpts
);
165 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
167 /*=export_func optionFree
169 * what: free allocated option processing memory
170 * arg: tOptions*, pOpts, program options descriptor
172 * doc: AutoOpts sometimes allocates memory and puts pointers to it in the
173 * option state structures. This routine deallocates all such memory.
175 * err: As long as memory has not been corrupted,
176 * this routine is always successful.
179 optionFree( tOptions
* pOpts
)
183 tOptDesc
* p
= pOpts
->pOptDesc
;
184 int ct
= pOpts
->optCt
;
186 if (p
->fOptState
& OPTST_ALLOC_ARG
) {
187 AGFREE(p
->optArg
.argString
);
188 p
->optArg
.argString
= NULL
;
189 p
->fOptState
&= ~OPTST_ALLOC_ARG
;
192 switch (OPTST_GET_ARGTYPE(p
->fOptState
)) {
193 case OPARG_TYPE_STRING
:
195 if ( (p
->fOptState
& OPTST_STACKED
)
196 && (p
->optCookie
!= NULL
)) {
197 p
->optArg
.argString
= ".*";
198 optionUnstackArg(pOpts
, p
);
205 case OPARG_TYPE_HIERARCHY
:
206 if (p
->optCookie
!= NULL
)
207 unloadNestedArglist(p
->optCookie
);
212 } while (p
++, --ct
> 0);
214 if (pOpts
->pSavedState
!= NULL
) {
215 tOptions
* p
= (tOptions
*)pOpts
->pSavedState
;
216 memcpy( pOpts
, p
, sizeof( *p
));
217 memcpy( pOpts
->pOptDesc
, p
+1, p
->optCt
* sizeof( tOptDesc
));
218 AGFREE( pOpts
->pSavedState
);
219 pOpts
->pSavedState
= NULL
;
220 goto free_saved_state
;
226 * c-file-style: "stroustrup"
227 * indent-tabs-mode: nil
229 * end of autoopts/restore.c */