Line data Source code
1 : /* src/toolbox/Option.cpp - Command line option parsing library
2 :
3 : Copyright (C) 1996-2014
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2, or (at
11 : your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 : #include "toolbox/Option.hpp"
26 : #include "toolbox/Debug.hpp"
27 : #include "toolbox/logging.hpp"
28 : #include "toolbox/OStream.hpp"
29 :
30 : namespace cacao {
31 :
32 : namespace option {
33 :
34 0 : OptionPrefix& root(){
35 0 : static OptionPrefix prefix("-");
36 0 : return prefix;
37 : }
38 :
39 1980 : OptionPrefix& xx_root(){
40 1980 : static OptionPrefix prefix("-XX:");
41 1980 : return prefix;
42 : }
43 :
44 : } // end namespace option
45 :
46 165 : OptionPrefix::OptionPrefix(const char* name) : name(name), s(std::strlen(name)) {
47 165 : }
48 1980 : void OptionPrefix::insert(OptionEntry* oe) {
49 1980 : children.insert(oe);
50 1980 : }
51 :
52 0 : void OptionParser::print_usage(OptionPrefix& root, FILE *fp) {
53 : static const char* blank29 = " "; // 29 spaces
54 0 : static const char* blank25 = blank29 + 4; // 25 spaces
55 0 : OStream OS(fp);
56 :
57 0 : std::set<OptionEntry*> sorted(root.begin(),root.end());
58 :
59 0 : for(std::set<OptionEntry*>::iterator i = sorted.begin(), e = sorted.end();
60 : i != e; ++i) {
61 0 : OptionEntry& oe = **i;
62 0 : OS << " " << root.get_name();
63 0 : std::size_t name_len = root.size() + oe.print(OS);
64 0 : if (name_len < (25-1)) {
65 0 : OS << (blank25 + name_len);
66 : } else {
67 0 : OS << nl << blank29;
68 : }
69 :
70 0 : const char* c = oe.get_desc();
71 0 : for (std::size_t i = 29; *c != 0; c++, i++) {
72 : /* If we are at the end of the line, break it. */
73 0 : if (i == 80) {
74 0 : OS << nl << blank29;
75 0 : i = 29;
76 : }
77 0 : OS << *c;
78 : }
79 0 : OS << nl;
80 0 : }
81 :
82 0 : }
83 :
84 0 : std::size_t option_print(OptionEntry& option, OStream& OS) {
85 0 : OS << option.get_name() << "=<value>";
86 0 : return option.size() + 8;
87 : }
88 :
89 0 : std::size_t option_print(OptionBase<bool>& option, OStream& OS) {
90 0 : OS << '+' << option.get_name();
91 0 : return option.size() + 1;
92 : }
93 :
94 :
95 : namespace {
96 :
97 0 : bool option_matcher(const char* a, std::size_t a_len,
98 : const char* b, std::size_t b_len) {
99 0 : return (a_len == b_len) && std::strncmp(a, b, a_len) == 0;
100 : }
101 :
102 : } // end anonymous namespace
103 :
104 0 : bool OptionParser::parse_option(OptionPrefix& root, const char* name, size_t name_len,
105 : const char* value, size_t value_len) {
106 0 : assert(std::strncmp(root.get_name(), name, std::strlen(root.get_name())) == 0);
107 0 : name += root.size();
108 0 : name_len -= root.size();
109 0 : assert(name_len > 0);
110 0 : if (name[0] == '-' || name[0] == '+') {
111 0 : assert(value_len == 0);
112 0 : assert(value == 0);
113 0 : value = name;
114 0 : value_len = 1;
115 0 : ++name;
116 0 : --name_len;
117 : }
118 0 : for(OptionPrefix::iterator i = root.begin(), e = root.end();
119 : i != e; ++i) {
120 0 : OptionEntry& oe = **i;
121 0 : if (option_matcher(oe.get_name(), oe.size(), name, name_len)) {
122 0 : if (oe.parse(value,value_len))
123 0 : return true;
124 0 : return false;
125 : }
126 : }
127 0 : return false;
128 : }
129 :
130 : template<>
131 0 : bool Option<const char*>::parse(const char* value, std::size_t value_len) {
132 0 : set_value(value);
133 0 : return true;
134 : }
135 :
136 : template<>
137 0 : bool Option<bool>::parse(const char* value, std::size_t value_len) {
138 0 : assert(value_len == 1);
139 0 : char first = value[0];
140 0 : if (first == '-') {
141 0 : set_value(false);
142 0 : return true;
143 : }
144 0 : if (first == '+') {
145 0 : set_value(true);
146 0 : return true;
147 : }
148 0 : ABORT_MSG("ERROR", "boolean option not valid: " << value);
149 0 : return false;
150 : }
151 :
152 : template<>
153 0 : bool Option<unsigned int>::parse(const char* value, std::size_t value_len) {
154 0 : int verb = os::atoi(value);
155 0 : set_value(verb >= 0 ? verb : 0);
156 0 : return true;
157 : }
158 :
159 : } // end namespace cacao
160 :
161 : /*
162 : * These are local overrides for various environment variables in Emacs.
163 : * Please do not remove this and leave it at the end of the file, where
164 : * Emacs will automagically detect them.
165 : * ---------------------------------------------------------------------
166 : * Local variables:
167 : * mode: c++
168 : * indent-tabs-mode: t
169 : * c-basic-offset: 4
170 : * tab-width: 4
171 : * End:
172 : * vim:noexpandtab:sw=4:ts=4:
173 : */
|