1 //
2 // C++ Implementation: gm_utils
3 //
4 // Description:
5 //
6 //
7 // Author: Lorenzo Bettini <http://www.lorenzobettini.it>, (C) 2004
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12 
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16 
17 #include <string.h>
18 #include <sstream>
19 
20 #include "gm_utils.h"
21 #include "ggo_options.h"
22 #include "argsdef.h"
23 #include "groups.h"
24 
25 using namespace std;
26 
27 extern groups_collection_t gengetopt_groups;
28 
29 char *
canonize_names(const char * name)30 canonize_names(const char *name) {
31     char *pvar;
32     char *p;
33 
34     pvar = strdup(name);
35 
36     for (p = pvar; *p; ++p)
37         if (*p == '.' || *p == '-' || *p == '/')
38             *p = '_';
39 
40     return pvar;
41 }
42 
43 // remove the path from the file name
strip_path(const string & s)44 const string strip_path(const string &s) {
45     string::size_type pos_of_sep;
46 
47     pos_of_sep = s.rfind("/");
48     if (pos_of_sep == string::npos)
49         pos_of_sep = s.rfind("\\"); // try also with DOS path sep
50 
51     if (pos_of_sep == string::npos)
52         return s; // no path
53 
54     return s.substr(pos_of_sep + 1);
55 }
56 
to_upper(const string & old)57 const string to_upper(const string &old) {
58     string upper = old;
59 
60     for (string::iterator s = upper.begin(); s != upper.end(); ++s)
61         *s = toupper(*s);
62 
63     return upper;
64 }
65 
canonize_name(const string & old)66 const string canonize_name(const string &old) {
67     string canonized = old;
68 
69     for (string::iterator s = canonized.begin(); s != canonized.end(); ++s)
70         if (*s == '.' || *s == '-' || *s == ' ' || *s == '/')
71             *s = '_';
72 
73     return canonized;
74 }
75 
canonize_enum(const string & old)76 const string canonize_enum(const string &old) {
77     string canonized;
78 
79     for (string::const_iterator s = old.begin(); s != old.end(); ++s)
80         if (*s == '-')
81             canonized += "MINUS_";
82         else if (*s == '+')
83             canonized += "PLUS_";
84         else
85             canonized += *s;
86 
87     return canonized;
88 }
89 
has_multiple_options_all_string()90 bool has_multiple_options_all_string() {
91     if (!has_multiple_options())
92         return false;
93 
94     struct gengetopt_option * opt = 0;
95 
96     foropt {
97         if (opt->multiple && (opt->type && opt->type != ARG_STRING))
98             return false;
99     }
100 
101     return true;
102 }
103 
has_multiple_options_string()104 bool has_multiple_options_string() {
105     if (!has_multiple_options())
106         return false;
107 
108     struct gengetopt_option * opt = 0;
109 
110     foropt {
111         if (opt->multiple && opt->type == ARG_STRING)
112             return true;
113     }
114 
115     return false;
116 }
117 
has_multiple_options()118 bool has_multiple_options() {
119     struct gengetopt_option * opt = 0;
120 
121     foropt {
122         if (opt->multiple)
123             return true;
124     }
125 
126     return false;
127 }
128 
has_multiple_options_with_type()129 bool has_multiple_options_with_type() {
130     gengetopt_option * opt = 0;
131 
132     for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it
133             != gengetopt_options.end() && (opt = *it); ++it)
134         if (opt->multiple && opt->type)
135             return true;
136 
137     return false;
138 }
139 
has_multiple_options_with_default()140 bool has_multiple_options_with_default() {
141     gengetopt_option * opt = 0;
142 
143     for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it
144             != gengetopt_options.end() && (opt = *it); ++it)
145         if (opt->multiple && opt->default_given)
146             return true;
147 
148     return false;
149 }
150 
has_options_with_details(bool strict_hidden)151 bool has_options_with_details(bool strict_hidden) {
152     gengetopt_option * opt = 0;
153 
154     for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it
155             != gengetopt_options.end() && (opt = *it); ++it)
156         if (opt->details && (!strict_hidden || !opt->hidden))
157             return true;
158 
159     return false;
160 }
161 
has_options_with_type()162 bool has_options_with_type() {
163     gengetopt_option * opt = 0;
164 
165     for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it
166             != gengetopt_options.end() && (opt = *it); ++it)
167         if (opt->type && opt->type != ARG_FLAG)
168             return true;
169 
170     return false;
171 }
172 
has_options_with_mode()173 bool has_options_with_mode() {
174     gengetopt_option * opt = 0;
175 
176     for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it
177             != gengetopt_options.end() && (opt = *it); ++it)
178         if (opt->mode_value)
179             return true;
180 
181     return false;
182 }
183 
has_required()184 bool has_required() {
185     struct gengetopt_option * opt = 0;
186 
187     foropt {
188         if (opt->required)
189             return true;
190     }
191 
192     groups_collection_t::const_iterator end = gengetopt_groups.end();
193     for (groups_collection_t::const_iterator idx = gengetopt_groups.begin(); idx
194             != end; ++idx) {
195         if (idx->second.required) {
196             return true;
197         }
198     }
199 
200     return false;
201 }
202 
has_dependencies()203 bool has_dependencies() {
204     struct gengetopt_option * opt = 0;
205 
206     foropt {
207         if (opt->dependon)
208             return true;
209     }
210 
211     return false;
212 }
213 
has_options()214 bool has_options() {
215     struct gengetopt_option * opt = 0;
216 
217     foropt {
218         if (opt->short_opt) {
219             if (opt->short_opt != 'h' && opt->short_opt != 'V')
220                 return true;
221         }
222     }
223 
224     return false;
225 }
226 
has_hidden_options()227 bool has_hidden_options() {
228     struct gengetopt_option * opt = 0;
229 
230     foropt {
231         if (opt->hidden) {
232             return true;
233         }
234     }
235 
236     return false;
237 }
238 
has_values()239 bool has_values() {
240     struct gengetopt_option * opt = 0;
241 
242     for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it
243             != gengetopt_options.end(); ++it) {
244         opt = *it;
245         if (opt->acceptedvalues) {
246             return true;
247         }
248     }
249 
250     return false;
251 }
252 
not_newlines(const string & buf,int & num_of_newlines)253 int not_newlines(const string &buf, int &num_of_newlines) {
254     num_of_newlines = 0;
255     // searches for the first non newline char
256     string::size_type notnewline = buf.find_first_not_of("\r\n");
257 
258     if (notnewline == string::npos) {
259         // a string made only of newlines
260         num_of_newlines = buf.size();
261         return num_of_newlines;
262     }
263 
264     if (notnewline) {
265         // everything before the non newline char is a newline
266         num_of_newlines = notnewline;
267         return notnewline;
268     }
269 
270     return 0;
271 }
272 
wrap_cstr(string & wrapped,unsigned int from_column,unsigned int second_indent,const string & orig)273 void wrap_cstr(string& wrapped, unsigned int from_column,
274         unsigned int second_indent, const string &orig) {
275     int next_space = from_column;
276     string next_word;
277     const char * out_buf = orig.c_str();
278     ostringstream stream;
279     const unsigned int second_line_column = from_column + second_indent;
280     string indent(second_line_column, ' ');
281     int newline_chars = 0;
282     int num_of_newlines = 0;
283 
284     while (*out_buf) {
285         // check for a new line
286         if ((newline_chars = not_newlines(out_buf, num_of_newlines))) {
287             for (int i = 1; i <= num_of_newlines; ++i)
288                 stream << "\\n";
289 
290             out_buf += newline_chars;
291 
292             if (*out_buf) {
293                 stream << indent;
294                 next_space = second_line_column;
295                 continue;
296             } else
297                 break;
298         }
299 
300         // find next word (including any preceeding spaces)
301         bool had_word = false;
302         while ((*out_buf) && (*out_buf != ' ' || !had_word) &&
303                 !not_newlines(out_buf, num_of_newlines)) {
304             had_word = *out_buf != ' ';
305             next_word += *out_buf++;
306             next_space++;
307         }
308 
309         // wrap line if it's too long
310         if (next_space > 79) {
311             // trim leading spaces
312             std::size_t pos = next_word.find_first_not_of(' ');
313             if( pos == std::string::npos )
314                 next_word.empty();
315             else if( pos )
316                 next_word.erase( 0, pos );
317 
318             stream << "\\n" << indent << next_word;
319             next_space = second_line_column + next_word.size();
320         } else
321             stream << next_word; // simply write word
322 
323         next_word = "";
324     }
325 
326     wrapped += stream.str();
327 }
328 
is_numeric(const gengetopt_option * opt)329 bool is_numeric(const gengetopt_option *opt) {
330     switch (opt->type) {
331     case ARG_INT:
332     case ARG_SHORT:
333     case ARG_LONG:
334     case ARG_FLOAT:
335     case ARG_DOUBLE:
336     case ARG_LONGDOUBLE:
337     case ARG_LONGLONG:
338         return true;
339     default:
340         return false;
341     }
342 }
343 
string_contains(const char * s,const char * tofind)344 bool string_contains(const char *s, const char *tofind) {
345     if (!s)
346         return false;
347 
348     return (strstr(s, tofind) != 0);
349 }
350