1245803Stheraven/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4245803Stheraven * Copyright (c) 2013 David Chisnall 5245803Stheraven * All rights reserved. 6245803Stheraven * 7245803Stheraven * This software was developed by SRI International and the University of 8245803Stheraven * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 9245803Stheraven * ("CTSRD"), as part of the DARPA CRASH research programme. 10245803Stheraven * 11245803Stheraven * Redistribution and use in source and binary forms, with or without 12245803Stheraven * modification, are permitted provided that the following conditions 13245803Stheraven * are met: 14245803Stheraven * 1. Redistributions of source code must retain the above copyright 15245803Stheraven * notice, this list of conditions and the following disclaimer. 16245803Stheraven * 2. Redistributions in binary form must reproduce the above copyright 17245803Stheraven * notice, this list of conditions and the following disclaimer in the 18245803Stheraven * documentation and/or other materials provided with the distribution. 19245803Stheraven * 20245803Stheraven * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21245803Stheraven * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22245803Stheraven * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23245803Stheraven * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24245803Stheraven * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25245803Stheraven * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26245803Stheraven * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27245803Stheraven * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28245803Stheraven * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29245803Stheraven * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30245803Stheraven * SUCH DAMAGE. 31245803Stheraven * 32245803Stheraven * $FreeBSD: stable/11/usr.bin/dtc/input_buffer.hh 330449 2018-03-05 07:26:05Z eadler $ 33245803Stheraven */ 34245803Stheraven 35245803Stheraven#ifndef _INPUT_BUFFER_HH_ 36245803Stheraven#define _INPUT_BUFFER_HH_ 37245803Stheraven#include "util.hh" 38245803Stheraven#include <assert.h> 39318093Sgonzo#include <stack> 40318093Sgonzo#include <string> 41318093Sgonzo#include <unordered_set> 42245803Stheraven 43245803Stheravennamespace dtc 44245803Stheraven{ 45245803Stheraven 46292876Stheravennamespace { 47292876Stheravenstruct expression; 48292876Stheraventypedef std::unique_ptr<expression> expression_ptr; 49292876Stheraven} 50292876Stheraven 51245803Stheraven/** 52245803Stheraven * Class encapsulating the input file. Can be used as a const char*, but has 53245803Stheraven * range checking. Attempting to access anything out of range will return a 0 54245803Stheraven * byte. The input buffer can be cheaply copied, without copying the 55245803Stheraven * underlying memory, however it is the user's responsibility to ensure that 56245803Stheraven * such copies do not persist beyond the lifetime of the underlying memory. 57245803Stheraven * 58245803Stheraven * This also contains methods for reporting errors and for consuming the token 59245803Stheraven * stream. 60245803Stheraven */ 61245803Stheravenclass input_buffer 62245803Stheraven{ 63318093Sgonzo friend class text_input_buffer; 64245803Stheraven protected: 65245803Stheraven /** 66245803Stheraven * The buffer. This class doesn't own the buffer, but the 67245803Stheraven * mmap_input_buffer subclass does. 68245803Stheraven */ 69245803Stheraven const char* buffer; 70245803Stheraven /** 71245803Stheraven * The size of the buffer. 72245803Stheraven */ 73245803Stheraven int size; 74245803Stheraven private: 75245803Stheraven /** 76245803Stheraven * The current place in the buffer where we are reading. This class 77245803Stheraven * keeps a separate size, pointer, and cursor so that we can move 78245803Stheraven * forwards and backwards and still have checks that we haven't fallen 79245803Stheraven * off either end. 80245803Stheraven */ 81245803Stheraven int cursor; 82245803Stheraven /** 83245803Stheraven * Private constructor. This is used to create input buffers that 84245803Stheraven * refer to the same memory, but have different cursors. 85245803Stheraven */ 86245803Stheraven input_buffer(const char* b, int s, int c) : buffer(b), size(s), 87245803Stheraven cursor(c) {} 88318093Sgonzo public: 89245803Stheraven /** 90318093Sgonzo * Returns the file name associated with this buffer. 91245803Stheraven */ 92318093Sgonzo virtual const std::string &filename() const 93318093Sgonzo { 94318093Sgonzo static std::string s; 95318093Sgonzo return s; 96318093Sgonzo } 97318093Sgonzo static std::unique_ptr<input_buffer> buffer_for_file(const std::string &path, 98318093Sgonzo bool warn=true); 99245803Stheraven /** 100318093Sgonzo * Skips all characters in the input until the specified character is 101318093Sgonzo * encountered. 102318093Sgonzo */ 103318093Sgonzo void skip_to(char); 104318093Sgonzo /** 105318093Sgonzo * Parses up to a specified character and returns the intervening 106318093Sgonzo * characters as a string. 107318093Sgonzo */ 108318093Sgonzo std::string parse_to(char); 109318093Sgonzo /** 110289935Stheraven * Return whether all input has been consumed. 111289935Stheraven */ 112289935Stheraven bool finished() { return cursor >= size; } 113289935Stheraven /** 114245803Stheraven * Virtual destructor. Does nothing, but exists so that subclasses 115245803Stheraven * that own the memory can run cleanup code for deallocating it. 116245803Stheraven */ 117245803Stheraven virtual ~input_buffer() {}; 118245803Stheraven /** 119245803Stheraven * Constructs an empty buffer. 120245803Stheraven */ 121245803Stheraven input_buffer() : buffer(0), size(0), cursor(0) {} 122245803Stheraven /** 123245803Stheraven * Constructs a new buffer with a specified memory region and size. 124245803Stheraven */ 125245803Stheraven input_buffer(const char* b, int s) : buffer(b), size(s), cursor(0){} 126245803Stheraven /** 127245803Stheraven * Returns a new input buffer referring into this input, clamped to the 128245803Stheraven * specified size. If the requested buffer would fall outside the 129245803Stheraven * range of this one, then it returns an empty buffer. 130245803Stheraven * 131245803Stheraven * The returned buffer shares the same underlying storage as the 132245803Stheraven * original. This is intended to be used for splitting up the various 133245803Stheraven * sections of a device tree blob. Requesting a size of 0 will give a 134245803Stheraven * buffer that extends to the end of the available memory. 135245803Stheraven */ 136245803Stheraven input_buffer buffer_from_offset(int offset, int s=0); 137245803Stheraven /** 138245803Stheraven * Dereferencing operator, allows the buffer to be treated as a char* 139245803Stheraven * and dereferenced to give a character. This returns a null byte if 140245803Stheraven * the cursor is out of range. 141245803Stheraven */ 142245803Stheraven inline char operator*() 143245803Stheraven { 144245803Stheraven if (cursor >= size) { return '\0'; } 145245803Stheraven if (cursor < 0) { return '\0'; } 146245803Stheraven return buffer[cursor]; 147245803Stheraven } 148245803Stheraven /** 149245803Stheraven * Array subscripting operator, returns a character at the specified 150245803Stheraven * index offset from the current cursor. The offset may be negative, 151245803Stheraven * to reread characters that have already been read. If the current 152245803Stheraven * cursor plus offset is outside of the range, this returns a nul 153245803Stheraven * byte. 154245803Stheraven */ 155245803Stheraven inline char operator[](int offset) 156245803Stheraven { 157245803Stheraven if (cursor + offset >= size) { return '\0'; } 158245803Stheraven if (cursor + offset < 0) { return '\0'; } 159245803Stheraven return buffer[cursor + offset]; 160245803Stheraven } 161245803Stheraven /** 162245803Stheraven * Increments the cursor, iterating forward in the buffer. 163245803Stheraven */ 164245803Stheraven inline input_buffer &operator++() 165245803Stheraven { 166245803Stheraven cursor++; 167245803Stheraven return *this; 168245803Stheraven } 169328495Skevans const char *begin() 170328495Skevans { 171328495Skevans return buffer; 172328495Skevans } 173328495Skevans const char *end() 174328495Skevans { 175328495Skevans return buffer + size; 176328495Skevans } 177245803Stheraven /** 178245803Stheraven * Consumes a character. Moves the cursor one character forward if the 179245803Stheraven * next character matches the argument, returning true. If the current 180245803Stheraven * character does not match the argument, returns false. 181245803Stheraven */ 182245803Stheraven inline bool consume(char c) 183245803Stheraven { 184318093Sgonzo if (*(*this) == c) 185245803Stheraven { 186245803Stheraven ++(*this); 187245803Stheraven return true; 188245803Stheraven } 189245803Stheraven return false; 190245803Stheraven } 191245803Stheraven /** 192245803Stheraven * Consumes a string. If the (null-terminated) string passed as the 193245803Stheraven * argument appears in the input, advances the cursor to the end and 194245803Stheraven * returns true. Returns false if the string does not appear at the 195245803Stheraven * current point in the input. 196245803Stheraven */ 197245803Stheraven bool consume(const char *str); 198245803Stheraven /** 199245803Stheraven * Reads an integer in base 8, 10, or 16. Returns true and advances 200245803Stheraven * the cursor to the end of the integer if the cursor points to an 201245803Stheraven * integer, returns false and does not move the cursor otherwise. 202245803Stheraven * 203245803Stheraven * The parsed value is returned via the argument. 204245803Stheraven */ 205289935Stheraven bool consume_integer(unsigned long long &outInt); 206245803Stheraven /** 207292876Stheraven * Reads an arithmetic expression (containing any of the normal C 208292876Stheraven * operators), evaluates it, and returns the result. 209292876Stheraven */ 210292876Stheraven bool consume_integer_expression(unsigned long long &outInt); 211292876Stheraven /** 212318093Sgonzo * Consumes two hex digits and return the resulting byte via the first 213318093Sgonzo * argument. If the next two characters are hex digits, returns true 214318093Sgonzo * and advances the cursor. If not, then returns false and leaves the 215318093Sgonzo * cursor in place. 216318093Sgonzo */ 217318093Sgonzo bool consume_hex_byte(uint8_t &outByte); 218318093Sgonzo /** 219245803Stheraven * Template function that consumes a binary value in big-endian format 220245803Stheraven * from the input stream. Returns true and advances the cursor if 221245803Stheraven * there is a value of the correct size. This function assumes that 222245803Stheraven * all values must be natively aligned, and so advances the cursor to 223245803Stheraven * the correct alignment before reading. 224245803Stheraven */ 225245803Stheraven template<typename T> 226245803Stheraven bool consume_binary(T &out) 227245803Stheraven { 228245803Stheraven int align = 0; 229245803Stheraven int type_size = sizeof(T); 230245803Stheraven if (cursor % type_size != 0) 231245803Stheraven { 232245803Stheraven align = type_size - (cursor % type_size); 233245803Stheraven } 234245803Stheraven if (size < cursor + align + type_size) 235245803Stheraven { 236245803Stheraven return false; 237245803Stheraven } 238245803Stheraven cursor += align; 239245803Stheraven assert(cursor % type_size == 0); 240245803Stheraven out = 0; 241245803Stheraven for (int i=0 ; i<type_size ; ++i) 242245803Stheraven { 243318093Sgonzo if (size < cursor) 244318093Sgonzo { 245318093Sgonzo return false; 246318093Sgonzo } 247245803Stheraven out <<= 8; 248245803Stheraven out |= (((T)buffer[cursor++]) & 0xff); 249245803Stheraven } 250245803Stheraven return true; 251245803Stheraven } 252292876Stheraven#ifndef NDEBUG 253245803Stheraven /** 254245803Stheraven * Dumps the current cursor value and the unconsumed values in the 255245803Stheraven * input buffer to the standard error. This method is intended solely 256245803Stheraven * for debugging. 257245803Stheraven */ 258245803Stheraven void dump(); 259292876Stheraven#endif 260245803Stheraven}; 261245803Stheraven/** 262245803Stheraven * Explicit specialisation for reading a single byte. 263245803Stheraven */ 264245803Stheraventemplate<> 265245803Stheraveninline bool input_buffer::consume_binary(uint8_t &out) 266245803Stheraven{ 267245803Stheraven if (size < cursor + 1) 268245803Stheraven { 269245803Stheraven return false; 270245803Stheraven } 271245803Stheraven out = buffer[cursor++]; 272245803Stheraven return true; 273245803Stheraven} 274245803Stheraven 275245803Stheraven/** 276318093Sgonzo * An input buffer subclass used for parsing DTS files. This manages a stack 277318093Sgonzo * of input buffers to handle /input/ operations. 278245803Stheraven */ 279318093Sgonzoclass text_input_buffer 280245803Stheraven{ 281318093Sgonzo std::unordered_set<std::string> defines; 282245803Stheraven /** 283318093Sgonzo * The cursor is the input into the input stream where we are currently reading. 284245803Stheraven */ 285318093Sgonzo int cursor = 0; 286245803Stheraven /** 287318093Sgonzo * The current stack of includes. The current input is always from the top 288318093Sgonzo * of the stack. 289245803Stheraven */ 290318093Sgonzo std::stack<std::shared_ptr<input_buffer>> input_stack; 291245803Stheraven /** 292318093Sgonzo * 293245803Stheraven */ 294318093Sgonzo const std::vector<std::string> include_paths; 295245803Stheraven /** 296318093Sgonzo * Reads forward past any spaces. The DTS format is not whitespace 297318093Sgonzo * sensitive and so we want to scan past whitespace when reading it. 298245803Stheraven */ 299318093Sgonzo void skip_spaces(); 300318093Sgonzo /** 301318093Sgonzo * Returns the character immediately after the current one. 302318093Sgonzo * 303318093Sgonzo * This method does not look between files. 304318093Sgonzo */ 305318093Sgonzo char peek(); 306318093Sgonzo /** 307318093Sgonzo * If a /include/ token is encountered, then look up the corresponding 308318093Sgonzo * input file, push it onto the input stack, and continue. 309318093Sgonzo */ 310318093Sgonzo void handle_include(); 311318093Sgonzo /** 312318093Sgonzo * The base directory for this file. 313318093Sgonzo */ 314318093Sgonzo const std::string dir; 315318093Sgonzo /** 316318093Sgonzo * The file where dependencies should be output. 317318093Sgonzo */ 318318093Sgonzo FILE *depfile; 319318093Sgonzo public: 320318093Sgonzo /** 321318093Sgonzo * Construct a new text input buffer with the specified buffer as the start 322318093Sgonzo * of parsing and the specified set of input paths for handling new 323318093Sgonzo * inclusions. 324318093Sgonzo */ 325318093Sgonzo text_input_buffer(std::unique_ptr<input_buffer> &&b, 326318093Sgonzo std::unordered_set<std::string> &&d, 327318093Sgonzo std::vector<std::string> &&i, 328318093Sgonzo const std::string directory, 329318093Sgonzo FILE *deps) 330318093Sgonzo : defines(d), include_paths(i), dir(directory), depfile(deps) 331318093Sgonzo { 332318093Sgonzo input_stack.push(std::move(b)); 333318093Sgonzo } 334318093Sgonzo /** 335318093Sgonzo * Skips all characters in the input until the specified character is 336318093Sgonzo * encountered. 337318093Sgonzo */ 338318093Sgonzo void skip_to(char); 339318093Sgonzo /** 340318093Sgonzo * Parse an expression. If `stopAtParen` is set, then only parse a number 341318093Sgonzo * or a parenthetical expression, otherwise assume that either is the 342318093Sgonzo * left-hand side of a binary expression and try to parse the right-hand 343318093Sgonzo * side. 344318093Sgonzo */ 345318093Sgonzo expression_ptr parse_expression(bool stopAtParen=false); 346318093Sgonzo /** 347318093Sgonzo * Parse a binary expression, having already parsed the right-hand side. 348318093Sgonzo */ 349318093Sgonzo expression_ptr parse_binary_expression(expression_ptr lhs); 350318093Sgonzo /** 351318093Sgonzo * Return whether all input has been consumed. 352318093Sgonzo */ 353318093Sgonzo bool finished() 354318093Sgonzo { 355318093Sgonzo return input_stack.empty() || 356318093Sgonzo ((input_stack.size() == 1) && input_stack.top()->finished()); 357318093Sgonzo } 358318093Sgonzo /** 359318093Sgonzo * Dereferencing operator. Returns the current character in the top input buffer. 360318093Sgonzo */ 361318093Sgonzo inline char operator*() 362318093Sgonzo { 363318093Sgonzo if (input_stack.empty()) 364318093Sgonzo { 365318093Sgonzo return 0; 366318093Sgonzo } 367318093Sgonzo return *(*input_stack.top()); 368318093Sgonzo } 369318093Sgonzo /** 370318093Sgonzo * Increments the cursor, iterating forward in the buffer. 371318093Sgonzo */ 372318093Sgonzo inline text_input_buffer &operator++() 373318093Sgonzo { 374318093Sgonzo if (input_stack.empty()) 375318093Sgonzo { 376318093Sgonzo return *this; 377318093Sgonzo } 378318093Sgonzo cursor++; 379318093Sgonzo auto &top = *input_stack.top(); 380318093Sgonzo ++top; 381318093Sgonzo if (top.finished()) 382318093Sgonzo { 383318093Sgonzo input_stack.pop(); 384318093Sgonzo } 385318093Sgonzo return *this; 386318093Sgonzo } 387318093Sgonzo /** 388318093Sgonzo * Consumes a character. Moves the cursor one character forward if the 389318093Sgonzo * next character matches the argument, returning true. If the current 390318093Sgonzo * character does not match the argument, returns false. 391318093Sgonzo */ 392318093Sgonzo inline bool consume(char c) 393318093Sgonzo { 394318093Sgonzo if (*(*this) == c) 395318093Sgonzo { 396318093Sgonzo ++(*this); 397318093Sgonzo return true; 398318093Sgonzo } 399318093Sgonzo return false; 400318093Sgonzo } 401318093Sgonzo /** 402318093Sgonzo * Consumes a string. If the (null-terminated) string passed as the 403318093Sgonzo * argument appears in the input, advances the cursor to the end and 404318093Sgonzo * returns true. Returns false if the string does not appear at the 405318093Sgonzo * current point in the input. 406318093Sgonzo * 407318093Sgonzo * This method does not scan between files. 408318093Sgonzo */ 409318093Sgonzo bool consume(const char *str) 410318093Sgonzo { 411318093Sgonzo if (input_stack.empty()) 412318093Sgonzo { 413318093Sgonzo return false; 414318093Sgonzo } 415318093Sgonzo return input_stack.top()->consume(str); 416318093Sgonzo } 417318093Sgonzo /** 418318093Sgonzo * Reads an integer in base 8, 10, or 16. Returns true and advances 419318093Sgonzo * the cursor to the end of the integer if the cursor points to an 420318093Sgonzo * integer, returns false and does not move the cursor otherwise. 421318093Sgonzo * 422318093Sgonzo * The parsed value is returned via the argument. 423318093Sgonzo * 424318093Sgonzo * This method does not scan between files. 425318093Sgonzo */ 426318093Sgonzo bool consume_integer(unsigned long long &outInt) 427318093Sgonzo { 428318093Sgonzo if (input_stack.empty()) 429318093Sgonzo { 430318093Sgonzo return false; 431318093Sgonzo } 432318093Sgonzo return input_stack.top()->consume_integer(outInt); 433318093Sgonzo } 434318093Sgonzo /** 435318093Sgonzo * Reads an arithmetic expression (containing any of the normal C 436318093Sgonzo * operators), evaluates it, and returns the result. 437318093Sgonzo */ 438318093Sgonzo bool consume_integer_expression(unsigned long long &outInt); 439318093Sgonzo /** 440318093Sgonzo * Consumes two hex digits and return the resulting byte via the first 441318093Sgonzo * argument. If the next two characters are hex digits, returns true 442318093Sgonzo * and advances the cursor. If not, then returns false and leaves the 443318093Sgonzo * cursor in place. 444318093Sgonzo * 445318093Sgonzo * This method does not scan between files. 446318093Sgonzo */ 447318093Sgonzo bool consume_hex_byte(uint8_t &outByte) 448318093Sgonzo { 449318093Sgonzo if (input_stack.empty()) 450318093Sgonzo { 451318093Sgonzo return false; 452318093Sgonzo } 453318093Sgonzo return input_stack.top()->consume_hex_byte(outByte); 454318093Sgonzo } 455318093Sgonzo /** 456318093Sgonzo * Returns the longest string in the input buffer starting at the 457318093Sgonzo * current cursor and composed entirely of characters that are valid in 458318093Sgonzo * node names. 459318093Sgonzo */ 460318093Sgonzo std::string parse_node_name(); 461318093Sgonzo /** 462318093Sgonzo * Returns the longest string in the input buffer starting at the 463318093Sgonzo * current cursor and composed entirely of characters that are valid in 464318093Sgonzo * property names. 465318093Sgonzo */ 466318093Sgonzo std::string parse_property_name(); 467318093Sgonzo /** 468318093Sgonzo * Parses either a node or a property name. If is_property is true on 469318093Sgonzo * entry, then only property names are parsed. If it is false, then it 470318093Sgonzo * will be set, on return, to indicate whether the parsed name is only 471318093Sgonzo * valid as a property. 472318093Sgonzo */ 473318093Sgonzo std::string parse_node_or_property_name(bool &is_property); 474318093Sgonzo /** 475318093Sgonzo * Parses up to a specified character and returns the intervening 476318093Sgonzo * characters as a string. 477318093Sgonzo */ 478318093Sgonzo std::string parse_to(char); 479318093Sgonzo /** 480318093Sgonzo * Advances the cursor to the start of the next token, skipping 481318093Sgonzo * comments and whitespace. If the cursor already points to the start 482318093Sgonzo * of a token, then this function does nothing. 483318093Sgonzo */ 484318093Sgonzo text_input_buffer &next_token(); 485318093Sgonzo /** 486318093Sgonzo * Location in the source file. This should never be interpreted by 487318093Sgonzo * anything other than error reporting functions of this class. It will 488318093Sgonzo * eventually become something more complex than an `int`. 489318093Sgonzo */ 490318093Sgonzo class source_location 491318093Sgonzo { 492318093Sgonzo friend class text_input_buffer; 493318093Sgonzo /** 494318093Sgonzo * The text buffer object that included `b`. 495318093Sgonzo */ 496318093Sgonzo text_input_buffer &buffer; 497318093Sgonzo /** 498318093Sgonzo * The underlying buffer that contains this location. 499318093Sgonzo */ 500318093Sgonzo std::shared_ptr<input_buffer> b; 501318093Sgonzo /** 502318093Sgonzo * The offset within the current buffer of the source location. 503318093Sgonzo */ 504318093Sgonzo int cursor; 505318093Sgonzo source_location(text_input_buffer &buf) 506318093Sgonzo : buffer(buf), 507318093Sgonzo b(buf.input_stack.empty() ? nullptr : buf.input_stack.top()), 508318093Sgonzo cursor(b ? b->cursor : 0) {} 509318093Sgonzo public: 510318093Sgonzo /** 511318093Sgonzo * Report an error at this location. 512318093Sgonzo */ 513318093Sgonzo void report_error(const char *msg) 514318093Sgonzo { 515318093Sgonzo if (b) 516318093Sgonzo { 517318093Sgonzo buffer.parse_error(msg, *b, cursor); 518318093Sgonzo } 519318093Sgonzo else 520318093Sgonzo { 521318093Sgonzo buffer.parse_error(msg); 522318093Sgonzo } 523318093Sgonzo } 524318093Sgonzo }; 525318093Sgonzo /** 526318093Sgonzo * Returns the current source location. 527318093Sgonzo */ 528318093Sgonzo source_location location() 529318093Sgonzo { 530318093Sgonzo return { *this }; 531318093Sgonzo } 532318093Sgonzo /** 533318093Sgonzo * Prints a message indicating the location of a parse error. 534318093Sgonzo */ 535318093Sgonzo void parse_error(const char *msg); 536328495Skevans /** 537328495Skevans * Reads the contents of a binary file into `b`. The file name is assumed 538328495Skevans * to be relative to one of the include paths. 539328495Skevans * 540328495Skevans * Returns true if the file exists and can be read, false otherwise. 541328495Skevans */ 542328495Skevans bool read_binary_file(const std::string &filename, byte_buffer &b); 543318093Sgonzo private: 544318093Sgonzo /** 545318093Sgonzo * Prints a message indicating the location of a parse error, given a 546318093Sgonzo * specified location. This is used when input has already moved beyond 547318093Sgonzo * the location that caused the failure. 548318093Sgonzo */ 549318093Sgonzo void parse_error(const char *msg, input_buffer &b, int loc); 550245803Stheraven}; 551245803Stheraven 552245803Stheraven} // namespace dtc 553245803Stheraven 554245803Stheraven#endif // !_INPUT_BUFFER_HH_ 555