1 // Copyright Vladimir Prus 2002-2004.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt
4 // or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 /** This example shows how to handle response file.
7 
8     For a test, build and run:
9        response_file -I foo @response_file.rsp
10 
11     The expected output is:
12       Include paths: foo bar biz
13 
14     Thanks to Hartmut Kaiser who raised the issue of response files
15     and discussed the possible approach.
16 */
17 
18 
19 #include <boost/program_options/options_description.hpp>
20 #include <boost/program_options/parsers.hpp>
21 #include <boost/program_options/variables_map.hpp>
22 #include <boost/tokenizer.hpp>
23 #include <boost/token_functions.hpp>
24 using namespace boost;
25 using namespace boost::program_options;
26 
27 #include <iostream>
28 #include <fstream>
29 using namespace std;
30 
31 // Additional command line parser which interprets '@something' as a
32 // option "config-file" with the value "something"
at_option_parser(string const & s)33 pair<string, string> at_option_parser(string const&s)
34 {
35     if ('@' == s[0])
36         return std::make_pair(string("response-file"), s.substr(1));
37     else
38         return pair<string, string>();
39 }
40 
main(int ac,char * av[])41 int main(int ac, char* av[])
42 {
43     try {
44         options_description desc("Allowed options");
45         desc.add_options()
46             ("help", "produce a help message")
47             ("include-path,I", value< vector<string> >()->composing(),
48                  "include path")
49             ("magic", value<int>(), "magic value")
50             ("response-file", value<string>(),
51                  "can be specified with '@name', too")
52         ;
53 
54         variables_map vm;
55         store(command_line_parser(ac, av).options(desc)
56               .extra_parser(at_option_parser).run(), vm);
57 
58         if (vm.count("help")) {
59             cout << desc;
60         }
61         if (vm.count("response-file")) {
62             // Load the file and tokenize it
63             ifstream ifs(vm["response-file"].as<string>().c_str());
64             if (!ifs) {
65                 cout << "Could not open the response file\n";
66                 return 1;
67             }
68             // Read the whole file into a string
69             stringstream ss;
70             ss << ifs.rdbuf();
71             // Split the file content
72             char_separator<char> sep(" \n\r");
73             string sstr = ss.str();
74             tokenizer<char_separator<char> > tok(sstr, sep);
75             vector<string> args;
76             copy(tok.begin(), tok.end(), back_inserter(args));
77             // Parse the file and store the options
78             store(command_line_parser(args).options(desc).run(), vm);
79         }
80 
81         if (vm.count("include-path")) {
82             const vector<string>& s = vm["include-path"].as<vector< string> >();
83             cout << "Include paths: ";
84             copy(s.begin(), s.end(), ostream_iterator<string>(cout, " "));
85             cout << "\n";
86         }
87         if (vm.count("magic")) {
88             cout << "Magic value: " << vm["magic"].as<int>() << "\n";
89         }
90     }
91     catch (std::exception& e) {
92         cout << e.what() << "\n";
93     }
94 }
95