1 /*-
2  * Copyright (c) 2004 Jacques A. Vidrine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 #include <sys/param.h>
28 #include <unistd.h>
29 
30 #include <cerrno>
31 #include <exception>
32 #include <iostream>
33 #include <fstream>
34 #include <functional>
35 #include <map>
36 #include <memory>
37 #include <stack>
38 #include <string>
39 #include <cstring>
40 #include <vector>
41 
42 #include <vuxml/vuxml.hh>
43 #include <vuxml/parser.hh>
44 #include <vuxml/handlers.hh>
45 #include <vuxml/processors.hh>
46 
47 using namespace vuxml;
48 
49 static int	realmain(int ac, char *av[]);
50 static void	usage();
51 
52 int
main(int ac,char * av[])53 main(int ac, char *av[])
54 {
55 	try {
56 		return realmain(ac, av);
57 	} catch (except &e) {
58 		LOG << e.what() << '\n';
59 		return 1;
60 	} catch (std::exception &e) {
61 		LOG << "Exception: " << e.what() << '\n';
62 		return 100;
63 	} catch (...) {
64 		LOG << "Exception.\n";
65 		return 101;
66 	}
67 	return 0;
68 }
69 
70 
71 static int
realmain(int ac,char * av[])72 realmain(int ac, char *av[])
73 {
74 	int ch;
75 	bool do_all = false;
76 	std::string output_format("text");
77 	std::string from_file;
78 	std::string directory;
79 
80 	opterr = 0;
81 	while ((ch = getopt(ac, av, "ad:f:t:")) != -1)
82 		switch (ch) {
83 		case 'a':
84 			do_all = true;
85 			break;
86 		case 'd':
87 			directory = optarg;
88 			break;
89 		case 't':
90 			output_format = optarg;
91 			break;
92 		case 'f':
93 			from_file = optarg;
94 			break;
95 		case 'h':
96 		case 'H':
97 		case '?':
98 		default:
99 			usage();
100 			return 1;
101 		}
102 	ac -= optind;
103 	av += optind;
104 
105 	if (ac < 1) {
106 		usage();
107 		return 1;
108 	}
109 
110 	std::vector<std::string> args(&av[1], &av[ac]);
111 	if (from_file.size() > 0) {
112 		args.resize(0);
113 		std::string arg;
114 		std::istream *in;
115 		std::ifstream infile;
116 		if (from_file == "-" || from_file == "/dev/stdin")
117 			in = &std::cin;
118 		else {
119 			in = &infile;
120 			infile.open(from_file.c_str(), std::ios::in);
121 			int sverrno = errno;
122 			if (infile.fail()) {
123 				LOG << "Failed to open file `" << from_file
124 				    << "' for reading.\n";
125 				LOG << "Possible reason: " << strerror(sverrno)
126 				    << '\n';
127 				return 1;
128 			}
129 		}
130 		while (*in >> arg)
131 			args.push_back(arg);
132 	}
133 
134 	std::ifstream db;
135 	db.open(av[0], std::ios::in|std::ios::binary);
136 	int sverrno = errno;
137 
138 	if (db.fail()) {
139 		LOG << "Failed to open file `" << av[0] << "' for reading.\n";
140 		LOG << "Possible reason: " << strerror(sverrno) << '\n';
141 		return 1;
142 	}
143 
144 	std::auto_ptr<EntryProcessor> writer;
145 	if (output_format == "text")
146 		writer.reset(new TextWriter(std::cout));
147 	else if (output_format == "vuxml")
148 		writer.reset(new VuXMLWriter(std::cout));
149 	else if (output_format == "xhtml")
150 		writer.reset(new XHTMLWriter(std::cout, 1));
151 	else if (output_format == "xhtml-files")
152 		writer.reset(new XHTMLFilesWriter(directory));
153 	else {
154 		LOG << "Unknown output format `" << output_format << "'\n";
155 		usage();
156 		return 1;
157 	}
158 
159 	std::auto_ptr<EntryProcessor> matcher;
160 	if (do_all)
161 		matcher.reset(new AllMatcher(*writer));
162 	else
163 		matcher.reset(new VersionMatcher(args, *writer));
164 
165 	matcher->start();
166 	BasicHandler handler(*matcher);
167 	Parser parser;
168 	parser.setHandler(handler);
169 	parser.parseStream(db);
170 	matcher->end();
171 	if (parser.fail()) {
172 		LOG << "Parsing failed @ line " << parser.getLine() << ":\n"
173 		    << parser.getErrorString() << '\n';
174 		return 1;
175 	}
176 	return 0;
177 }
178 
179 
180 static void
usage()181 usage()
182 {
183 	LOG << "VuXML Query Tool (" << PACKAGE_NAME << ") "
184 	    << PACKAGE_VERSION << "\n"
185 	    << "Report bugs to " << PACKAGE_BUGREPORT << "\n\n"
186 	    << "Usage:	 " << getprogname()
187 	    << " [options] {filename} {package1} {package2} ... {packageN}\n"
188 	    << "Options:\n"
189 	    << "  -a	      Output *all* entries.\n"
190 	    << "  -d {dir}    Write output files into specified directory.\n"
191 	    << "  -f {file}   Read package names from specified file.\n"
192 	    << "  -h	      Display this usage summary.\n"
193 	    << "  -t {format} Choose output format.\n"
194 	    << "Formats: text, vuxml, xhtml, xhtml-files\n";
195 }
196