input_buffer.cc (009e81b16465ea457c0e63fd49fe77f47cc27a5a) | input_buffer.cc (bbe31b709a653884e18995a1c97cdafd7392999a) |
---|---|
1/*- 2 * Copyright (c) 2013 David Chisnall 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7 * ("CTSRD"), as part of the DARPA CRASH research programme. 8 * --- 32 unchanged lines hidden (view full) --- 41#ifndef NDEBUG 42#include <iostream> 43#endif 44 45 46#include <sys/stat.h> 47#include <sys/mman.h> 48#include <assert.h> | 1/*- 2 * Copyright (c) 2013 David Chisnall 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7 * ("CTSRD"), as part of the DARPA CRASH research programme. 8 * --- 32 unchanged lines hidden (view full) --- 41#ifndef NDEBUG 42#include <iostream> 43#endif 44 45 46#include <sys/stat.h> 47#include <sys/mman.h> 48#include <assert.h> |
49#include <fcntl.h> 50#include <unistd.h> |
|
49 50#ifndef MAP_PREFAULT_READ 51#define MAP_PREFAULT_READ 0 52#endif 53 | 51 52#ifndef MAP_PREFAULT_READ 53#define MAP_PREFAULT_READ 0 54#endif 55 |
56using std::string; 57 58namespace 59{ 60/** 61 * Subclass of input_buffer that mmap()s a file and owns the resulting memory. 62 * When this object is destroyed, the memory is unmapped. 63 */ 64struct mmap_input_buffer : public dtc::input_buffer 65{ 66 string fn; 67 const string &filename() const override 68 { 69 return fn; 70 } 71 /** 72 * Constructs a new buffer from the file passed in as a file 73 * descriptor. 74 */ 75 mmap_input_buffer(int fd, string &&filename); 76 /** 77 * Unmaps the buffer, if one exists. 78 */ 79 virtual ~mmap_input_buffer(); 80}; 81/** 82 * Input buffer read from standard input. This is used for reading device tree 83 * blobs and source from standard input. It reads the entire input into 84 * malloc'd memory, so will be very slow for large inputs. DTS and DTB files 85 * are very rarely more than 10KB though, so this is probably not a problem. 86 */ 87struct stream_input_buffer : public dtc::input_buffer 88{ 89 const string &filename() const override 90 { 91 static string n = "<standard input>"; 92 return n; 93 } 94 /** 95 * The buffer that will store the data read from the standard input. 96 */ 97 std::vector<char> b; 98 /** 99 * Constructs a new buffer from the standard input. 100 */ 101 stream_input_buffer(); 102}; 103 104mmap_input_buffer::mmap_input_buffer(int fd, std::string &&filename) 105 : input_buffer(0, 0), fn(filename) 106{ 107 struct stat sb; 108 if (fstat(fd, &sb)) 109 { 110 perror("Failed to stat file"); 111 } 112 size = sb.st_size; 113 buffer = (const char*)mmap(0, size, PROT_READ, MAP_PRIVATE | 114 MAP_PREFAULT_READ, fd, 0); 115 if (buffer == MAP_FAILED) 116 { 117 perror("Failed to mmap file"); 118 exit(EXIT_FAILURE); 119 } 120} 121 122mmap_input_buffer::~mmap_input_buffer() 123{ 124 if (buffer != 0) 125 { 126 munmap((void*)buffer, size); 127 } 128} 129 130stream_input_buffer::stream_input_buffer() : input_buffer(0, 0) 131{ 132 int c; 133 while ((c = fgetc(stdin)) != EOF) 134 { 135 b.push_back(c); 136 } 137 buffer = b.data(); 138 size = b.size(); 139} 140 141} // Anonymous namespace 142 143 |
|
54namespace dtc 55{ | 144namespace dtc 145{ |
146 |
|
56void | 147void |
57input_buffer::skip_spaces() | 148input_buffer::skip_to(char c) |
58{ | 149{ |
59 if (cursor >= size) { return; } 60 if (cursor < 0) { return; } 61 char c = buffer[cursor]; | 150 while ((cursor < size) && (buffer[cursor] != c)) 151 { 152 cursor++; 153 } 154} 155 156void 157text_input_buffer::skip_to(char c) 158{ 159 while (!finished() && (*(*this) != c)) 160 { 161 ++(*this); 162 } 163} 164 165void 166text_input_buffer::skip_spaces() 167{ 168 if (finished()) { return; } 169 char c = *(*this); 170 bool last_nl = false; |
62 while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f') 63 || (c == '\v') || (c == '\r')) 64 { | 171 while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f') 172 || (c == '\v') || (c == '\r')) 173 { |
65 cursor++; 66 if (cursor > size) | 174 last_nl = ((c == '\n') || (c == '\r')); 175 ++(*this); 176 if (finished()) |
67 { 68 c = '\0'; 69 } 70 else 71 { | 177 { 178 c = '\0'; 179 } 180 else 181 { |
72 c = buffer[cursor]; | 182 c = *(*this); |
73 } 74 } | 183 } 184 } |
185 // Skip C preprocessor leftovers 186 if ((c == '#') && ((cursor == 0) || last_nl)) 187 { 188 skip_to('\n'); 189 skip_spaces(); 190 } 191 if (consume("/include/")) 192 { 193 handle_include(); 194 skip_spaces(); 195 } |
|
75} 76 | 196} 197 |
198void 199text_input_buffer::handle_include() 200{ 201 bool reallyInclude = true; 202 if (consume("if ")) 203 { 204 next_token(); 205 string name = parse_property_name(); 206 if (defines.count(name) > 0) 207 { 208 reallyInclude = true; 209 } 210 consume('/'); 211 } 212 next_token(); 213 if (!consume('"')) 214 { 215 parse_error("Expected quoted filename"); 216 return; 217 } 218 string file = parse_to('"'); 219 consume('"'); 220 if (!reallyInclude) 221 { 222 return; 223 } 224 string include_file = dir + '/' + file; 225 auto include_buffer = input_buffer::buffer_for_file(include_file, false); 226 if (include_buffer == 0) 227 { 228 for (auto i : include_paths) 229 { 230 include_file = i + '/' + file; 231 include_buffer = input_buffer::buffer_for_file(include_file, false); 232 if (include_buffer != 0) 233 { 234 break; 235 } 236 } 237 } 238 if (depfile) 239 { 240 putc(' ', depfile); 241 fputs(include_file.c_str(), depfile); 242 } 243 if (!include_buffer) 244 { 245 parse_error("Unable to locate input file"); 246 return; 247 } 248 input_stack.push(std::move(include_buffer)); 249} 250 |
|
77input_buffer 78input_buffer::buffer_from_offset(int offset, int s) 79{ | 251input_buffer 252input_buffer::buffer_from_offset(int offset, int s) 253{ |
254 if (offset < 0) 255 { 256 return input_buffer(); 257 } |
|
80 if (s == 0) 81 { 82 s = size - offset; 83 } 84 if (offset > size) 85 { 86 return input_buffer(); 87 } --- 11 unchanged lines hidden (view full) --- 99 if (len > size - cursor) 100 { 101 return false; 102 } 103 else 104 { 105 for (int i=0 ; i<len ; ++i) 106 { | 258 if (s == 0) 259 { 260 s = size - offset; 261 } 262 if (offset > size) 263 { 264 return input_buffer(); 265 } --- 11 unchanged lines hidden (view full) --- 277 if (len > size - cursor) 278 { 279 return false; 280 } 281 else 282 { 283 for (int i=0 ; i<len ; ++i) 284 { |
107 if (str[i] != buffer[cursor + i]) | 285 if (str[i] != (*this)[i]) |
108 { 109 return false; 110 } 111 } 112 cursor += len; 113 return true; 114 } 115 return false; 116} 117 118bool 119input_buffer::consume_integer(unsigned long long &outInt) 120{ 121 // The first character must be a digit. Hex and octal strings 122 // are prefixed by 0 and 0x, respectively. 123 if (!isdigit((*this)[0])) 124 { 125 return false; 126 } | 286 { 287 return false; 288 } 289 } 290 cursor += len; 291 return true; 292 } 293 return false; 294} 295 296bool 297input_buffer::consume_integer(unsigned long long &outInt) 298{ 299 // The first character must be a digit. Hex and octal strings 300 // are prefixed by 0 and 0x, respectively. 301 if (!isdigit((*this)[0])) 302 { 303 return false; 304 } |
127 char *end=0; | 305 char *end= const_cast<char*>(&buffer[size]); |
128 outInt = strtoull(&buffer[cursor], &end, 0); 129 if (end == &buffer[cursor]) 130 { 131 return false; 132 } 133 cursor = end - buffer; 134 return true; 135} --- 5 unchanged lines hidden (view full) --- 141 */ 142typedef unsigned long long valty; 143 144/** 145 * Expression tree currently being parsed. 146 */ 147struct expression 148{ | 306 outInt = strtoull(&buffer[cursor], &end, 0); 307 if (end == &buffer[cursor]) 308 { 309 return false; 310 } 311 cursor = end - buffer; 312 return true; 313} --- 5 unchanged lines hidden (view full) --- 319 */ 320typedef unsigned long long valty; 321 322/** 323 * Expression tree currently being parsed. 324 */ 325struct expression 326{ |
327 typedef text_input_buffer::source_location source_location; |
|
149 /** | 328 /** |
329 * The type that is returned when computing the result. The boolean value 330 * indicates whether this is a valid expression. 331 * 332 * FIXME: Once we can use C++17, this should be `std::optional`. 333 */ 334 typedef std::pair<valty, bool> result; 335 /** |
|
150 * Evaluate this node, taking into account operator precedence. 151 */ | 336 * Evaluate this node, taking into account operator precedence. 337 */ |
152 virtual valty operator()() = 0; | 338 virtual result operator()() = 0; |
153 /** 154 * Returns the precedence of this node. Lower values indicate higher 155 * precedence. 156 */ 157 virtual int precedence() = 0; | 339 /** 340 * Returns the precedence of this node. Lower values indicate higher 341 * precedence. 342 */ 343 virtual int precedence() = 0; |
344 /** 345 * Constructs an expression, storing the location where it was created. 346 */ 347 expression(source_location l) : loc(l) {} |
|
158 virtual ~expression() {} 159#ifndef NDEBUG 160 /** 161 * Dumps this expression to `std::cerr`, appending a newline if `nl` is 162 * `true`. 163 */ 164 void dump(bool nl=false) 165 { | 348 virtual ~expression() {} 349#ifndef NDEBUG 350 /** 351 * Dumps this expression to `std::cerr`, appending a newline if `nl` is 352 * `true`. 353 */ 354 void dump(bool nl=false) 355 { |
166 if (this == nullptr) | 356 void *ptr = this; 357 if (ptr == nullptr) |
167 { 168 std::cerr << "{nullptr}\n"; 169 return; 170 } 171 dump_impl(); 172 if (nl) 173 { 174 std::cerr << '\n'; 175 } 176 } 177 private: 178 /** 179 * Method that sublcasses override to implement the behaviour of `dump()`. 180 */ 181 virtual void dump_impl() = 0; 182#endif | 358 { 359 std::cerr << "{nullptr}\n"; 360 return; 361 } 362 dump_impl(); 363 if (nl) 364 { 365 std::cerr << '\n'; 366 } 367 } 368 private: 369 /** 370 * Method that sublcasses override to implement the behaviour of `dump()`. 371 */ 372 virtual void dump_impl() = 0; 373#endif |
374 protected: 375 source_location loc; |
|
183}; 184 185/** 186 * Expression wrapping a single integer. Leaf nodes in the expression tree. 187 */ 188class terminal_expr : public expression 189{ 190 /** 191 * The value that this wraps. 192 */ 193 valty val; 194 /** 195 * Evaluate. Trivially returns the value that this class wraps. 196 */ | 376}; 377 378/** 379 * Expression wrapping a single integer. Leaf nodes in the expression tree. 380 */ 381class terminal_expr : public expression 382{ 383 /** 384 * The value that this wraps. 385 */ 386 valty val; 387 /** 388 * Evaluate. Trivially returns the value that this class wraps. 389 */ |
197 valty operator()() override | 390 result operator()() override |
198 { | 391 { |
199 return val; | 392 return {val, true}; |
200 } 201 int precedence() override 202 { 203 return 0; 204 } 205 public: 206 /** 207 * Constructor. 208 */ | 393 } 394 int precedence() override 395 { 396 return 0; 397 } 398 public: 399 /** 400 * Constructor. 401 */ |
209 terminal_expr(valty v) : val(v) {} | 402 terminal_expr(source_location l, valty v) : expression(l), val(v) {} |
210#ifndef NDEBUG 211 void dump_impl() override { std::cerr << val; } 212#endif 213}; 214 215/** 216 * Parenthetical expression. Exists to make the contents opaque. 217 */ 218struct paren_expression : public expression 219{ 220 /** 221 * The expression within the parentheses. 222 */ 223 expression_ptr subexpr; 224 /** 225 * Constructor. Takes the child expression as the only argument. 226 */ | 403#ifndef NDEBUG 404 void dump_impl() override { std::cerr << val; } 405#endif 406}; 407 408/** 409 * Parenthetical expression. Exists to make the contents opaque. 410 */ 411struct paren_expression : public expression 412{ 413 /** 414 * The expression within the parentheses. 415 */ 416 expression_ptr subexpr; 417 /** 418 * Constructor. Takes the child expression as the only argument. 419 */ |
227 paren_expression(expression_ptr p) : subexpr(std::move(p)) {} | 420 paren_expression(source_location l, expression_ptr p) : expression(l), 421 subexpr(std::move(p)) {} |
228 int precedence() override 229 { 230 return 0; 231 } 232 /** 233 * Evaluate - just forwards to the underlying expression. 234 */ | 422 int precedence() override 423 { 424 return 0; 425 } 426 /** 427 * Evaluate - just forwards to the underlying expression. 428 */ |
235 valty operator()() override | 429 result operator()() override |
236 { 237 return (*subexpr)(); 238 } 239#ifndef NDEBUG 240 void dump_impl() override 241 { 242 std::cerr << " ("; 243 subexpr->dump(); --- 11 unchanged lines hidden (view full) --- 255 */ 256template<char OpChar, class Op> 257class unary_operator : public expression 258{ 259 /** 260 * The subexpression for this unary operator. 261 */ 262 expression_ptr subexpr; | 430 { 431 return (*subexpr)(); 432 } 433#ifndef NDEBUG 434 void dump_impl() override 435 { 436 std::cerr << " ("; 437 subexpr->dump(); --- 11 unchanged lines hidden (view full) --- 449 */ 450template<char OpChar, class Op> 451class unary_operator : public expression 452{ 453 /** 454 * The subexpression for this unary operator. 455 */ 456 expression_ptr subexpr; |
263 valty operator()() override | 457 result operator()() override |
264 { 265 Op op; | 458 { 459 Op op; |
266 return op((*subexpr)()); | 460 result s = (*subexpr)(); 461 if (!s.second) 462 { 463 return s; 464 } 465 return {op(s.first), true}; |
267 } 268 /** 269 * All unary operators have the same precedence. They are all evaluated 270 * before binary expressions, but after parentheses. 271 */ 272 int precedence() override 273 { 274 return 3; 275 } 276 public: | 466 } 467 /** 468 * All unary operators have the same precedence. They are all evaluated 469 * before binary expressions, but after parentheses. 470 */ 471 int precedence() override 472 { 473 return 3; 474 } 475 public: |
277 unary_operator(expression_ptr p) : subexpr(std::move(p)) {} | 476 unary_operator(source_location l, expression_ptr p) : 477 expression(l), subexpr(std::move(p)) {} |
278#ifndef NDEBUG 279 void dump_impl() override 280 { 281 std::cerr << OpChar; 282 subexpr->dump(); 283 } 284#endif 285}; 286 287/** 288 * Abstract base class for binary operators. Allows the tree to be modified 289 * without knowing what the operations actually are. 290 */ 291struct binary_operator_base : public expression 292{ | 478#ifndef NDEBUG 479 void dump_impl() override 480 { 481 std::cerr << OpChar; 482 subexpr->dump(); 483 } 484#endif 485}; 486 487/** 488 * Abstract base class for binary operators. Allows the tree to be modified 489 * without knowing what the operations actually are. 490 */ 491struct binary_operator_base : public expression 492{ |
493 using expression::expression; |
|
293 /** 294 * The left side of the expression. 295 */ 296 expression_ptr lhs; 297 /** 298 * The right side of the expression. 299 */ 300 expression_ptr rhs; --- 17 unchanged lines hidden (view full) --- 318 319/** 320 * Template class for binary operators. The precedence and the operation are 321 * provided as template parameters. 322 */ 323template<int Precedence, class Op> 324struct binary_operator : public binary_operator_base 325{ | 494 /** 495 * The left side of the expression. 496 */ 497 expression_ptr lhs; 498 /** 499 * The right side of the expression. 500 */ 501 expression_ptr rhs; --- 17 unchanged lines hidden (view full) --- 519 520/** 521 * Template class for binary operators. The precedence and the operation are 522 * provided as template parameters. 523 */ 524template<int Precedence, class Op> 525struct binary_operator : public binary_operator_base 526{ |
326 valty operator()() override | 527 result operator()() override |
327 { 328 Op op; | 528 { 529 Op op; |
329 return op((*lhs)(), (*rhs)()); | 530 result l = (*lhs)(); 531 result r = (*rhs)(); 532 if (!(l.second && r.second)) 533 { 534 return {0, false}; 535 } 536 return {op(l.first, r.first), true}; |
330 } 331 int precedence() override 332 { 333 return Precedence; 334 } 335#ifdef NDEBUG 336 /** 337 * Constructor. Takes the name of the operator as an argument, for 338 * debugging. Only stores it in debug mode. 339 */ | 537 } 538 int precedence() override 539 { 540 return Precedence; 541 } 542#ifdef NDEBUG 543 /** 544 * Constructor. Takes the name of the operator as an argument, for 545 * debugging. Only stores it in debug mode. 546 */ |
340 binary_operator(const char *) {} | 547 binary_operator(source_location l, const char *) : expression(l) {} |
341#else 342 const char *opName; | 548#else 549 const char *opName; |
343 binary_operator(const char *o) : opName(o) {} | 550 binary_operator(source_location l, const char *o) : 551 binary_operator_base(l), opName(o) {} |
344 void dump_impl() override 345 { 346 lhs->dump(); 347 std::cerr << opName; 348 rhs->dump(); 349 } 350#endif 351}; --- 11 unchanged lines hidden (view full) --- 363 /** 364 * The expression that this evaluates to if the condition is true. 365 */ 366 expression_ptr lhs; 367 /** 368 * The expression that this evaluates to if the condition is false. 369 */ 370 expression_ptr rhs; | 552 void dump_impl() override 553 { 554 lhs->dump(); 555 std::cerr << opName; 556 rhs->dump(); 557 } 558#endif 559}; --- 11 unchanged lines hidden (view full) --- 571 /** 572 * The expression that this evaluates to if the condition is true. 573 */ 574 expression_ptr lhs; 575 /** 576 * The expression that this evaluates to if the condition is false. 577 */ 578 expression_ptr rhs; |
371 valty operator()() override | 579 result operator()() override |
372 { | 580 { |
373 return (*cond)() ? (*lhs)() : (*rhs)(); | 581 result c = (*cond)(); 582 result l = (*lhs)(); 583 result r = (*rhs)(); 584 if (!(l.second && r.second && c.second)) 585 { 586 return {0, false}; 587 } 588 return c.first ? l : r; |
374 } 375 int precedence() override 376 { 377 // The actual precedence of a ternary conditional operator is 15, but 378 // its associativity is the opposite way around to the other operators, 379 // so we fudge it slightly. 380 return 3; 381 } 382#ifndef NDEBUG 383 void dump_impl() override 384 { 385 cond->dump(); 386 std::cerr << " ? "; 387 lhs->dump(); 388 std::cerr << " : "; 389 rhs->dump(); 390 } 391#endif 392 public: | 589 } 590 int precedence() override 591 { 592 // The actual precedence of a ternary conditional operator is 15, but 593 // its associativity is the opposite way around to the other operators, 594 // so we fudge it slightly. 595 return 3; 596 } 597#ifndef NDEBUG 598 void dump_impl() override 599 { 600 cond->dump(); 601 std::cerr << " ? "; 602 lhs->dump(); 603 std::cerr << " : "; 604 rhs->dump(); 605 } 606#endif 607 public: |
393 ternary_conditional_operator(expression_ptr c, | 608 ternary_conditional_operator(source_location sl, 609 expression_ptr c, |
394 expression_ptr l, 395 expression_ptr r) : | 610 expression_ptr l, 611 expression_ptr r) : |
396 cond(std::move(c)), lhs(std::move(l)), rhs(std::move(r)) {} | 612 expression(sl), cond(std::move(c)), lhs(std::move(l)), 613 rhs(std::move(r)) {} |
397}; 398 399template<typename T> 400struct lshift 401{ 402 constexpr T operator()(const T &lhs, const T &rhs) const 403 { 404 return lhs << rhs; --- 20 unchanged lines hidden (view full) --- 425struct bit_not 426{ 427 constexpr T operator()(const T &val) const 428 { 429 return ~val; 430 } 431}; 432 | 614}; 615 616template<typename T> 617struct lshift 618{ 619 constexpr T operator()(const T &lhs, const T &rhs) const 620 { 621 return lhs << rhs; --- 20 unchanged lines hidden (view full) --- 642struct bit_not 643{ 644 constexpr T operator()(const T &val) const 645 { 646 return ~val; 647 } 648}; 649 |
650template<typename T> 651struct divmod : public binary_operator<5, T> 652{ 653 using binary_operator<5, T>::binary_operator; 654 using binary_operator_base::result; 655 result operator()() override 656 { 657 result r = (*binary_operator_base::rhs)(); 658 if (r.second && (r.first == 0)) 659 { 660 expression::loc.report_error("Division by zero"); 661 return {0, false}; 662 } 663 return binary_operator<5, T>::operator()(); 664 } 665}; 666 |
|
433} // anonymous namespace 434 435 | 667} // anonymous namespace 668 669 |
436expression_ptr input_buffer::parse_binary_expression(expression_ptr lhs) | 670expression_ptr text_input_buffer::parse_binary_expression(expression_ptr lhs) |
437{ 438 next_token(); 439 binary_operator_base *expr = nullptr; | 671{ 672 next_token(); 673 binary_operator_base *expr = nullptr; |
440 char op = ((*this)[0]); | 674 char op = *(*this); 675 source_location l = location(); |
441 switch (op) 442 { 443 default: 444 return lhs; 445 case '+': | 676 switch (op) 677 { 678 default: 679 return lhs; 680 case '+': |
446 expr = new binary_operator<6, std::plus<valty>>("+"); | 681 expr = new binary_operator<6, std::plus<valty>>(l, "+"); |
447 break; 448 case '-': | 682 break; 683 case '-': |
449 expr = new binary_operator<6, std::minus<valty>>("-"); | 684 expr = new binary_operator<6, std::minus<valty>>(l, "-"); |
450 break; 451 case '%': | 685 break; 686 case '%': |
452 expr = new binary_operator<5, std::modulus<valty>>("%"); | 687 expr = new divmod<std::modulus<valty>>(l, "/"); |
453 break; 454 case '*': | 688 break; 689 case '*': |
455 expr = new binary_operator<5, std::multiplies<valty>>("*"); | 690 expr = new binary_operator<5, std::multiplies<valty>>(l, "*"); |
456 break; 457 case '/': | 691 break; 692 case '/': |
458 expr = new binary_operator<5, std::divides<valty>>("/"); | 693 expr = new divmod<std::divides<valty>>(l, "/"); |
459 break; 460 case '<': | 694 break; 695 case '<': |
461 cursor++; 462 switch ((*this)[0]) | 696 switch (peek()) |
463 { 464 default: 465 parse_error("Invalid operator"); 466 return nullptr; 467 case ' ': 468 case '(': 469 case '0'...'9': | 697 { 698 default: 699 parse_error("Invalid operator"); 700 return nullptr; 701 case ' ': 702 case '(': 703 case '0'...'9': |
470 cursor--; 471 expr = new binary_operator<8, std::less<valty>>("<"); | 704 expr = new binary_operator<8, std::less<valty>>(l, "<"); |
472 break; 473 case '=': | 705 break; 706 case '=': |
474 expr = new binary_operator<8, std::less_equal<valty>>("<="); | 707 ++(*this); 708 expr = new binary_operator<8, std::less_equal<valty>>(l, "<="); |
475 break; 476 case '<': | 709 break; 710 case '<': |
477 expr = new binary_operator<7, lshift<valty>>("<<"); | 711 ++(*this); 712 expr = new binary_operator<7, lshift<valty>>(l, "<<"); |
478 break; 479 } 480 break; 481 case '>': | 713 break; 714 } 715 break; 716 case '>': |
482 cursor++; 483 switch ((*this)[0]) | 717 switch (peek()) |
484 { 485 default: 486 parse_error("Invalid operator"); 487 return nullptr; 488 case '(': 489 case ' ': 490 case '0'...'9': | 718 { 719 default: 720 parse_error("Invalid operator"); 721 return nullptr; 722 case '(': 723 case ' ': 724 case '0'...'9': |
491 cursor--; 492 expr = new binary_operator<8, std::greater<valty>>(">"); | 725 expr = new binary_operator<8, std::greater<valty>>(l, ">"); |
493 break; 494 case '=': | 726 break; 727 case '=': |
495 expr = new binary_operator<8, std::greater_equal<valty>>(">="); | 728 ++(*this); 729 expr = new binary_operator<8, std::greater_equal<valty>>(l, ">="); |
496 break; 497 case '>': | 730 break; 731 case '>': |
498 expr = new binary_operator<7, rshift<valty>>(">>"); | 732 ++(*this); 733 expr = new binary_operator<7, rshift<valty>>(l, ">>"); |
499 break; 500 return lhs; 501 } 502 break; 503 case '=': | 734 break; 735 return lhs; 736 } 737 break; 738 case '=': |
504 if ((*this)[1] != '=') | 739 if (peek() != '=') |
505 { 506 parse_error("Invalid operator"); 507 return nullptr; 508 } | 740 { 741 parse_error("Invalid operator"); 742 return nullptr; 743 } |
509 consume('='); 510 expr = new binary_operator<9, std::equal_to<valty>>("=="); | 744 expr = new binary_operator<9, std::equal_to<valty>>(l, "=="); |
511 break; 512 case '!': | 745 break; 746 case '!': |
513 if ((*this)[1] != '=') | 747 if (peek() != '=') |
514 { 515 parse_error("Invalid operator"); 516 return nullptr; 517 } 518 cursor++; | 748 { 749 parse_error("Invalid operator"); 750 return nullptr; 751 } 752 cursor++; |
519 expr = new binary_operator<9, std::not_equal_to<valty>>("!="); | 753 expr = new binary_operator<9, std::not_equal_to<valty>>(l, "!="); |
520 break; 521 case '&': | 754 break; 755 case '&': |
522 if ((*this)[1] == '&') | 756 if (peek() == '&') |
523 { | 757 { |
524 expr = new binary_operator<13, std::logical_and<valty>>("&&"); | 758 expr = new binary_operator<13, std::logical_and<valty>>(l, "&&"); |
525 } 526 else 527 { | 759 } 760 else 761 { |
528 expr = new binary_operator<10, std::bit_and<valty>>("&"); | 762 expr = new binary_operator<10, std::bit_and<valty>>(l, "&"); |
529 } 530 break; 531 case '|': | 763 } 764 break; 765 case '|': |
532 if ((*this)[1] == '|') | 766 if (peek() == '|') |
533 { | 767 { |
534 expr = new binary_operator<12, std::logical_or<valty>>("||"); | 768 expr = new binary_operator<12, std::logical_or<valty>>(l, "||"); |
535 } 536 else 537 { | 769 } 770 else 771 { |
538 expr = new binary_operator<14, std::bit_or<valty>>("|"); | 772 expr = new binary_operator<14, std::bit_or<valty>>(l, "|"); |
539 } 540 break; 541 case '?': 542 { 543 consume('?'); 544 expression_ptr true_case = parse_expression(); 545 next_token(); 546 if (!true_case || !consume(':')) 547 { 548 parse_error("Expected : in ternary conditional operator"); 549 return nullptr; 550 } 551 expression_ptr false_case = parse_expression(); 552 if (!false_case) 553 { 554 parse_error("Expected false condition for ternary operator"); 555 return nullptr; 556 } | 773 } 774 break; 775 case '?': 776 { 777 consume('?'); 778 expression_ptr true_case = parse_expression(); 779 next_token(); 780 if (!true_case || !consume(':')) 781 { 782 parse_error("Expected : in ternary conditional operator"); 783 return nullptr; 784 } 785 expression_ptr false_case = parse_expression(); 786 if (!false_case) 787 { 788 parse_error("Expected false condition for ternary operator"); 789 return nullptr; 790 } |
557 return expression_ptr(new ternary_conditional_operator(std::move(lhs), | 791 return expression_ptr(new ternary_conditional_operator(l, std::move(lhs), |
558 std::move(true_case), std::move(false_case))); 559 } 560 } | 792 std::move(true_case), std::move(false_case))); 793 } 794 } |
561 cursor++; | 795 ++(*this); |
562 next_token(); 563 expression_ptr e(expr); 564 expression_ptr rhs(parse_expression()); 565 if (!rhs) 566 { 567 return nullptr; 568 } 569 expr->lhs = std::move(lhs); --- 9 unchanged lines hidden (view full) --- 579 static_cast<binary_operator_base*>(rhs.get()); 580 rhs_op->insert_left(expr); 581 e.release(); 582 return rhs; 583 } 584 return e; 585} 586 | 796 next_token(); 797 expression_ptr e(expr); 798 expression_ptr rhs(parse_expression()); 799 if (!rhs) 800 { 801 return nullptr; 802 } 803 expr->lhs = std::move(lhs); --- 9 unchanged lines hidden (view full) --- 813 static_cast<binary_operator_base*>(rhs.get()); 814 rhs_op->insert_left(expr); 815 e.release(); 816 return rhs; 817 } 818 return e; 819} 820 |
587expression_ptr input_buffer::parse_expression(bool stopAtParen) | 821expression_ptr text_input_buffer::parse_expression(bool stopAtParen) |
588{ 589 next_token(); 590 unsigned long long leftVal; 591 expression_ptr lhs; | 822{ 823 next_token(); 824 unsigned long long leftVal; 825 expression_ptr lhs; |
592 switch ((*this)[0]) | 826 source_location l = location(); 827 switch (*(*this)) |
593 { 594 case '0'...'9': 595 if (!consume_integer(leftVal)) 596 { 597 return nullptr; 598 } | 828 { 829 case '0'...'9': 830 if (!consume_integer(leftVal)) 831 { 832 return nullptr; 833 } |
599 lhs.reset(new terminal_expr(leftVal)); | 834 lhs.reset(new terminal_expr(l, leftVal)); |
600 break; 601 case '(': 602 { 603 consume('('); 604 expression_ptr &&subexpr = parse_expression(); 605 if (!subexpr) 606 { 607 return nullptr; 608 } | 835 break; 836 case '(': 837 { 838 consume('('); 839 expression_ptr &&subexpr = parse_expression(); 840 if (!subexpr) 841 { 842 return nullptr; 843 } |
609 lhs.reset(new paren_expression(std::move(subexpr))); | 844 lhs.reset(new paren_expression(l, std::move(subexpr))); |
610 if (!consume(')')) 611 { 612 return nullptr; 613 } 614 if (stopAtParen) 615 { 616 return lhs; 617 } 618 break; 619 } 620 case '+': 621 { 622 consume('+'); 623 expression_ptr &&subexpr = parse_expression(); 624 if (!subexpr) 625 { 626 return nullptr; 627 } | 845 if (!consume(')')) 846 { 847 return nullptr; 848 } 849 if (stopAtParen) 850 { 851 return lhs; 852 } 853 break; 854 } 855 case '+': 856 { 857 consume('+'); 858 expression_ptr &&subexpr = parse_expression(); 859 if (!subexpr) 860 { 861 return nullptr; 862 } |
628 lhs.reset(new unary_operator<'+', unary_plus<valty>>(std::move(subexpr))); | 863 lhs.reset(new unary_operator<'+', unary_plus<valty>>(l, std::move(subexpr))); |
629 break; 630 } 631 case '-': 632 { 633 consume('-'); 634 expression_ptr &&subexpr = parse_expression(); 635 if (!subexpr) 636 { 637 return nullptr; 638 } | 864 break; 865 } 866 case '-': 867 { 868 consume('-'); 869 expression_ptr &&subexpr = parse_expression(); 870 if (!subexpr) 871 { 872 return nullptr; 873 } |
639 lhs.reset(new unary_operator<'-', std::negate<valty>>(std::move(subexpr))); | 874 lhs.reset(new unary_operator<'-', std::negate<valty>>(l, std::move(subexpr))); |
640 break; 641 } 642 case '!': 643 { 644 consume('!'); 645 expression_ptr &&subexpr = parse_expression(); 646 if (!subexpr) 647 { 648 return nullptr; 649 } | 875 break; 876 } 877 case '!': 878 { 879 consume('!'); 880 expression_ptr &&subexpr = parse_expression(); 881 if (!subexpr) 882 { 883 return nullptr; 884 } |
650 lhs.reset(new unary_operator<'!', std::logical_not<valty>>(std::move(subexpr))); | 885 lhs.reset(new unary_operator<'!', std::logical_not<valty>>(l, std::move(subexpr))); |
651 break; 652 } 653 case '~': 654 { 655 consume('~'); 656 expression_ptr &&subexpr = parse_expression(); 657 if (!subexpr) 658 { 659 return nullptr; 660 } | 886 break; 887 } 888 case '~': 889 { 890 consume('~'); 891 expression_ptr &&subexpr = parse_expression(); 892 if (!subexpr) 893 { 894 return nullptr; 895 } |
661 lhs.reset(new unary_operator<'~', bit_not<valty>>(std::move(subexpr))); | 896 lhs.reset(new unary_operator<'~', bit_not<valty>>(l, std::move(subexpr))); |
662 break; 663 } 664 } 665 if (!lhs) 666 { 667 return nullptr; 668 } 669 return parse_binary_expression(std::move(lhs)); 670} 671 672bool | 897 break; 898 } 899 } 900 if (!lhs) 901 { 902 return nullptr; 903 } 904 return parse_binary_expression(std::move(lhs)); 905} 906 907bool |
673input_buffer::consume_integer_expression(unsigned long long &outInt) | 908text_input_buffer::consume_integer_expression(unsigned long long &outInt) |
674{ | 909{ |
675 switch ((*this)[0]) | 910 switch (*(*this)) |
676 { 677 case '(': 678 { 679 expression_ptr e(parse_expression(true)); 680 if (!e) 681 { 682 return false; 683 } | 911 { 912 case '(': 913 { 914 expression_ptr e(parse_expression(true)); 915 if (!e) 916 { 917 return false; 918 } |
684 outInt = (*e)(); 685 return true; | 919 auto r = (*e)(); 920 if (r.second) 921 { 922 outInt = r.first; 923 return true; 924 } 925 return false; |
686 } 687 case '0'...'9': 688 return consume_integer(outInt); 689 default: 690 return false; 691 } 692} 693 --- 4 unchanged lines hidden (view full) --- 698 { 699 return false; 700 } 701 outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]); 702 cursor += 2; 703 return true; 704} 705 | 926 } 927 case '0'...'9': 928 return consume_integer(outInt); 929 default: 930 return false; 931 } 932} 933 --- 4 unchanged lines hidden (view full) --- 938 { 939 return false; 940 } 941 outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]); 942 cursor += 2; 943 return true; 944} 945 |
706input_buffer& 707input_buffer::next_token() | 946text_input_buffer& 947text_input_buffer::next_token() |
708{ | 948{ |
949 auto &self = *this; |
|
709 int start; 710 do { 711 start = cursor; 712 skip_spaces(); | 950 int start; 951 do { 952 start = cursor; 953 skip_spaces(); |
954 if (finished()) 955 { 956 return self; 957 } |
|
713 // Parse /* comments | 958 // Parse /* comments |
714 if ((*this)[0] == '/' && (*this)[1] == '*') | 959 if (*self == '/' && peek() == '*') |
715 { 716 // eat the start of the comment | 960 { 961 // eat the start of the comment |
717 ++(*this); 718 ++(*this); | 962 ++self; 963 ++self; |
719 do { 720 // Find the ending * of */ | 964 do { 965 // Find the ending * of */ |
721 while ((**this != '\0') && (**this != '*')) | 966 while ((*self != '\0') && (*self != '*') && !finished()) |
722 { | 967 { |
723 ++(*this); | 968 ++self; |
724 } 725 // Eat the * | 969 } 970 // Eat the * |
726 ++(*this); 727 } while ((**this != '\0') && (**this != '/')); | 971 ++self; 972 } while ((*self != '\0') && (*self != '/') && !finished()); |
728 // Eat the / | 973 // Eat the / |
729 ++(*this); | 974 ++self; |
730 } 731 // Parse // comments | 975 } 976 // Parse // comments |
732 if (((*this)[0] == '/' && (*this)[1] == '/')) | 977 if ((*self == '/' && peek() == '/')) |
733 { 734 // eat the start of the comment | 978 { 979 // eat the start of the comment |
735 ++(*this); 736 ++(*this); | 980 ++self; 981 ++self; |
737 // Find the ending of the line | 982 // Find the ending of the line |
738 while (**this != '\n') | 983 while (*self != '\n' && !finished()) |
739 { | 984 { |
740 ++(*this); | 985 ++self; |
741 } 742 // Eat the \n | 986 } 987 // Eat the \n |
743 ++(*this); | 988 ++self; |
744 } 745 } while (start != cursor); | 989 } 990 } while (start != cursor); |
746 return *this; | 991 return self; |
747} 748 749void | 992} 993 994void |
750input_buffer::parse_error(const char *msg) | 995text_input_buffer::parse_error(const char *msg) |
751{ | 996{ |
997 if (input_stack.empty()) 998 { 999 fprintf(stderr, "Error: %s\n", msg); 1000 return; 1001 } 1002 input_buffer &b = *input_stack.top(); 1003 parse_error(msg, b, b.cursor); 1004} 1005void 1006text_input_buffer::parse_error(const char *msg, 1007 input_buffer &b, 1008 int loc) 1009{ |
|
752 int line_count = 1; 753 int line_start = 0; | 1010 int line_count = 1; 1011 int line_start = 0; |
754 int line_end = cursor; 755 for (int i=cursor ; i>0 ; --i) | 1012 int line_end = loc; 1013 if (loc < 0 || loc > b.size) |
756 { | 1014 { |
757 if (buffer[i] == '\n') | 1015 return; 1016 } 1017 for (int i=loc ; i>0 ; --i) 1018 { 1019 if (b.buffer[i] == '\n') |
758 { 759 line_count++; 760 if (line_start == 0) 761 { 762 line_start = i+1; 763 } 764 } 765 } | 1020 { 1021 line_count++; 1022 if (line_start == 0) 1023 { 1024 line_start = i+1; 1025 } 1026 } 1027 } |
766 for (int i=cursor+1 ; i<size ; ++i) | 1028 for (int i=loc+1 ; i<b.size ; ++i) |
767 { | 1029 { |
768 if (buffer[i] == '\n') | 1030 if (b.buffer[i] == '\n') |
769 { 770 line_end = i; 771 break; 772 } 773 } | 1031 { 1032 line_end = i; 1033 break; 1034 } 1035 } |
774 fprintf(stderr, "Error on line %d: %s\n", line_count, msg); 775 fwrite(&buffer[line_start], line_end-line_start, 1, stderr); | 1036 fprintf(stderr, "Error at %s:%d:%d: %s\n", b.filename().c_str(), line_count, loc - line_start, msg); 1037 fwrite(&b.buffer[line_start], line_end-line_start, 1, stderr); |
776 putc('\n', stderr); | 1038 putc('\n', stderr); |
777 for (int i=0 ; i<(cursor-line_start) ; ++i) | 1039 for (int i=0 ; i<(loc-line_start) ; ++i) |
778 { | 1040 { |
779 char c = (buffer[i+line_start] == '\t') ? '\t' : ' '; | 1041 char c = (b.buffer[i+line_start] == '\t') ? '\t' : ' '; |
780 putc(c, stderr); 781 } 782 putc('^', stderr); 783 putc('\n', stderr); 784} 785#ifndef NDEBUG 786void 787input_buffer::dump() 788{ 789 fprintf(stderr, "Current cursor: %d\n", cursor); 790 fwrite(&buffer[cursor], size-cursor, 1, stderr); 791} 792#endif 793 | 1042 putc(c, stderr); 1043 } 1044 putc('^', stderr); 1045 putc('\n', stderr); 1046} 1047#ifndef NDEBUG 1048void 1049input_buffer::dump() 1050{ 1051 fprintf(stderr, "Current cursor: %d\n", cursor); 1052 fwrite(&buffer[cursor], size-cursor, 1, stderr); 1053} 1054#endif 1055 |
794mmap_input_buffer::mmap_input_buffer(int fd) : input_buffer(0, 0) | 1056 1057namespace |
795{ | 1058{ |
796 struct stat sb; 797 if (fstat(fd, &sb)) | 1059/** 1060 * The source files are ASCII, so we provide a non-locale-aware version of 1061 * isalpha. This is a class so that it can be used with a template function 1062 * for parsing strings. 1063 */ 1064struct is_alpha 1065{ 1066 static inline bool check(const char c) |
798 { | 1067 { |
799 perror("Failed to stat file"); | 1068 return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && 1069 (c <= 'Z')); |
800 } | 1070 } |
801 size = sb.st_size; 802 buffer = (const char*)mmap(0, size, PROT_READ, MAP_PRIVATE | 803 MAP_PREFAULT_READ, fd, 0); 804 if (buffer == MAP_FAILED) | 1071}; 1072/** 1073 * Check whether a character is in the set allowed for node names. This is a 1074 * class so that it can be used with a template function for parsing strings. 1075 */ 1076struct is_node_name_character 1077{ 1078 static inline bool check(const char c) |
805 { | 1079 { |
806 perror("Failed to mmap file"); 807 exit(EXIT_FAILURE); | 1080 switch(c) 1081 { 1082 default: 1083 return false; 1084 case 'a'...'z': case 'A'...'Z': case '0'...'9': 1085 case ',': case '.': case '+': case '-': 1086 case '_': 1087 return true; 1088 } |
808 } | 1089 } |
1090}; 1091/** 1092 * Check whether a character is in the set allowed for property names. This is 1093 * a class so that it can be used with a template function for parsing strings. 1094 */ 1095struct is_property_name_character 1096{ 1097 static inline bool check(const char c) 1098 { 1099 switch(c) 1100 { 1101 default: 1102 return false; 1103 case 'a'...'z': case 'A'...'Z': case '0'...'9': 1104 case ',': case '.': case '+': case '-': 1105 case '_': case '#': 1106 return true; 1107 } 1108 } 1109}; 1110 1111template<class T> 1112string parse(text_input_buffer &s) 1113{ 1114 std::vector<char> bytes; 1115 for (char c=*s ; T::check(c) ; c=*(++s)) 1116 { 1117 bytes.push_back(c); 1118 } 1119 return string(bytes.begin(), bytes.end()); |
|
809} 810 | 1120} 1121 |
811mmap_input_buffer::~mmap_input_buffer() | 1122} 1123 1124string 1125text_input_buffer::parse_node_name() |
812{ | 1126{ |
813 if (buffer != 0) | 1127 return parse<is_node_name_character>(*this); 1128} 1129 1130string 1131text_input_buffer::parse_property_name() 1132{ 1133 return parse<is_property_name_character>(*this); 1134} 1135 1136string 1137text_input_buffer::parse_node_or_property_name(bool &is_property) 1138{ 1139 if (is_property) |
814 { | 1140 { |
815 munmap((void*)buffer, size); | 1141 return parse_property_name(); |
816 } | 1142 } |
1143 std::vector<char> bytes; 1144 for (char c=*(*this) ; is_node_name_character::check(c) ; c=*(++(*this))) 1145 { 1146 bytes.push_back(c); 1147 } 1148 for (char c=*(*this) ; is_property_name_character::check(c) ; c=*(++(*this))) 1149 { 1150 bytes.push_back(c); 1151 is_property = true; 1152 } 1153 return string(bytes.begin(), bytes.end()); |
|
817} 818 | 1154} 1155 |
819stream_input_buffer::stream_input_buffer() : input_buffer(0, 0) | 1156string 1157input_buffer::parse_to(char stop) |
820{ | 1158{ |
821 int c; 822 while ((c = fgetc(stdin)) != EOF) | 1159 std::vector<char> bytes; 1160 for (char c=*(*this) ; c != stop ; c=*(++(*this))) |
823 { | 1161 { |
824 b.push_back(c); | 1162 bytes.push_back(c); |
825 } | 1163 } |
826 buffer = b.data(); 827 size = b.size(); | 1164 return string(bytes.begin(), bytes.end()); |
828} 829 | 1165} 1166 |
1167string 1168text_input_buffer::parse_to(char stop) 1169{ 1170 std::vector<char> bytes; 1171 for (char c=*(*this) ; c != stop ; c=*(++(*this))) 1172 { 1173 if (finished()) 1174 { 1175 break; 1176 } 1177 bytes.push_back(c); 1178 } 1179 return string(bytes.begin(), bytes.end()); 1180} 1181 1182char 1183text_input_buffer::peek() 1184{ 1185 return (*input_stack.top())[1]; 1186} 1187 1188std::unique_ptr<input_buffer> 1189input_buffer::buffer_for_file(const string &path, bool warn) 1190{ 1191 if (path == "-") 1192 { 1193 std::unique_ptr<input_buffer> b(new stream_input_buffer()); 1194 return b; 1195 } 1196 int source = open(path.c_str(), O_RDONLY); 1197 if (source == -1) 1198 { 1199 if (warn) 1200 { 1201 fprintf(stderr, "Unable to open file '%s'. %s\n", path.c_str(), strerror(errno)); 1202 } 1203 return 0; 1204 } 1205 struct stat st; 1206 if (fstat(source, &st) == 0 && S_ISDIR(st.st_mode)) 1207 { 1208 if (warn) 1209 { 1210 fprintf(stderr, "File %s is a directory\n", path.c_str()); 1211 } 1212 close(source); 1213 return 0; 1214 } 1215 std::unique_ptr<input_buffer> b(new mmap_input_buffer(source, std::string(path))); 1216 close(source); 1217 return b; 1218} 1219 |
|
830} // namespace dtc 831 | 1220} // namespace dtc 1221 |