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