819fe493f97078521bb6b9a7b97583bef89f5abcMark Andrews//
d63ae51ba337165172a9b50fd5d84805ffe50044Tinderbox User// Automated Testing Framework (atf)
819fe493f97078521bb6b9a7b97583bef89f5abcMark Andrews//
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews// Copyright (c) 2007 The NetBSD Foundation, Inc.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews// All rights reserved.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews//
819fe493f97078521bb6b9a7b97583bef89f5abcMark Andrews// Redistribution and use in source and binary forms, with or without
f5d30e2864e048a42c4dc1134993ae7efdb5d6c3Mark Andrews// modification, are permitted provided that the following conditions
26440aaebba1acb5c8810f7faa26ad3b7553762eMark Andrews// are met:
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// 1. Redistributions of source code must retain the above copyright
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// notice, this list of conditions and the following disclaimer.
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// 2. Redistributions in binary form must reproduce the above copyright
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// notice, this list of conditions and the following disclaimer in the
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// documentation and/or other materials provided with the distribution.
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews//
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
bff64bf12b58a6f80e740e94f2e42a32df18113aEvan Hunt// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews//
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews#include <cassert>
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews#include <sstream>
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews#include "parser.hpp"
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews#include "text.hpp"
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrews
33d96fbbc8aa221508f3c780539bf44810fd2c9cMark Andrewsnamespace impl = tools::parser;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt#define IMPL_NAME "tools::parser"
83a28ca274521e15086fc39febde507bcc4e145eMark Andrews
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt// ------------------------------------------------------------------------
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt// The "parse_error" class.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntimpl::parse_error::parse_error(size_t line, std::string msg) :
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt std::runtime_error(msg),
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein std::pair< size_t, std::string >(line, msg)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::parse_error::~parse_error(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein throw()
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinconst char*
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::parse_error::what(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const throw()
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein try {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein std::ostringstream oss;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein oss << "LONELY PARSE ERROR: " << first << ": " << second;
f5d30e2864e048a42c4dc1134993ae7efdb5d6c3Mark Andrews m_msg = oss.str();
1b06367c345e972a0c719a6e821db3e875f20c3bMark Andrews return m_msg.c_str();
c1a883f2e04d94e99c433b1f6cfd0c0338f4ed85Mark Andrews } catch (...) {
8077efca7d2ec3b9bf0428386a1ec2fcbcdf437bAutomatic Updater return "Could not format message for parsing error.";
d2bdd5b314d3ee2250c740fe5fff8b91ab3731b2Tinderbox User }
85167bb10f76e71c3c8519e2135e31d249f54805Tinderbox User}
19c7b1a0293498a3e36692c59646ed6e15ffc8d0Tinderbox User
feb1ccdaf161557d2f160974c16c294a6cdd8c3aTinderbox Userimpl::parse_error::operator std::string(void)
d63ae51ba337165172a9b50fd5d84805ffe50044Tinderbox User const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return tools::text::to_string(first) + ": " + second;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt// The "parse_errors" class.
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntimpl::parse_errors::parse_errors(void) :
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt std::runtime_error("No parsing errors yet")
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_msg.clear();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrewsimpl::parse_errors::~parse_errors(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein throw()
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinconst char*
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::parse_errors::what(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const throw()
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein try {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt m_msg = tools::text::join(*this, "\n");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return m_msg.c_str();
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt } catch (...) {
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews return "Could not format messages for parsing errors.";
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein }
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// The "format_error" class.
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::format_error::format_error(const std::string& w) :
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein std::runtime_error(w.c_str())
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// The "token" class.
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::token::token(void) :
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_inited(false)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::token::token(size_t p_line,
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const token_type& p_type,
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const std::string& p_text) :
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_inited(true),
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_line(p_line),
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_type(p_type),
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_text(p_text)
d3cbd6b05c16c6e0e86c1651bda3b3ee06574d62Mark Andrews{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
819fe493f97078521bb6b9a7b97583bef89f5abcMark Andrews
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinsize_t
d3cbd6b05c16c6e0e86c1651bda3b3ee06574d62Mark Andrewsimpl::token::lineno(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const
9f5222620cd3b68f88a5d8cc01b194ea4abb0754Evan Hunt{
9f5222620cd3b68f88a5d8cc01b194ea4abb0754Evan Hunt return m_line;
9f5222620cd3b68f88a5d8cc01b194ea4abb0754Evan Hunt}
9f5222620cd3b68f88a5d8cc01b194ea4abb0754Evan Hunt
9f5222620cd3b68f88a5d8cc01b194ea4abb0754Evan Huntconst impl::token_type&
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::token::type(void)
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt return m_type;
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinconst std::string&
8d709e3ee443222cd35e44eadc9a4c0a8d92fec2Rob Austeinimpl::token::text(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return m_text;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::token::operator bool(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return m_inited;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinbool
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::token::operator!(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return !m_inited;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// The "header_entry" class.
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::header_entry::header_entry(void)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::header_entry::header_entry(const std::string& n, const std::string& v,
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein attrs_map as) :
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_name(n),
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_value(v),
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein m_attrs(as)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinconst std::string&
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::header_entry::name(void) const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return m_name;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinconst std::string&
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::header_entry::value(void) const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return m_value;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinconst impl::attrs_map&
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::header_entry::attrs(void) const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return m_attrs;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinbool
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::header_entry::has_attr(const std::string& n) const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return m_attrs.find(n) != m_attrs.end();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinconst std::string&
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::header_entry::get_attr(const std::string& n) const
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein attrs_map::const_iterator iter = m_attrs.find(n);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein assert(iter != m_attrs.end());
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return (*iter).second;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// The header tokenizer.
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinnamespace header {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic const impl::token_type eof_type = 0;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic const impl::token_type nl_type = 1;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic const impl::token_type text_type = 2;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic const impl::token_type colon_type = 3;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic const impl::token_type semicolon_type = 4;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic const impl::token_type dblquote_type = 5;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic const impl::token_type equal_type = 6;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinclass tokenizer : public impl::tokenizer< std::istream > {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinpublic:
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein tokenizer(std::istream& is, size_t curline) :
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein impl::tokenizer< std::istream >
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein (is, true, eof_type, nl_type, text_type, curline)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein add_delim(';', semicolon_type);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein add_delim(':', colon_type);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein add_delim('=', equal_type);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein add_quote('"', dblquote_type);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein }
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein};
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::parser< header::tokenizer >&
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinread(impl::parser< header::tokenizer >& p, impl::header_entry& he)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein using namespace header;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein impl::token t = p.expect(text_type, nl_type, "a header name");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if (t.type() == nl_type) {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein he = impl::header_entry();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return p;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein }
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein std::string hdr_name = t.text();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein t = p.expect(colon_type, "`:'");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein t = p.expect(text_type, "a textual value");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein std::string hdr_value = t.text();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein impl::attrs_map attrs;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein for (;;) {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein t = p.expect(eof_type, semicolon_type, nl_type,
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein "eof, `;' or new line");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if (t.type() == eof_type || t.type() == nl_type)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein break;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein t = p.expect(text_type, "an attribute name");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein std::string attr_name = t.text();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein t = p.expect(equal_type, "`='");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein t = p.expect(text_type, "word or quoted string");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein std::string attr_value = t.text();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein attrs[attr_name] = attr_value;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein }
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein he = impl::header_entry(hdr_name, hdr_value, attrs);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return p;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstatic
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstd::ostream&
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinwrite(std::ostream& os, const impl::header_entry& he)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein std::string line = he.name() + ": " + he.value();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein impl::attrs_map as = he.attrs();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein for (impl::attrs_map::const_iterator iter = as.begin(); iter != as.end();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein iter++) {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein assert((*iter).second.find('\"') == std::string::npos);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein line += "; " + (*iter).first + "=\"" + (*iter).second + "\"";
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein }
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein os << line << "\n";
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return os;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein} // namespace header
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// Free functions.
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein// ------------------------------------------------------------------------
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinstd::pair< size_t, impl::headers_map >
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::read_headers(std::istream& is, size_t curline)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein using impl::format_error;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein headers_map hm;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein //
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein // Grammar
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein //
3001a1b4e6298466882a4147307b4c28a3b08f91Mark Andrews // header = entry+ nl
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein // entry = line nl
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein // line = text colon text
561a29af8c54a216e7d30b5b4f6e0d21661654ecMark Andrews // (semicolon (text equal (text | dblquote string dblquote)))*
561a29af8c54a216e7d30b5b4f6e0d21661654ecMark Andrews // string = quoted_string
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein //
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein header::tokenizer tkz(is, curline);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein impl::parser< header::tokenizer > p(tkz);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein bool first = true;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein for (;;) {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein try {
3001a1b4e6298466882a4147307b4c28a3b08f91Mark Andrews header_entry he;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if (!header::read(p, he).good() || he.name().empty())
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein break;
561a29af8c54a216e7d30b5b4f6e0d21661654ecMark Andrews
0f78f780648806bcb3e374b7dafac73e6c558ea8Mark Andrews if (first && he.name() != "Content-Type")
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein throw format_error("Could not determine content type");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein else
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein first = false;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein hm[he.name()] = he;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein } catch (const impl::parse_error& pe) {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein p.add_error(pe);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein p.reset(header::nl_type);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein }
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein }
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if (!is.good())
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein throw format_error("Unexpected end of stream");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein return std::pair< size_t, headers_map >(tkz.lineno(), hm);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
3001a1b4e6298466882a4147307b4c28a3b08f91Mark Andrewsvoid
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::write_headers(const impl::headers_map& hm, std::ostream& os)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein assert(!hm.empty());
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein headers_map::const_iterator ct = hm.find("Content-Type");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein assert(ct != hm.end());
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein header::write(os, (*ct).second);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein for (headers_map::const_iterator iter = hm.begin(); iter != hm.end();
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein iter++) {
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if ((*iter).first != "Content-Type")
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein header::write(os, (*iter).second);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein }
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein os << "\n";
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinvoid
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austeinimpl::validate_content_type(const impl::headers_map& hm, const std::string& fmt,
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein int version)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein{
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein using impl::format_error;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein headers_map::const_iterator iter = hm.find("Content-Type");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if (iter == hm.end())
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein throw format_error("Could not determine content type");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const header_entry& he = (*iter).second;
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if (he.value() != fmt)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein throw format_error("Mismatched content type: expected `" + fmt +
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein "' but got `" + he.value() + "'");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if (!he.has_attr("version"))
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein throw format_error("Could not determine version");
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein const std::string& vstr = tools::text::to_string(version);
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein if (he.get_attr("version") != vstr)
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein throw format_error("Mismatched version: expected `" +
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein vstr + "' but got `" +
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein he.get_attr("version") + "'");
7ba5dc6485e54258101da72455974dde38d04289Mark Andrews}
268a4475065fe6a8cd7cc707820982cf5e98f430Rob Austein