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