1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2013 David Chisnall 5 * All rights reserved. 6 * 7 * This software was developed by SRI International and the University of 8 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 9 * ("CTSRD"), as part of the DARPA CRASH research programme. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD$ 33 */ 34 35 #ifndef _INPUT_BUFFER_HH_ 36 #define _INPUT_BUFFER_HH_ 37 #include "util.hh" 38 #include <assert.h> 39 #include <stack> 40 #include <string> 41 #include <unordered_set> 42 43 namespace dtc 44 { 45 46 namespace { 47 struct expression; 48 typedef std::unique_ptr<expression> expression_ptr; 49 } 50 51 /** 52 * Class encapsulating the input file. Can be used as a const char*, but has 53 * range checking. Attempting to access anything out of range will return a 0 54 * byte. The input buffer can be cheaply copied, without copying the 55 * underlying memory, however it is the user's responsibility to ensure that 56 * such copies do not persist beyond the lifetime of the underlying memory. 57 * 58 * This also contains methods for reporting errors and for consuming the token 59 * stream. 60 */ 61 class input_buffer 62 { 63 friend class text_input_buffer; 64 protected: 65 /** 66 * The buffer. This class doesn't own the buffer, but the 67 * mmap_input_buffer subclass does. 68 */ 69 const char* buffer; 70 /** 71 * The size of the buffer. 72 */ 73 int size; 74 private: 75 /** 76 * The current place in the buffer where we are reading. This class 77 * keeps a separate size, pointer, and cursor so that we can move 78 * forwards and backwards and still have checks that we haven't fallen 79 * off either end. 80 */ 81 int cursor; 82 /** 83 * Private constructor. This is used to create input buffers that 84 * refer to the same memory, but have different cursors. 85 */ 86 input_buffer(const char* b, int s, int c) : buffer(b), size(s), 87 cursor(c) {} 88 public: 89 /** 90 * Returns the file name associated with this buffer. 91 */ 92 virtual const std::string &filename() const 93 { 94 static std::string s; 95 return s; 96 } 97 static std::unique_ptr<input_buffer> buffer_for_file(const std::string &path, 98 bool warn=true); 99 /** 100 * Skips all characters in the input until the specified character is 101 * encountered. 102 */ 103 void skip_to(char); 104 /** 105 * Parses up to a specified character and returns the intervening 106 * characters as a string. 107 */ 108 std::string parse_to(char); 109 /** 110 * Return whether all input has been consumed. 111 */ 112 bool finished() { return cursor >= size; } 113 /** 114 * Virtual destructor. Does nothing, but exists so that subclasses 115 * that own the memory can run cleanup code for deallocating it. 116 */ 117 virtual ~input_buffer() {}; 118 /** 119 * Constructs an empty buffer. 120 */ 121 input_buffer() : buffer(0), size(0), cursor(0) {} 122 /** 123 * Constructs a new buffer with a specified memory region and size. 124 */ 125 input_buffer(const char* b, int s) : buffer(b), size(s), cursor(0){} 126 /** 127 * Returns a new input buffer referring into this input, clamped to the 128 * specified size. If the requested buffer would fall outside the 129 * range of this one, then it returns an empty buffer. 130 * 131 * The returned buffer shares the same underlying storage as the 132 * original. This is intended to be used for splitting up the various 133 * sections of a device tree blob. Requesting a size of 0 will give a 134 * buffer that extends to the end of the available memory. 135 */ 136 input_buffer buffer_from_offset(int offset, int s=0); 137 /** 138 * Dereferencing operator, allows the buffer to be treated as a char* 139 * and dereferenced to give a character. This returns a null byte if 140 * the cursor is out of range. 141 */ 142 inline char operator*() 143 { 144 if (cursor >= size) { return '\0'; } 145 if (cursor < 0) { return '\0'; } 146 return buffer[cursor]; 147 } 148 /** 149 * Array subscripting operator, returns a character at the specified 150 * index offset from the current cursor. The offset may be negative, 151 * to reread characters that have already been read. If the current 152 * cursor plus offset is outside of the range, this returns a nul 153 * byte. 154 */ 155 inline char operator[](int offset) 156 { 157 if (cursor + offset >= size) { return '\0'; } 158 if (cursor + offset < 0) { return '\0'; } 159 return buffer[cursor + offset]; 160 } 161 /** 162 * Increments the cursor, iterating forward in the buffer. 163 */ 164 inline input_buffer &operator++() 165 { 166 cursor++; 167 return *this; 168 } 169 const char *begin() 170 { 171 return buffer; 172 } 173 const char *end() 174 { 175 return buffer + size; 176 } 177 /** 178 * Consumes a character. Moves the cursor one character forward if the 179 * next character matches the argument, returning true. If the current 180 * character does not match the argument, returns false. 181 */ 182 inline bool consume(char c) 183 { 184 if (*(*this) == c) 185 { 186 ++(*this); 187 return true; 188 } 189 return false; 190 } 191 /** 192 * Consumes a string. If the (null-terminated) string passed as the 193 * argument appears in the input, advances the cursor to the end and 194 * returns true. Returns false if the string does not appear at the 195 * current point in the input. 196 */ 197 bool consume(const char *str); 198 /** 199 * Reads an integer in base 8, 10, or 16. Returns true and advances 200 * the cursor to the end of the integer if the cursor points to an 201 * integer, returns false and does not move the cursor otherwise. 202 * 203 * The parsed value is returned via the argument. 204 */ 205 bool consume_integer(unsigned long long &outInt); 206 /** 207 * Reads an arithmetic expression (containing any of the normal C 208 * operators), evaluates it, and returns the result. 209 */ 210 bool consume_integer_expression(unsigned long long &outInt); 211 /** 212 * Consumes two hex digits and return the resulting byte via the first 213 * argument. If the next two characters are hex digits, returns true 214 * and advances the cursor. If not, then returns false and leaves the 215 * cursor in place. 216 */ 217 bool consume_hex_byte(uint8_t &outByte); 218 /** 219 * Template function that consumes a binary value in big-endian format 220 * from the input stream. Returns true and advances the cursor if 221 * there is a value of the correct size. This function assumes that 222 * all values must be natively aligned, and so advances the cursor to 223 * the correct alignment before reading. 224 */ 225 template<typename T> 226 bool consume_binary(T &out) 227 { 228 int align = 0; 229 int type_size = sizeof(T); 230 if (cursor % type_size != 0) 231 { 232 align = type_size - (cursor % type_size); 233 } 234 if (size < cursor + align + type_size) 235 { 236 return false; 237 } 238 cursor += align; 239 assert(cursor % type_size == 0); 240 out = 0; 241 for (int i=0 ; i<type_size ; ++i) 242 { 243 if (size < cursor) 244 { 245 return false; 246 } 247 out <<= 8; 248 out |= (((T)buffer[cursor++]) & 0xff); 249 } 250 return true; 251 } 252 #ifndef NDEBUG 253 /** 254 * Dumps the current cursor value and the unconsumed values in the 255 * input buffer to the standard error. This method is intended solely 256 * for debugging. 257 */ 258 void dump(); 259 #endif 260 }; 261 /** 262 * Explicit specialisation for reading a single byte. 263 */ 264 template<> 265 inline bool input_buffer::consume_binary(uint8_t &out) 266 { 267 if (size < cursor + 1) 268 { 269 return false; 270 } 271 out = buffer[cursor++]; 272 return true; 273 } 274 275 /** 276 * An input buffer subclass used for parsing DTS files. This manages a stack 277 * of input buffers to handle /input/ operations. 278 */ 279 class text_input_buffer 280 { 281 std::unordered_set<std::string> defines; 282 /** 283 * The cursor is the input into the input stream where we are currently reading. 284 */ 285 int cursor = 0; 286 /** 287 * The current stack of includes. The current input is always from the top 288 * of the stack. 289 */ 290 std::stack<std::shared_ptr<input_buffer>> input_stack; 291 /** 292 * 293 */ 294 const std::vector<std::string> include_paths; 295 /** 296 * Reads forward past any spaces. The DTS format is not whitespace 297 * sensitive and so we want to scan past whitespace when reading it. 298 */ 299 void skip_spaces(); 300 /** 301 * Returns the character immediately after the current one. 302 * 303 * This method does not look between files. 304 */ 305 char peek(); 306 /** 307 * If a /include/ token is encountered, then look up the corresponding 308 * input file, push it onto the input stack, and continue. 309 */ 310 void handle_include(); 311 /** 312 * The base directory for this file. 313 */ 314 const std::string dir; 315 /** 316 * The file where dependencies should be output. 317 */ 318 FILE *depfile; 319 public: 320 /** 321 * Construct a new text input buffer with the specified buffer as the start 322 * of parsing and the specified set of input paths for handling new 323 * inclusions. 324 */ 325 text_input_buffer(std::unique_ptr<input_buffer> &&b, 326 std::unordered_set<std::string> &&d, 327 std::vector<std::string> &&i, 328 const std::string directory, 329 FILE *deps) 330 : defines(d), include_paths(i), dir(directory), depfile(deps) 331 { 332 input_stack.push(std::move(b)); 333 } 334 /** 335 * Skips all characters in the input until the specified character is 336 * encountered. 337 */ 338 void skip_to(char); 339 /** 340 * Parse an expression. If `stopAtParen` is set, then only parse a number 341 * or a parenthetical expression, otherwise assume that either is the 342 * left-hand side of a binary expression and try to parse the right-hand 343 * side. 344 */ 345 expression_ptr parse_expression(bool stopAtParen=false); 346 /** 347 * Parse a binary expression, having already parsed the right-hand side. 348 */ 349 expression_ptr parse_binary_expression(expression_ptr lhs); 350 /** 351 * Return whether all input has been consumed. 352 */ 353 bool finished() 354 { 355 return input_stack.empty() || 356 ((input_stack.size() == 1) && input_stack.top()->finished()); 357 } 358 /** 359 * Dereferencing operator. Returns the current character in the top input buffer. 360 */ 361 inline char operator*() 362 { 363 if (input_stack.empty()) 364 { 365 return 0; 366 } 367 return *(*input_stack.top()); 368 } 369 /** 370 * Increments the cursor, iterating forward in the buffer. 371 */ 372 inline text_input_buffer &operator++() 373 { 374 if (input_stack.empty()) 375 { 376 return *this; 377 } 378 cursor++; 379 auto &top = *input_stack.top(); 380 ++top; 381 if (top.finished()) 382 { 383 input_stack.pop(); 384 } 385 return *this; 386 } 387 /** 388 * Consumes a character. Moves the cursor one character forward if the 389 * next character matches the argument, returning true. If the current 390 * character does not match the argument, returns false. 391 */ 392 inline bool consume(char c) 393 { 394 if (*(*this) == c) 395 { 396 ++(*this); 397 return true; 398 } 399 return false; 400 } 401 /** 402 * Consumes a string. If the (null-terminated) string passed as the 403 * argument appears in the input, advances the cursor to the end and 404 * returns true. Returns false if the string does not appear at the 405 * current point in the input. 406 * 407 * This method does not scan between files. 408 */ 409 bool consume(const char *str) 410 { 411 if (input_stack.empty()) 412 { 413 return false; 414 } 415 return input_stack.top()->consume(str); 416 } 417 /** 418 * Reads an integer in base 8, 10, or 16. Returns true and advances 419 * the cursor to the end of the integer if the cursor points to an 420 * integer, returns false and does not move the cursor otherwise. 421 * 422 * The parsed value is returned via the argument. 423 * 424 * This method does not scan between files. 425 */ 426 bool consume_integer(unsigned long long &outInt) 427 { 428 if (input_stack.empty()) 429 { 430 return false; 431 } 432 return input_stack.top()->consume_integer(outInt); 433 } 434 /** 435 * Reads an arithmetic expression (containing any of the normal C 436 * operators), evaluates it, and returns the result. 437 */ 438 bool consume_integer_expression(unsigned long long &outInt); 439 /** 440 * Consumes two hex digits and return the resulting byte via the first 441 * argument. If the next two characters are hex digits, returns true 442 * and advances the cursor. If not, then returns false and leaves the 443 * cursor in place. 444 * 445 * This method does not scan between files. 446 */ 447 bool consume_hex_byte(uint8_t &outByte) 448 { 449 if (input_stack.empty()) 450 { 451 return false; 452 } 453 return input_stack.top()->consume_hex_byte(outByte); 454 } 455 /** 456 * Returns the longest string in the input buffer starting at the 457 * current cursor and composed entirely of characters that are valid in 458 * node names. 459 */ 460 std::string parse_node_name(); 461 /** 462 * Returns the longest string in the input buffer starting at the 463 * current cursor and composed entirely of characters that are valid in 464 * property names. 465 */ 466 std::string parse_property_name(); 467 /** 468 * Parses either a node or a property name. If is_property is true on 469 * entry, then only property names are parsed. If it is false, then it 470 * will be set, on return, to indicate whether the parsed name is only 471 * valid as a property. 472 */ 473 std::string parse_node_or_property_name(bool &is_property); 474 /** 475 * Parses up to a specified character and returns the intervening 476 * characters as a string. 477 */ 478 std::string parse_to(char); 479 /** 480 * Advances the cursor to the start of the next token, skipping 481 * comments and whitespace. If the cursor already points to the start 482 * of a token, then this function does nothing. 483 */ 484 text_input_buffer &next_token(); 485 /** 486 * Location in the source file. This should never be interpreted by 487 * anything other than error reporting functions of this class. It will 488 * eventually become something more complex than an `int`. 489 */ 490 class source_location 491 { 492 friend class text_input_buffer; 493 /** 494 * The text buffer object that included `b`. 495 */ 496 text_input_buffer &buffer; 497 /** 498 * The underlying buffer that contains this location. 499 */ 500 std::shared_ptr<input_buffer> b; 501 /** 502 * The offset within the current buffer of the source location. 503 */ 504 int cursor; 505 source_location(text_input_buffer &buf) 506 : buffer(buf), 507 b(buf.input_stack.empty() ? nullptr : buf.input_stack.top()), 508 cursor(b ? b->cursor : 0) {} 509 public: 510 /** 511 * Report an error at this location. 512 */ 513 void report_error(const char *msg) 514 { 515 if (b) 516 { 517 buffer.parse_error(msg, *b, cursor); 518 } 519 else 520 { 521 buffer.parse_error(msg); 522 } 523 } 524 }; 525 /** 526 * Returns the current source location. 527 */ 528 source_location location() 529 { 530 return { *this }; 531 } 532 /** 533 * Prints a message indicating the location of a parse error. 534 */ 535 void parse_error(const char *msg); 536 /** 537 * Reads the contents of a binary file into `b`. The file name is assumed 538 * to be relative to one of the include paths. 539 * 540 * Returns true if the file exists and can be read, false otherwise. 541 */ 542 bool read_binary_file(const std::string &filename, byte_buffer &b); 543 private: 544 /** 545 * Prints a message indicating the location of a parse error, given a 546 * specified location. This is used when input has already moved beyond 547 * the location that caused the failure. 548 */ 549 void parse_error(const char *msg, input_buffer &b, int loc); 550 }; 551 552 } // namespace dtc 553 554 #endif // !_INPUT_BUFFER_HH_ 555