1245803Stheraven/*- 2245803Stheraven * Copyright (c) 2013 David Chisnall 3245803Stheraven * All rights reserved. 4245803Stheraven * 5245803Stheraven * This software was developed by SRI International and the University of 6245803Stheraven * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7245803Stheraven * ("CTSRD"), as part of the DARPA CRASH research programme. 8245803Stheraven * 9245803Stheraven * Redistribution and use in source and binary forms, with or without 10245803Stheraven * modification, are permitted provided that the following conditions 11245803Stheraven * are met: 12245803Stheraven * 1. Redistributions of source code must retain the above copyright 13245803Stheraven * notice, this list of conditions and the following disclaimer. 14245803Stheraven * 2. Redistributions in binary form must reproduce the above copyright 15245803Stheraven * notice, this list of conditions and the following disclaimer in the 16245803Stheraven * documentation and/or other materials provided with the distribution. 17245803Stheraven * 18245803Stheraven * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19245803Stheraven * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20245803Stheraven * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21245803Stheraven * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22245803Stheraven * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23245803Stheraven * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24245803Stheraven * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25245803Stheraven * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26245803Stheraven * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27245803Stheraven * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28245803Stheraven * SUCH DAMAGE. 29245803Stheraven * 30245803Stheraven * $FreeBSD: releng/11.0/usr.bin/dtc/input_buffer.cc 292876 2015-12-29 16:29:42Z theraven $ 31245803Stheraven */ 32245803Stheraven 33245803Stheraven#include "input_buffer.hh" 34245839Stheraven#include <ctype.h> 35245839Stheraven#include <limits.h> 36245839Stheraven#include <stdint.h> 37245839Stheraven#include <stdio.h> 38245839Stheraven#include <stdlib.h> 39245803Stheraven#include <string.h> 40292876Stheraven#include <functional> 41292876Stheraven#ifndef NDEBUG 42292876Stheraven#include <iostream> 43292876Stheraven#endif 44245803Stheraven 45245839Stheraven 46245803Stheraven#include <sys/stat.h> 47245803Stheraven#include <sys/mman.h> 48245803Stheraven#include <assert.h> 49245803Stheraven 50247006Suqs#ifndef MAP_PREFAULT_READ 51247006Suqs#define MAP_PREFAULT_READ 0 52247006Suqs#endif 53247006Suqs 54245803Stheravennamespace dtc 55245803Stheraven{ 56245803Stheravenvoid 57245803Stheraveninput_buffer::skip_spaces() 58245803Stheraven{ 59245803Stheraven if (cursor >= size) { return; } 60245803Stheraven if (cursor < 0) { return; } 61245803Stheraven char c = buffer[cursor]; 62245803Stheraven while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f') 63245803Stheraven || (c == '\v') || (c == '\r')) 64245803Stheraven { 65245803Stheraven cursor++; 66245803Stheraven if (cursor > size) 67245803Stheraven { 68245803Stheraven c = '\0'; 69245803Stheraven } 70245803Stheraven else 71245803Stheraven { 72245803Stheraven c = buffer[cursor]; 73245803Stheraven } 74245803Stheraven } 75245803Stheraven} 76245803Stheraven 77245803Stheraveninput_buffer 78245803Stheraveninput_buffer::buffer_from_offset(int offset, int s) 79245803Stheraven{ 80245803Stheraven if (s == 0) 81245803Stheraven { 82245803Stheraven s = size - offset; 83245803Stheraven } 84245803Stheraven if (offset > size) 85245803Stheraven { 86245803Stheraven return input_buffer(); 87245803Stheraven } 88245803Stheraven if (s > (size-offset)) 89245803Stheraven { 90245803Stheraven return input_buffer(); 91245803Stheraven } 92245803Stheraven return input_buffer(&buffer[offset], s); 93245803Stheraven} 94245803Stheraven 95245803Stheravenbool 96245803Stheraveninput_buffer::consume(const char *str) 97245803Stheraven{ 98245803Stheraven int len = strlen(str); 99245803Stheraven if (len > size - cursor) 100245803Stheraven { 101245803Stheraven return false; 102245803Stheraven } 103245803Stheraven else 104245803Stheraven { 105245803Stheraven for (int i=0 ; i<len ; ++i) 106245803Stheraven { 107245803Stheraven if (str[i] != buffer[cursor + i]) 108245803Stheraven { 109245803Stheraven return false; 110245803Stheraven } 111245803Stheraven } 112245803Stheraven cursor += len; 113245803Stheraven return true; 114245803Stheraven } 115245803Stheraven return false; 116245803Stheraven} 117245803Stheraven 118245803Stheravenbool 119289935Stheraveninput_buffer::consume_integer(unsigned long long &outInt) 120245803Stheraven{ 121245803Stheraven // The first character must be a digit. Hex and octal strings 122245803Stheraven // are prefixed by 0 and 0x, respectively. 123245803Stheraven if (!isdigit((*this)[0])) 124245803Stheraven { 125245803Stheraven return false; 126245803Stheraven } 127245803Stheraven char *end=0; 128289935Stheraven outInt = strtoull(&buffer[cursor], &end, 0); 129245803Stheraven if (end == &buffer[cursor]) 130245803Stheraven { 131245803Stheraven return false; 132245803Stheraven } 133245803Stheraven cursor = end - buffer; 134245803Stheraven return true; 135245803Stheraven} 136245803Stheraven 137292876Stheravennamespace { 138292876Stheraven 139292876Stheraven/** 140292876Stheraven * Convenience typedef for the type that we use for all values. 141292876Stheraven */ 142292876Stheraventypedef unsigned long long valty; 143292876Stheraven 144292876Stheraven/** 145292876Stheraven * Expression tree currently being parsed. 146292876Stheraven */ 147292876Stheravenstruct expression 148292876Stheraven{ 149292876Stheraven /** 150292876Stheraven * Evaluate this node, taking into account operator precedence. 151292876Stheraven */ 152292876Stheraven virtual valty operator()() = 0; 153292876Stheraven /** 154292876Stheraven * Returns the precedence of this node. Lower values indicate higher 155292876Stheraven * precedence. 156292876Stheraven */ 157292876Stheraven virtual int precedence() = 0; 158292876Stheraven virtual ~expression() {} 159292876Stheraven#ifndef NDEBUG 160292876Stheraven /** 161292876Stheraven * Dumps this expression to `std::cerr`, appending a newline if `nl` is 162292876Stheraven * `true`. 163292876Stheraven */ 164292876Stheraven void dump(bool nl=false) 165292876Stheraven { 166292876Stheraven if (this == nullptr) 167292876Stheraven { 168292876Stheraven std::cerr << "{nullptr}\n"; 169292876Stheraven return; 170292876Stheraven } 171292876Stheraven dump_impl(); 172292876Stheraven if (nl) 173292876Stheraven { 174292876Stheraven std::cerr << '\n'; 175292876Stheraven } 176292876Stheraven } 177292876Stheraven private: 178292876Stheraven /** 179292876Stheraven * Method that sublcasses override to implement the behaviour of `dump()`. 180292876Stheraven */ 181292876Stheraven virtual void dump_impl() = 0; 182292876Stheraven#endif 183292876Stheraven}; 184292876Stheraven 185292876Stheraven/** 186292876Stheraven * Expression wrapping a single integer. Leaf nodes in the expression tree. 187292876Stheraven */ 188292876Stheravenclass terminal_expr : public expression 189292876Stheraven{ 190292876Stheraven /** 191292876Stheraven * The value that this wraps. 192292876Stheraven */ 193292876Stheraven valty val; 194292876Stheraven /** 195292876Stheraven * Evaluate. Trivially returns the value that this class wraps. 196292876Stheraven */ 197292876Stheraven valty operator()() override 198292876Stheraven { 199292876Stheraven return val; 200292876Stheraven } 201292876Stheraven int precedence() override 202292876Stheraven { 203292876Stheraven return 0; 204292876Stheraven } 205292876Stheraven public: 206292876Stheraven /** 207292876Stheraven * Constructor. 208292876Stheraven */ 209292876Stheraven terminal_expr(valty v) : val(v) {} 210292876Stheraven#ifndef NDEBUG 211292876Stheraven void dump_impl() override { std::cerr << val; } 212292876Stheraven#endif 213292876Stheraven}; 214292876Stheraven 215292876Stheraven/** 216292876Stheraven * Parenthetical expression. Exists to make the contents opaque. 217292876Stheraven */ 218292876Stheravenstruct paren_expression : public expression 219292876Stheraven{ 220292876Stheraven /** 221292876Stheraven * The expression within the parentheses. 222292876Stheraven */ 223292876Stheraven expression_ptr subexpr; 224292876Stheraven /** 225292876Stheraven * Constructor. Takes the child expression as the only argument. 226292876Stheraven */ 227292876Stheraven paren_expression(expression_ptr p) : subexpr(std::move(p)) {} 228292876Stheraven int precedence() override 229292876Stheraven { 230292876Stheraven return 0; 231292876Stheraven } 232292876Stheraven /** 233292876Stheraven * Evaluate - just forwards to the underlying expression. 234292876Stheraven */ 235292876Stheraven valty operator()() override 236292876Stheraven { 237292876Stheraven return (*subexpr)(); 238292876Stheraven } 239292876Stheraven#ifndef NDEBUG 240292876Stheraven void dump_impl() override 241292876Stheraven { 242292876Stheraven std::cerr << " ("; 243292876Stheraven subexpr->dump(); 244292876Stheraven std::cerr << ") "; 245292876Stheraven } 246292876Stheraven#endif 247292876Stheraven}; 248292876Stheraven 249292876Stheraven/** 250292876Stheraven * Template class for unary operators. The `OpChar` template parameter is 251292876Stheraven * solely for debugging and makes it easy to print the expression. The `Op` 252292876Stheraven * template parameter is a function object that implements the operator that 253292876Stheraven * this class provides. Most of these are provided by the `<functional>` 254292876Stheraven * header. 255292876Stheraven */ 256292876Stheraventemplate<char OpChar, class Op> 257292876Stheravenclass unary_operator : public expression 258292876Stheraven{ 259292876Stheraven /** 260292876Stheraven * The subexpression for this unary operator. 261292876Stheraven */ 262292876Stheraven expression_ptr subexpr; 263292876Stheraven valty operator()() override 264292876Stheraven { 265292876Stheraven Op op; 266292876Stheraven return op((*subexpr)()); 267292876Stheraven } 268292876Stheraven /** 269292876Stheraven * All unary operators have the same precedence. They are all evaluated 270292876Stheraven * before binary expressions, but after parentheses. 271292876Stheraven */ 272292876Stheraven int precedence() override 273292876Stheraven { 274292876Stheraven return 3; 275292876Stheraven } 276292876Stheraven public: 277292876Stheraven unary_operator(expression_ptr p) : subexpr(std::move(p)) {} 278292876Stheraven#ifndef NDEBUG 279292876Stheraven void dump_impl() override 280292876Stheraven { 281292876Stheraven std::cerr << OpChar; 282292876Stheraven subexpr->dump(); 283292876Stheraven } 284292876Stheraven#endif 285292876Stheraven}; 286292876Stheraven 287292876Stheraven/** 288292876Stheraven * Abstract base class for binary operators. Allows the tree to be modified 289292876Stheraven * without knowing what the operations actually are. 290292876Stheraven */ 291292876Stheravenstruct binary_operator_base : public expression 292292876Stheraven{ 293292876Stheraven /** 294292876Stheraven * The left side of the expression. 295292876Stheraven */ 296292876Stheraven expression_ptr lhs; 297292876Stheraven /** 298292876Stheraven * The right side of the expression. 299292876Stheraven */ 300292876Stheraven expression_ptr rhs; 301292876Stheraven /** 302292876Stheraven * Insert a node somewhere down the path of left children, until it would 303292876Stheraven * be preempting something that should execute first. 304292876Stheraven */ 305292876Stheraven void insert_left(binary_operator_base *new_left) 306292876Stheraven { 307292876Stheraven if (lhs->precedence() < new_left->precedence()) 308292876Stheraven { 309292876Stheraven new_left->rhs = std::move(lhs); 310292876Stheraven lhs.reset(new_left); 311292876Stheraven } 312292876Stheraven else 313292876Stheraven { 314292876Stheraven static_cast<binary_operator_base*>(lhs.get())->insert_left(new_left); 315292876Stheraven } 316292876Stheraven } 317292876Stheraven}; 318292876Stheraven 319292876Stheraven/** 320292876Stheraven * Template class for binary operators. The precedence and the operation are 321292876Stheraven * provided as template parameters. 322292876Stheraven */ 323292876Stheraventemplate<int Precedence, class Op> 324292876Stheravenstruct binary_operator : public binary_operator_base 325292876Stheraven{ 326292876Stheraven valty operator()() override 327292876Stheraven { 328292876Stheraven Op op; 329292876Stheraven return op((*lhs)(), (*rhs)()); 330292876Stheraven } 331292876Stheraven int precedence() override 332292876Stheraven { 333292876Stheraven return Precedence; 334292876Stheraven } 335292876Stheraven#ifdef NDEBUG 336292876Stheraven /** 337292876Stheraven * Constructor. Takes the name of the operator as an argument, for 338292876Stheraven * debugging. Only stores it in debug mode. 339292876Stheraven */ 340292876Stheraven binary_operator(const char *) {} 341292876Stheraven#else 342292876Stheraven const char *opName; 343292876Stheraven binary_operator(const char *o) : opName(o) {} 344292876Stheraven void dump_impl() override 345292876Stheraven { 346292876Stheraven lhs->dump(); 347292876Stheraven std::cerr << opName; 348292876Stheraven rhs->dump(); 349292876Stheraven } 350292876Stheraven#endif 351292876Stheraven}; 352292876Stheraven 353292876Stheraven/** 354292876Stheraven * Ternary conditional operators (`cond ? true : false`) are a special case - 355292876Stheraven * there are no other ternary operators. 356292876Stheraven */ 357292876Stheravenclass ternary_conditional_operator : public expression 358292876Stheraven{ 359292876Stheraven /** 360292876Stheraven * The condition for the clause. 361292876Stheraven */ 362292876Stheraven expression_ptr cond; 363292876Stheraven /** 364292876Stheraven * The expression that this evaluates to if the condition is true. 365292876Stheraven */ 366292876Stheraven expression_ptr lhs; 367292876Stheraven /** 368292876Stheraven * The expression that this evaluates to if the condition is false. 369292876Stheraven */ 370292876Stheraven expression_ptr rhs; 371292876Stheraven valty operator()() override 372292876Stheraven { 373292876Stheraven return (*cond)() ? (*lhs)() : (*rhs)(); 374292876Stheraven } 375292876Stheraven int precedence() override 376292876Stheraven { 377292876Stheraven // The actual precedence of a ternary conditional operator is 15, but 378292876Stheraven // its associativity is the opposite way around to the other operators, 379292876Stheraven // so we fudge it slightly. 380292876Stheraven return 3; 381292876Stheraven } 382292876Stheraven#ifndef NDEBUG 383292876Stheraven void dump_impl() override 384292876Stheraven { 385292876Stheraven cond->dump(); 386292876Stheraven std::cerr << " ? "; 387292876Stheraven lhs->dump(); 388292876Stheraven std::cerr << " : "; 389292876Stheraven rhs->dump(); 390292876Stheraven } 391292876Stheraven#endif 392292876Stheraven public: 393292876Stheraven ternary_conditional_operator(expression_ptr c, 394292876Stheraven expression_ptr l, 395292876Stheraven expression_ptr r) : 396292876Stheraven cond(std::move(c)), lhs(std::move(l)), rhs(std::move(r)) {} 397292876Stheraven}; 398292876Stheraven 399292876Stheraventemplate<typename T> 400292876Stheravenstruct lshift 401292876Stheraven{ 402292876Stheraven constexpr T operator()(const T &lhs, const T &rhs) const 403292876Stheraven { 404292876Stheraven return lhs << rhs; 405292876Stheraven } 406292876Stheraven}; 407292876Stheraventemplate<typename T> 408292876Stheravenstruct rshift 409292876Stheraven{ 410292876Stheraven constexpr T operator()(const T &lhs, const T &rhs) const 411292876Stheraven { 412292876Stheraven return lhs >> rhs; 413292876Stheraven } 414292876Stheraven}; 415292876Stheraventemplate<typename T> 416292876Stheravenstruct unary_plus 417292876Stheraven{ 418292876Stheraven constexpr T operator()(const T &val) const 419292876Stheraven { 420292876Stheraven return +val; 421292876Stheraven } 422292876Stheraven}; 423292876Stheraven// TODO: Replace with std::bit_not once we can guarantee C++14 as a baseline. 424292876Stheraventemplate<typename T> 425292876Stheravenstruct bit_not 426292876Stheraven{ 427292876Stheraven constexpr T operator()(const T &val) const 428292876Stheraven { 429292876Stheraven return ~val; 430292876Stheraven } 431292876Stheraven}; 432292876Stheraven 433292876Stheraven} // anonymous namespace 434292876Stheraven 435292876Stheraven 436292876Stheravenexpression_ptr input_buffer::parse_binary_expression(expression_ptr lhs) 437292876Stheraven{ 438292876Stheraven next_token(); 439292876Stheraven binary_operator_base *expr = nullptr; 440292876Stheraven char op = ((*this)[0]); 441292876Stheraven switch (op) 442292876Stheraven { 443292876Stheraven default: 444292876Stheraven return lhs; 445292876Stheraven case '+': 446292876Stheraven expr = new binary_operator<6, std::plus<valty>>("+"); 447292876Stheraven break; 448292876Stheraven case '-': 449292876Stheraven expr = new binary_operator<6, std::minus<valty>>("-"); 450292876Stheraven break; 451292876Stheraven case '%': 452292876Stheraven expr = new binary_operator<5, std::modulus<valty>>("%"); 453292876Stheraven break; 454292876Stheraven case '*': 455292876Stheraven expr = new binary_operator<5, std::multiplies<valty>>("*"); 456292876Stheraven break; 457292876Stheraven case '/': 458292876Stheraven expr = new binary_operator<5, std::divides<valty>>("/"); 459292876Stheraven break; 460292876Stheraven case '<': 461292876Stheraven cursor++; 462292876Stheraven switch ((*this)[0]) 463292876Stheraven { 464292876Stheraven default: 465292876Stheraven parse_error("Invalid operator"); 466292876Stheraven return nullptr; 467292876Stheraven case ' ': 468292876Stheraven case '(': 469292876Stheraven case '0'...'9': 470292876Stheraven cursor--; 471292876Stheraven expr = new binary_operator<8, std::less<valty>>("<"); 472292876Stheraven break; 473292876Stheraven case '=': 474292876Stheraven expr = new binary_operator<8, std::less_equal<valty>>("<="); 475292876Stheraven break; 476292876Stheraven case '<': 477292876Stheraven expr = new binary_operator<7, lshift<valty>>("<<"); 478292876Stheraven break; 479292876Stheraven } 480292876Stheraven break; 481292876Stheraven case '>': 482292876Stheraven cursor++; 483292876Stheraven switch ((*this)[0]) 484292876Stheraven { 485292876Stheraven default: 486292876Stheraven parse_error("Invalid operator"); 487292876Stheraven return nullptr; 488292876Stheraven case '(': 489292876Stheraven case ' ': 490292876Stheraven case '0'...'9': 491292876Stheraven cursor--; 492292876Stheraven expr = new binary_operator<8, std::greater<valty>>(">"); 493292876Stheraven break; 494292876Stheraven case '=': 495292876Stheraven expr = new binary_operator<8, std::greater_equal<valty>>(">="); 496292876Stheraven break; 497292876Stheraven case '>': 498292876Stheraven expr = new binary_operator<7, rshift<valty>>(">>"); 499292876Stheraven break; 500292876Stheraven return lhs; 501292876Stheraven } 502292876Stheraven break; 503292876Stheraven case '=': 504292876Stheraven if ((*this)[1] != '=') 505292876Stheraven { 506292876Stheraven parse_error("Invalid operator"); 507292876Stheraven return nullptr; 508292876Stheraven } 509292876Stheraven consume('='); 510292876Stheraven expr = new binary_operator<9, std::equal_to<valty>>("=="); 511292876Stheraven break; 512292876Stheraven case '!': 513292876Stheraven if ((*this)[1] != '=') 514292876Stheraven { 515292876Stheraven parse_error("Invalid operator"); 516292876Stheraven return nullptr; 517292876Stheraven } 518292876Stheraven cursor++; 519292876Stheraven expr = new binary_operator<9, std::not_equal_to<valty>>("!="); 520292876Stheraven break; 521292876Stheraven case '&': 522292876Stheraven if ((*this)[1] == '&') 523292876Stheraven { 524292876Stheraven expr = new binary_operator<13, std::logical_and<valty>>("&&"); 525292876Stheraven } 526292876Stheraven else 527292876Stheraven { 528292876Stheraven expr = new binary_operator<10, std::bit_and<valty>>("&"); 529292876Stheraven } 530292876Stheraven break; 531292876Stheraven case '|': 532292876Stheraven if ((*this)[1] == '|') 533292876Stheraven { 534292876Stheraven expr = new binary_operator<12, std::logical_or<valty>>("||"); 535292876Stheraven } 536292876Stheraven else 537292876Stheraven { 538292876Stheraven expr = new binary_operator<14, std::bit_or<valty>>("|"); 539292876Stheraven } 540292876Stheraven break; 541292876Stheraven case '?': 542292876Stheraven { 543292876Stheraven consume('?'); 544292876Stheraven expression_ptr true_case = parse_expression(); 545292876Stheraven next_token(); 546292876Stheraven if (!true_case || !consume(':')) 547292876Stheraven { 548292876Stheraven parse_error("Expected : in ternary conditional operator"); 549292876Stheraven return nullptr; 550292876Stheraven } 551292876Stheraven expression_ptr false_case = parse_expression(); 552292876Stheraven if (!false_case) 553292876Stheraven { 554292876Stheraven parse_error("Expected false condition for ternary operator"); 555292876Stheraven return nullptr; 556292876Stheraven } 557292876Stheraven return expression_ptr(new ternary_conditional_operator(std::move(lhs), 558292876Stheraven std::move(true_case), std::move(false_case))); 559292876Stheraven } 560292876Stheraven } 561292876Stheraven cursor++; 562292876Stheraven next_token(); 563292876Stheraven expression_ptr e(expr); 564292876Stheraven expression_ptr rhs(parse_expression()); 565292876Stheraven if (!rhs) 566292876Stheraven { 567292876Stheraven return nullptr; 568292876Stheraven } 569292876Stheraven expr->lhs = std::move(lhs); 570292876Stheraven if (rhs->precedence() < expr->precedence()) 571292876Stheraven { 572292876Stheraven expr->rhs = std::move(rhs); 573292876Stheraven } 574292876Stheraven else 575292876Stheraven { 576292876Stheraven // If we're a normal left-to-right expression, then we need to insert 577292876Stheraven // this as the far-left child node of the rhs expression 578292876Stheraven binary_operator_base *rhs_op = 579292876Stheraven static_cast<binary_operator_base*>(rhs.get()); 580292876Stheraven rhs_op->insert_left(expr); 581292876Stheraven e.release(); 582292876Stheraven return rhs; 583292876Stheraven } 584292876Stheraven return e; 585292876Stheraven} 586292876Stheraven 587292876Stheravenexpression_ptr input_buffer::parse_expression(bool stopAtParen) 588292876Stheraven{ 589292876Stheraven next_token(); 590292876Stheraven unsigned long long leftVal; 591292876Stheraven expression_ptr lhs; 592292876Stheraven switch ((*this)[0]) 593292876Stheraven { 594292876Stheraven case '0'...'9': 595292876Stheraven if (!consume_integer(leftVal)) 596292876Stheraven { 597292876Stheraven return nullptr; 598292876Stheraven } 599292876Stheraven lhs.reset(new terminal_expr(leftVal)); 600292876Stheraven break; 601292876Stheraven case '(': 602292876Stheraven { 603292876Stheraven consume('('); 604292876Stheraven expression_ptr &&subexpr = parse_expression(); 605292876Stheraven if (!subexpr) 606292876Stheraven { 607292876Stheraven return nullptr; 608292876Stheraven } 609292876Stheraven lhs.reset(new paren_expression(std::move(subexpr))); 610292876Stheraven if (!consume(')')) 611292876Stheraven { 612292876Stheraven return nullptr; 613292876Stheraven } 614292876Stheraven if (stopAtParen) 615292876Stheraven { 616292876Stheraven return lhs; 617292876Stheraven } 618292876Stheraven break; 619292876Stheraven } 620292876Stheraven case '+': 621292876Stheraven { 622292876Stheraven consume('+'); 623292876Stheraven expression_ptr &&subexpr = parse_expression(); 624292876Stheraven if (!subexpr) 625292876Stheraven { 626292876Stheraven return nullptr; 627292876Stheraven } 628292876Stheraven lhs.reset(new unary_operator<'+', unary_plus<valty>>(std::move(subexpr))); 629292876Stheraven break; 630292876Stheraven } 631292876Stheraven case '-': 632292876Stheraven { 633292876Stheraven consume('-'); 634292876Stheraven expression_ptr &&subexpr = parse_expression(); 635292876Stheraven if (!subexpr) 636292876Stheraven { 637292876Stheraven return nullptr; 638292876Stheraven } 639292876Stheraven lhs.reset(new unary_operator<'-', std::negate<valty>>(std::move(subexpr))); 640292876Stheraven break; 641292876Stheraven } 642292876Stheraven case '!': 643292876Stheraven { 644292876Stheraven consume('!'); 645292876Stheraven expression_ptr &&subexpr = parse_expression(); 646292876Stheraven if (!subexpr) 647292876Stheraven { 648292876Stheraven return nullptr; 649292876Stheraven } 650292876Stheraven lhs.reset(new unary_operator<'!', std::logical_not<valty>>(std::move(subexpr))); 651292876Stheraven break; 652292876Stheraven } 653292876Stheraven case '~': 654292876Stheraven { 655292876Stheraven consume('~'); 656292876Stheraven expression_ptr &&subexpr = parse_expression(); 657292876Stheraven if (!subexpr) 658292876Stheraven { 659292876Stheraven return nullptr; 660292876Stheraven } 661292876Stheraven lhs.reset(new unary_operator<'~', bit_not<valty>>(std::move(subexpr))); 662292876Stheraven break; 663292876Stheraven } 664292876Stheraven } 665292876Stheraven if (!lhs) 666292876Stheraven { 667292876Stheraven return nullptr; 668292876Stheraven } 669292876Stheraven return parse_binary_expression(std::move(lhs)); 670292876Stheraven} 671292876Stheraven 672245803Stheravenbool 673292876Stheraveninput_buffer::consume_integer_expression(unsigned long long &outInt) 674292876Stheraven{ 675292876Stheraven switch ((*this)[0]) 676292876Stheraven { 677292876Stheraven case '(': 678292876Stheraven { 679292876Stheraven expression_ptr e(parse_expression(true)); 680292876Stheraven if (!e) 681292876Stheraven { 682292876Stheraven return false; 683292876Stheraven } 684292876Stheraven outInt = (*e)(); 685292876Stheraven return true; 686292876Stheraven } 687292876Stheraven case '0'...'9': 688292876Stheraven return consume_integer(outInt); 689292876Stheraven default: 690292876Stheraven return false; 691292876Stheraven } 692292876Stheraven} 693292876Stheraven 694292876Stheravenbool 695245803Stheraveninput_buffer::consume_hex_byte(uint8_t &outByte) 696245803Stheraven{ 697245803Stheraven if (!ishexdigit((*this)[0]) && !ishexdigit((*this)[1])) 698245803Stheraven { 699245803Stheraven return false; 700245803Stheraven } 701245803Stheraven outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]); 702245803Stheraven cursor += 2; 703245803Stheraven return true; 704245803Stheraven} 705245803Stheraven 706245803Stheraveninput_buffer& 707245803Stheraveninput_buffer::next_token() 708245803Stheraven{ 709245803Stheraven int start; 710245803Stheraven do { 711245803Stheraven start = cursor; 712245803Stheraven skip_spaces(); 713245803Stheraven // Parse /* comments 714267318Srpaulo if ((*this)[0] == '/' && (*this)[1] == '*') 715245803Stheraven { 716245803Stheraven // eat the start of the comment 717245803Stheraven ++(*this); 718245803Stheraven ++(*this); 719245803Stheraven do { 720245803Stheraven // Find the ending * of */ 721245803Stheraven while ((**this != '\0') && (**this != '*')) 722245803Stheraven { 723245803Stheraven ++(*this); 724245803Stheraven } 725245803Stheraven // Eat the * 726245803Stheraven ++(*this); 727245803Stheraven } while ((**this != '\0') && (**this != '/')); 728245803Stheraven // Eat the / 729245803Stheraven ++(*this); 730245803Stheraven } 731289935Stheraven // Parse // comments 732289935Stheraven if (((*this)[0] == '/' && (*this)[1] == '/')) 733245803Stheraven { 734245803Stheraven // eat the start of the comment 735245803Stheraven ++(*this); 736245803Stheraven ++(*this); 737267318Srpaulo // Find the ending of the line 738245803Stheraven while (**this != '\n') 739245803Stheraven { 740245803Stheraven ++(*this); 741245803Stheraven } 742245803Stheraven // Eat the \n 743245803Stheraven ++(*this); 744245803Stheraven } 745245803Stheraven } while (start != cursor); 746245803Stheraven return *this; 747245803Stheraven} 748245803Stheraven 749245803Stheravenvoid 750245803Stheraveninput_buffer::parse_error(const char *msg) 751245803Stheraven{ 752245803Stheraven int line_count = 1; 753245803Stheraven int line_start = 0; 754245803Stheraven int line_end = cursor; 755245803Stheraven for (int i=cursor ; i>0 ; --i) 756245803Stheraven { 757245803Stheraven if (buffer[i] == '\n') 758245803Stheraven { 759245803Stheraven line_count++; 760245803Stheraven if (line_start == 0) 761245803Stheraven { 762245803Stheraven line_start = i+1; 763245803Stheraven } 764245803Stheraven } 765245803Stheraven } 766245803Stheraven for (int i=cursor+1 ; i<size ; ++i) 767245803Stheraven { 768245803Stheraven if (buffer[i] == '\n') 769245803Stheraven { 770245803Stheraven line_end = i; 771245803Stheraven break; 772245803Stheraven } 773245803Stheraven } 774245803Stheraven fprintf(stderr, "Error on line %d: %s\n", line_count, msg); 775245803Stheraven fwrite(&buffer[line_start], line_end-line_start, 1, stderr); 776245803Stheraven putc('\n', stderr); 777245803Stheraven for (int i=0 ; i<(cursor-line_start) ; ++i) 778245803Stheraven { 779254327Stheraven char c = (buffer[i+line_start] == '\t') ? '\t' : ' '; 780254327Stheraven putc(c, stderr); 781245803Stheraven } 782245803Stheraven putc('^', stderr); 783245803Stheraven putc('\n', stderr); 784245803Stheraven} 785292876Stheraven#ifndef NDEBUG 786245803Stheravenvoid 787245803Stheraveninput_buffer::dump() 788245803Stheraven{ 789245803Stheraven fprintf(stderr, "Current cursor: %d\n", cursor); 790245803Stheraven fwrite(&buffer[cursor], size-cursor, 1, stderr); 791245803Stheraven} 792292876Stheraven#endif 793245803Stheraven 794245803Stheravenmmap_input_buffer::mmap_input_buffer(int fd) : input_buffer(0, 0) 795245803Stheraven{ 796245803Stheraven struct stat sb; 797245803Stheraven if (fstat(fd, &sb)) 798245803Stheraven { 799245803Stheraven perror("Failed to stat file"); 800245803Stheraven } 801245803Stheraven size = sb.st_size; 802289935Stheraven buffer = (const char*)mmap(0, size, PROT_READ, MAP_PRIVATE | 803289935Stheraven MAP_PREFAULT_READ, fd, 0); 804289935Stheraven if (buffer == MAP_FAILED) 805245803Stheraven { 806245803Stheraven perror("Failed to mmap file"); 807289935Stheraven exit(EXIT_FAILURE); 808245803Stheraven } 809245803Stheraven} 810245803Stheraven 811245803Stheravenmmap_input_buffer::~mmap_input_buffer() 812245803Stheraven{ 813245803Stheraven if (buffer != 0) 814245803Stheraven { 815245803Stheraven munmap((void*)buffer, size); 816245803Stheraven } 817245803Stheraven} 818245803Stheraven 819245803Stheravenstream_input_buffer::stream_input_buffer() : input_buffer(0, 0) 820245803Stheraven{ 821245803Stheraven int c; 822245803Stheraven while ((c = fgetc(stdin)) != EOF) 823245803Stheraven { 824245803Stheraven b.push_back(c); 825245803Stheraven } 826245803Stheraven buffer = b.data(); 827245803Stheraven size = b.size(); 828245803Stheraven} 829245803Stheraven 830245803Stheraven} // namespace dtc 831245803Stheraven 832