1 /*
2 
3 This file is from Nitrogen, an X11 background setter.
4 Copyright (C) 2006  Dave Foster & Javeed Shaikh
5 
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 
20 */
21 
22 #include "ArgParser.h"
23 #include "gcs-i18n.h"
24 
parse(int argc,char ** argv)25 bool ArgParser::parse
26 			(int argc, char ** argv) {
27     std::vector<Glib::ustring> argVec;
28     for (int i = 0; i < argc; i++) {
29         argVec.push_back(Glib::ustring(argv[i]));
30     }
31 
32     return this->parse(argVec);
33 }
34 
parse(std::vector<Glib::ustring> argVec)35 bool ArgParser::parse
36             (std::vector<Glib::ustring> argVec) {
37 	bool retval = true;
38 
39     for (std::vector<Glib::ustring>::const_iterator i = argVec.begin() + 1; i != argVec.end(); i++) {
40 		std::string arg(*i);
41 		std::string key = arg;
42 		std::string value;
43 
44 		if (key == "-h" || key == "--help") {
45 			received_args["help"];
46 			continue;
47 		}
48 
49 		std::string::size_type minuspos;
50 		if ((minuspos = key.find ("--")) == std::string::npos) {
51 			// this is not an arg, append it
52 			// to the extra string
53 			if (extra_arg_str.length ()) {
54 				// it has stuff, we need to add blank space
55 				extra_arg_str += " ";
56 			}
57 			extra_arg_str += key;
58 			continue;
59 		}
60 
61 		key = std::string (key, minuspos + 2);
62 
63 		std::string::size_type pos = key.find ('=');
64 		if (pos != std::string::npos) {
65 			key.erase (pos);
66 			value = std::string (arg, pos + 3);
67 		}
68 
69 		std::map<std::string, Arg>::const_iterator iter;
70 		Arg current;
71 
72 		if ((iter = expected_args.find (key)) == expected_args.end ()) {
73 			// ignore this argument and set the error string
74 			retval = false;
75 			error_str += _("Unexpected argument ") + key + "\n";
76 			continue;
77 		} else {
78 			current = iter->second;
79 		}
80 
81 		if (current.get_has_arg () && !value.length ()) {
82 			// this expects an arg, but has received none.
83 			retval = false;
84 			error_str += key + _(" expects an argument.") + "\n";
85 		} else if (value.length () && !current.get_has_arg ()) {
86 			retval = false;
87 			error_str += key + _(" does not expect an argument.") + "\n";
88 		}
89 
90 		if (conflicts (key)) {
91 			// use the previously supplied argument
92 			retval = false;
93 			error_str += key + _(" conflicts with another argument.") + "\n";
94 			continue;
95 		}
96 
97 		// save it.
98 		received_args[key] = value;
99 	}
100 
101 	return retval;
102 }
103 
help_text(void) const104 std::string ArgParser::help_text (void) const {
105 	std::string ret_str = _("Usage:");
106 
107 	std::map<std::string, Arg>::const_iterator iter;
108 
109 	for (iter=expected_args.begin();iter!=expected_args.end();iter++) {
110 		std::string name = "--" + iter->first;
111 		std::string arg = iter->second.get_has_arg () ? "=[arg]" : "";
112 		std::string desc = iter->second.get_desc ();
113 		ret_str += "\n\t" + name + arg + "\n\t\t" + desc;
114 	}
115 
116 	return ret_str;
117 }
118 
conflicts(std::string key)119 bool ArgParser::conflicts (std::string key) {
120 	std::vector< std::vector<std::string> >::const_iterator iter;
121 
122 	// Look through the exclusive iter. Cramped together to fit
123 	// into 80 columns.
124 	for (iter=exclusive.begin();iter!=exclusive.end();iter++) {
125 		std::vector<std::string>::const_iterator str_iter;
126 
127 		// Look through every option in this exclusive series.
128 		for (str_iter=iter->begin();str_iter!=iter->end();str_iter++) {
129 			if (*str_iter == key) {
130 				// this option cannot be used with any others
131 				// in this vector.
132 				// check if any of the options in this vector
133 				// have already been specified.
134 				std::vector<std::string>::const_iterator new_str_iter;
135 				for (new_str_iter=iter->begin();new_str_iter!=iter->end();new_str_iter++) {
136 					if (received_args.find (*new_str_iter) != received_args.end ()) {
137 						// this option conflicts with a
138 						// previous option.
139 						return true;
140 					}
141 				}
142 				// no conflicts.
143 				return false;
144 			}
145 		}
146 	}
147 
148 	return false;
149 }
150