1 #if !defined HAVE_NEXTARG_H__
2 #define HAVE_NEXTARG_H__
3
4 // This file is part of the FXT library.
5 // Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2018, 2019 Joerg Arndt
6 // License: GNU General Public License version 3 or later,
7 // see the file COPYING.txt in the main directory.
8
9 //: simple argument parser, mostly for demo programs.
10
11 #include "fxtio.h"
12 #include "fxttypes.h"
13
14 #include <cstdlib> // atol(), atof(), strtoul(), strtod()
15
16 // To suppress the output such as
17 // arg 1: val == explanation
18 // insert the (following) line
19 //#define FXT_SILENT_NXARG
20 // before the inclusion of this header file.
21
22 // To prefix each line with a string, define
23 //#define FXT_PREF_NXARG "## "
24 // This can be useful with redirections and filtering.
25
26 extern int nextarg_act; // nextarg.cc
27
28 template <typename Type>
next_arg(Type & v,const char * vname,const char * what,int argc,char ** argv)29 void next_arg(Type &v, const char *vname, const char *what,
30 int argc, char **argv)
31 {
32 const Type def = v;
33 ++nextarg_act;
34
35 if ( argc > nextarg_act )
36 {
37 if ( argv[nextarg_act][0] != '.' ) // "." for default
38 {
39 int b = 10; // default is base 10
40
41 // leading "0x" for base 16:
42 if ( (argv[nextarg_act][0]=='0') && (argv[nextarg_act][1]=='x') ) b = 16;
43
44 // leading "_" for base 2:
45 if ( argv[nextarg_act][0]=='_' ) { b = 2; argv[nextarg_act]+=1; }
46
47 // check signed-ness:
48 Type nextarg_x = 1;
49 nextarg_x = -nextarg_x;
50 if ( nextarg_x > 0 ) // we have an unsigned type
51 v = (Type)strtoul(argv[nextarg_act], nullptr, b);
52 else
53 v = (Type)strtol(argv[nextarg_act], nullptr, b);
54 }
55 }
56
57
58 #ifndef FXT_SILENT_NXARG
59 #ifdef FXT_PREF_NXARG
60 cout << FXT_PREF_NXARG;
61 #endif
62 cout << "arg " << nextarg_act << ": ";
63 cout << v << " == " << vname;
64 cout << " [" << what << "]";
65 cout << " default=" << def;
66 cout << endl;
67 #else
68 // supress warnings about unused parameters:
69 (void)what;
70 (void)vname;
71 (void)def;
72 #endif
73
74 }
75 // -------------------------
76
77 // nextarg.cc:
78 void
79 next_float_arg(double &v, const char *vname, const char *what,
80 int argc, char **argv);
81
82 void
83 next_string_arg(char *&v, const char *vname, const char *what,
84 int argc, char **argv,
85 char *def); // need explicit default with strings
86
87 template <typename Type>
next_enum_arg(Type & v,const char * vname,const char * what,int argc,char ** argv)88 void next_enum_arg(Type &v, const char *vname, const char *what,
89 int argc, char **argv)
90 {
91 const Type def = v;
92 ++nextarg_act;
93
94 if ( argc > nextarg_act )
95 {
96 if ( argv[nextarg_act][0] != '.' ) // "." for default
97 {
98 int b = 10; // default is base 10
99
100 // leading "0x" for base 16:
101 if ( (argv[nextarg_act][0]=='0') && (argv[nextarg_act][1]=='x') ) b = 16;
102
103 // leading "_" for base 2:
104 if ( argv[nextarg_act][0]=='_' ) { b = 2; argv[nextarg_act]+=1; }
105
106 // // check signed-ness:
107 // Type nextarg_x = 1;
108 // nextarg_x = -nextarg_x;
109 // if ( nextarg_x > 0 ) // we have an unsigned type
110 // v = (Type)strtoul(argv[nextarg_act], nullptr, b);
111 // else
112 v = (Type)strtol(argv[nextarg_act], nullptr, b);
113 }
114 }
115
116
117 #ifndef FXT_SILENT_NXARG
118 #ifdef FXT_PREF_NXARG
119 cout << FXT_PREF_NXARG;
120 #endif
121 cout << "arg " << nextarg_act << ": ";
122 cout << (int)v << " == " << vname;
123 cout << " [" << what << "]";
124 cout << " default=" << (int)def;
125 cout << endl;
126 #else
127 // supress warnings about unused parameters:
128 (void)what;
129 (void)vname;
130 (void)def;
131 #endif
132
133 }
134 // -------------------------
135
136 #define NXARG(v, what) { next_arg(v, #v, what, argc, argv); }
137 #define NXARGFL(v, what) { next_float_arg(v, #v, what, argc, argv); }
138 #define NXARGSTR(v, what, def) { next_string_arg(v, ""#v, what, argc, argv, (char *)def); }
139 #define NXARGENUM(v, what) { next_enum_arg(v, ""#v, what, argc, argv); }
140
141 #ifdef FXT_SILENT_NXARG
142 #define RESTARGS_MSG(what) // silence
143 #else
144 #define RESTARGS_MSG(what) \
145 cout << "args " << nextarg_act \
146 << ","<< nextarg_act+1 << ",... : [" << what <<"]" << endl;
147 #endif
148
149 #define RESTARGS(what) { ++nextarg_act; RESTARGS_MSG(what); }
150
151
152
153 #endif // !defined HAVE_NEXTARG_H__
154