aboutsummaryrefslogtreecommitdiff
path: root/project/dclib/dclib-option.h
blob: f16dd7b1c82130f6835fe19fb383e1b9811256f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

/***************************************************************************
 *                                                                         *
 *                     _____     ____                                      *
 *                    |  __ \   / __ \   _     _ _____                     *
 *                    | |  \ \ / /  \_\ | |   | |  _  \                    *
 *                    | |   \ \| |      | |   | | |_| |                    *
 *                    | |   | || |      | |   | |  ___/                    *
 *                    | |   / /| |   __ | |   | |  _  \                    *
 *                    | |__/ / \ \__/ / | |___| | |_| |                    *
 *                    |_____/   \____/  |_____|_|_____/                    *
 *                                                                         *
 *                       Wiimms source code library                        *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *        Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de>         *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt       *
 *                                                                         *
 ***************************************************************************/

#ifndef DCLIB_OPTION_H
#define DCLIB_OPTION_H 1

#include "dclib-basics.h"
struct TCPStream_t;

//
///////////////////////////////////////////////////////////////////////////////
///////////////			    GenericOpt_t		///////////////
///////////////////////////////////////////////////////////////////////////////
// [[GenericOptParm_t]]

typedef struct GenericOptParm_t
{
    u32		id;		// id of the option,
    u8		arg;		// 0:no arg, 1:arg, 2:optional arg
    ccp		name;		// pipe separated option names
}
GenericOptParm_t;

//-----------------------------------------------------------------------------
// [[GenericOpt_t]]

struct option;

typedef struct GenericOpt_t
{
    //--- short options

    char	sopt[0x100];	// short options string
    u32		sopt_id[0x80];

    //--- long options

    struct option *lopt;	// long options list
    uint	lopt_used;	// number of used 'lopt' elements
    uint	lopt_size;	// number of alloced 'lopt' elements

    //--- string pool

    MemPool_t	str_pool;	// pool for option names
}
GenericOpt_t;

//-----------------------------------------------------------------------------

void InitializeGenericOpt ( GenericOpt_t *go, char first_char );
void ResetGenericOpt ( GenericOpt_t *go );

void AddGenericOpt
(
    GenericOpt_t	*go,		// data structure
    const GenericOptParm_t *gp,		// list to add, list end on name==NULL
    bool		rm_minus	// remove '-' on options for alternatives
);

//
///////////////////////////////////////////////////////////////////////////////
///////////////			    GOPT_t			///////////////
///////////////////////////////////////////////////////////////////////////////
// [[GOPT_t]]

typedef enum GOPT_t
{
	GOPT_RESERVED_BEG	= 0x01000000,	// begin of reserved range
	GOPT_RESERVED_END	= 0x02000000,	// end of reserved range

	GOPT_M_INDEX		= 0x000000ff,	// mask to get the index
	GOPT_N_PARAM		=         25,	// max used index+1 = num of params
	 GOPT_M_VALUE		= 0x0003ff00,	// mask for GOPT_T_PLUS|GOPT_T_MINUS
	 GOPT_S_VALUE		=	   8,	// value is shifted by this num
	GOPT_M_TYPE		= 0x00fc0000,	// mask to isolate option type
	GOPT_I_TYPE		= 0x00040000,	// increment between types
	GOPT_S_TYPE		=	  18,	// type is shifted by this num


	//--- parameters by index

	GOPT_IDX_NULL = 0,	// type undefined

	GOPT_IDX_INC,		// increment 'sn', ptype := GOPT_T_INC
	GOPT_IDX_INC0,		// increment 'sn', ptype := GOPT_T_INC
	GOPT_IDX_DEC,		// decrement 'sn', ptype := GOPT_T_INC
	GOPT_IDX_DEC0,		// decrement 'sn', ptype := GOPT_T_INC

	GOPT_IDX_SETP,		// set 'sn' to value 0..0x3ff,   ptype := GOPT_IDX_SINT
	GOPT_IDX_SETM,		// set 'sn' to value -0..-0x3ff, ptype := GOPT_IDX_SINT
	GOPT_IDX_SETP64,	// set 'sn64' to value 0..0x3ff,   ptype := GOPT_IDX_S64
	GOPT_IDX_SETM64,	// set 'sn64' to value -0..-0x3ff, ptype := GOPT_IDX_S64

	GOPT_IDX_OR,		// set 'un' |= value 0..0x3ff, ptype := GOPT_IDX_UINT
	GOPT_IDX_SETBIT,	// set bit VALUE in 'un', ptype := GOPT_IDX_UINT
	GOPT_IDX_BIT,		// ana param and set/clear bit VALUE in 'un', ptype := GOPT_IDX_UINT
	GOPT_IDX_OR64,		// set 'un64' |= value 0..0x3ff, ptype := GOPT_IDX_U64
	GOPT_IDX_SETBIT64,	// set bit VALUE in 'un64', ptype := GOPT_IDX_UINT64

	GOPT_IDX_SINT,		// scan signed integer
	GOPT_IDX_UINT,		// scan unsigned integer
	GOPT_IDX_OFF_ON,	// scan 'off|onn|0|1' and otional a number, ptype := GOPT_IDX_UINT
	GOPT_IDX_S64,		// scan signed 64-bit integer
	GOPT_IDX_U64,		// scan unsigned 64-bit integer
	GOPT_IDX_HEX,		// scan unsigned 64-bit integer, assume hex
	GOPT_IDX_SIZE,		// scan size (double with optional SI) and store as 'un64'
	GOPT_IDX_DOUBLE,	// scan double float
	GOPT_IDX_DURATION,	// scan duration (double with optional SI) and store as 'd'
	GOPT_IDX_STRING,	// store ccp pointer to text

	GOPT_IDX_END,		// end of parameters


	//--- parameters types

	GOPT_T_NULL		= 0, // type undefined
	GOPT_T_INC		= GOPT_RESERVED_BEG | ( GOPT_IDX_INC	<< GOPT_S_TYPE ),
	GOPT_T_INC0		= GOPT_RESERVED_BEG | ( GOPT_IDX_INC0	<< GOPT_S_TYPE ),
	GOPT_T_DEC		= GOPT_RESERVED_BEG | ( GOPT_IDX_DEC	<< GOPT_S_TYPE ),
	GOPT_T_DEC0		= GOPT_RESERVED_BEG | ( GOPT_IDX_DEC0	<< GOPT_S_TYPE ),
	GOPT_T_SETP		= GOPT_RESERVED_BEG | ( GOPT_IDX_SETP	<< GOPT_S_TYPE ),
	GOPT_T_SETM		= GOPT_RESERVED_BEG | ( GOPT_IDX_SETM	<< GOPT_S_TYPE ),
	GOPT_T_SETP64		= GOPT_RESERVED_BEG | ( GOPT_IDX_SETP64	<< GOPT_S_TYPE ),
	GOPT_T_SETM64		= GOPT_RESERVED_BEG | ( GOPT_IDX_SETM64	<< GOPT_S_TYPE ),
	GOPT_T_OR		= GOPT_RESERVED_BEG | ( GOPT_IDX_OR	<< GOPT_S_TYPE ),
	GOPT_T_SETBIT		= GOPT_RESERVED_BEG | ( GOPT_IDX_SETBIT	<< GOPT_S_TYPE ),
	GOPT_T_BIT		= GOPT_RESERVED_BEG | ( GOPT_IDX_BIT	<< GOPT_S_TYPE ),
	GOPT_T_OR64		= GOPT_RESERVED_BEG | ( GOPT_IDX_OR64	<< GOPT_S_TYPE ),
	GOPT_T_SETBIT64		= GOPT_RESERVED_BEG | ( GOPT_IDX_SETBIT64 << GOPT_S_TYPE ),
	GOPT_T_SINT		= GOPT_RESERVED_BEG | ( GOPT_IDX_SINT	<< GOPT_S_TYPE ),
	GOPT_T_UINT		= GOPT_RESERVED_BEG | ( GOPT_IDX_UINT	<< GOPT_S_TYPE ),
	GOPT_T_OFF_ON		= GOPT_RESERVED_BEG | ( GOPT_IDX_OFF_ON	<< GOPT_S_TYPE ),
	GOPT_T_S64		= GOPT_RESERVED_BEG | ( GOPT_IDX_S64	<< GOPT_S_TYPE ),
	GOPT_T_U64		= GOPT_RESERVED_BEG | ( GOPT_IDX_U64	<< GOPT_S_TYPE ),
	GOPT_T_HEX		= GOPT_RESERVED_BEG | ( GOPT_IDX_HEX	<< GOPT_S_TYPE ),
	GOPT_T_SIZE		= GOPT_RESERVED_BEG | ( GOPT_IDX_SIZE	<< GOPT_S_TYPE ),
	GOPT_T_DOUBLE		= GOPT_RESERVED_BEG | ( GOPT_IDX_DOUBLE	<< GOPT_S_TYPE ),
	GOPT_T_DURATION		= GOPT_RESERVED_BEG | ( GOPT_IDX_DURATION << GOPT_S_TYPE ),
	GOPT_T_STRING		= GOPT_RESERVED_BEG | ( GOPT_IDX_STRING	<< GOPT_S_TYPE ),
	GOPT_T_END		= GOPT_RESERVED_BEG | ( GOPT_IDX_END	<< GOPT_S_TYPE ),


	//--- named options

	GOPT_O__BEGIN		= 0x100,
	GOPT_O_TEST_OPT,	// test: print all defined options

	GOPT_O_HELP,		// force help
	GOPT_O_CLEAR,		// clear screen -> ScanGOptionsHelperTN()
	GOPT_O_PAGER,		// activate pager -> ScanGOptionsHelperTN()
	GOPT_O_QUIT,		// quit if command done -> ScanGOptionsHelperTN()

	GOPT_O_QUIET,		// be quiet
	GOPT_O_VERBOSE,		// be verbose

	GOPT_O__CONTINUE	// continue with this value on more options
}
GOPT_t;

static inline GOPT_t GetGOPType ( GOPT_t gt )
	{ return ( gt & GOPT_M_TYPE ) >> GOPT_S_TYPE; }

//
///////////////////////////////////////////////////////////////////////////////
///////////////		    global options: parameters		///////////////
///////////////////////////////////////////////////////////////////////////////
// [[GParamValueType_t]]

typedef enum GParamValueType_t
{
	GPT_NONE,	// no param set
	GPT_SN,		// value stored as 'sn'
	GPT_UN,		// value stored as 'un'
	GPT_SN64,	// value stored as 'sn64'
	GPT_UN64,	// value stored as 'un64'
	GPT_D,		// value stored as 'd'
	GPT_STR,	// value stored as 'str'
	GPT_BIT,	// value stored as 'bit.val' & 'bit.mask'
}
GParamValueType_t;

GParamValueType_t GetGParamValueType ( GOPT_t gt );

///////////////////////////////////////////////////////////////////////////////
// [[GParam_t]]

typedef struct GParam_t
{
    u16 ptype;		// GOPT_IDX_*
    u16 vtype;		// GParamValueType_t

    union
    {
	int	sn;	// used by GOPT_T_INC*, GOPT_T_DEC*, GOPT_T_SINT
	uint	un;	// used by GOPT_T_UINT
	s64	sn64;	// used by GOPT_T_S64, GOPT_T_SETM
	u64	un64;	// used by GOPT_T_U64, GOPT_T_HEX, GOPT_T_SIZE, GOPT_T_SETP
	double	d;	// used by GOPT_T_DOUBLE, GOPT_T_DURATION
	ccp	str;	// used by GOPT_T_STRING
	struct { u32 val; u32 mask; } bit;
			// used by GOPT_T_BIT
    };
}
GParam_t;

///////////////////////////////////////////////////////////////////////////////
// [[GetGParam_t]]

typedef enum GetGParam_t
{
	GGP_NONE,	// no param set or param unusable, 'return_val' untouched
	GGP_CONVERT,	// param set, but converted (different numeric type)
	GGP_SIGN,	// param returned, but sign maybe converted
	GGP_OK		// original or extended param returned
}
GetGParam_t;

// If gp==NULL: return GGP_NONE
// If return_val==NULL: analyse only
GetGParam_t GetGParamINT  ( const GParam_t *par, int    *return_val );
GetGParam_t GetGParamUINT ( const GParam_t *par, uint   *return_val );
GetGParam_t GetGParamS64  ( const GParam_t *par, s64    *return_val );
GetGParam_t GetGParamU64  ( const GParam_t *par, u64    *return_val );
GetGParam_t GetGParamDBL  ( const GParam_t *par, double *return_val );
GetGParam_t GetGParamSTR  ( const GParam_t *par, ccp    *return_val );
GetGParam_t GetGParamBIT  ( const GParam_t *par, u32    *return_val, u32 *return_mask );

ccp PrintGParam ( const GParam_t *par );

//
///////////////////////////////////////////////////////////////////////////////
///////////////			global options			///////////////
///////////////////////////////////////////////////////////////////////////////
// [[GOptions_t]]

typedef struct GOptions_t
{
    //--- parameters

    int		argc;		// number of parameters
    char	**argv;		// parameters without options


    //--- named options

    int		help;		// number of GOPT_O_HELP
    int		clear;		// number of GOPT_O_CLEAR
    int		pager;		// number of GOPT_O_PAGER,
    int		quit;		// number of GOPT_O_QUIT,
    int		verbose;	// combi of GOPT_O_QUIET & GOPT_O_VERBOSE,


    //--- generic parameter support

    GParam_t param[GOPT_N_PARAM];
}
GOptions_t;

//-----------------------------------------------------------------------------

static inline void InitializeGOptions ( GOptions_t *go )
{
    DASSERT(go);
    memset(go,0,sizeof(*go));
}

static inline const GParam_t * GetGParam ( const GOptions_t *go, uint par_index )
	{ return go && par_index < GOPT_N_PARAM ? go->param+par_index : 0; }

///////////////////////////////////////////////////////////////////////////////

extern const GenericOptParm_t StandardGOptions[];

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef int (*ScanOptionFunc)
(
    // returns: 0 on not procecced / <0 on error / >0 on success

    GenericOpt_t	*go,		// valid pointer to generic options
    GOptions_t		*gopt,		// valid pointer to options data
    void		*any_ptr,	// user specific pointer
    int			num,		// numeric param:
					//   OnAddOptions():	'scan_opt'
					//   OnOption():	option id
					//   OnArgument():	argument index
    ccp			arg		// NULL or text argument
);

///////////////////////////////////////////////////////////////////////////////
// [[ScanGOpt_t]]

typedef enum ScanGOpt_t
{
	SGO_KNOWN	= 0x0001,   // scan only until first unknown parameter
	SGO_PAGER	= 0x0002,   // auto enable pager

	SGO__CONTINUE	= 0x0004    // define more flags based on this value
}
ScanGOpt_t;

///////////////////////////////////////////////////////////////////////////////

enumError ScanGOptionsHelper
(
    GOptions_t		*gopt,		// valid pointer
    GenericOpt_t	*go,		// NULL or list with options
					//	=> ResetGenericOpt() is called at finish
    int			argc,		// argument counter
    char		**argv,		// list of arguments
    int			max_param,	// >=0: max allowed parameters
    ScanGOpt_t		scan_opt,	// scan options

    //--- call back functions
    ScanOptionFunc	OnAddOptions,	// not NULL: called once to add options
    ScanOptionFunc	OnOption,	// not NULL: called for each option
    ScanOptionFunc	OnArgument,	// not NULL: called for each argument
    void		*any_ptr	// NULL or user specific pointer for call back
);

//-----------------------------------------------------------------------------

enumError ScanGOptionsHelperTN
(
    // like ScanGOptionsHelper(), but with TELNET support
    // for 'gopt->clear', 'gopt->pager' and 'gopt->quit',
    // if 'ts' is not NULL and telnet is active.

    GOptions_t		*gopt,		// valid pointer
    GenericOpt_t	*go,		// NULL or list with options
					//	=> ResetGenericOpt() is called at finish
    int			argc,		// argument counter
    char		**argv,		// list of arguments
    int			max_param,	// >=0: max allowed parameters
    ScanGOpt_t		scan_opt,	// scan options
    struct TCPStream_t	*ts,		// NULL or current stream with TELNET support

    //--- call back functions
    ScanOptionFunc	OnAddOptions,	// not NULL: called once to add options
    ScanOptionFunc	OnOption,	// not NULL: called for each option
    ScanOptionFunc	OnArgument,	// not NULL: called for each argument
    void		*any_ptr	// NULL or user specific pointer for call back
);

//
///////////////////////////////////////////////////////////////////////////////
///////////////			    E N D			///////////////
///////////////////////////////////////////////////////////////////////////////

#endif // DCLIB_OPTION_H