xref: /freebsd/usr.bin/dtc/input_buffer.cc (revision 478d3005721019319c11a37980f8464ac22f529a)
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  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32 
33 #include "input_buffer.hh"
34 #include <ctype.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <functional>
42 #ifndef NDEBUG
43 #include <iostream>
44 #endif
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;
68 	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 {
90 	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 
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 
123 mmap_input_buffer::~mmap_input_buffer()
124 {
125 	if (buffer != 0)
126 	{
127 		munmap((void*)buffer, size);
128 	}
129 }
130 
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
149 input_buffer::skip_to(char c)
150 {
151 	while ((cursor < size) && (buffer[cursor] != c))
152 	{
153 		cursor++;
154 	}
155 }
156 
157 void
158 text_input_buffer::skip_to(char c)
159 {
160 	while (!finished() && (*(*this) != c))
161 	{
162 		++(*this);
163 	}
164 }
165 
166 void
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
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 = true;
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 
253 input_buffer
254 input_buffer::buffer_from_offset(int offset, int s)
255 {
256 	if (offset < 0)
257 	{
258 		return input_buffer();
259 	}
260 	if (s == 0)
261 	{
262 		s = size - offset;
263 	}
264 	if (offset > size)
265 	{
266 		return input_buffer();
267 	}
268 	if (s > (size-offset))
269 	{
270 		return input_buffer();
271 	}
272 	return input_buffer(&buffer[offset], s);
273 }
274 
275 bool
276 input_buffer::consume(const char *str)
277 {
278 	int len = strlen(str);
279 	if (len > size - cursor)
280 	{
281 		return false;
282 	}
283 	else
284 	{
285 		for (int i=0 ; i<len ; ++i)
286 		{
287 			if (str[i] != (*this)[i])
288 			{
289 				return false;
290 			}
291 		}
292 		cursor += len;
293 		return true;
294 	}
295 	return false;
296 }
297 
298 bool
299 input_buffer::consume_integer(unsigned long long &outInt)
300 {
301 	// The first character must be a digit.  Hex and octal strings
302 	// are prefixed by 0 and 0x, respectively.
303 	if (!isdigit((*this)[0]))
304 	{
305 		return false;
306 	}
307 	char *end= const_cast<char*>(&buffer[size]);
308 	outInt = strtoull(&buffer[cursor], &end, 0);
309 	if (end == &buffer[cursor])
310 	{
311 		return false;
312 	}
313 	cursor = end - buffer;
314 	return true;
315 }
316 
317 namespace {
318 
319 /**
320  * Convenience typedef for the type that we use for all values.
321  */
322 typedef unsigned long long valty;
323 
324 /**
325  * Expression tree currently being parsed.
326  */
327 struct expression
328 {
329 	typedef text_input_buffer::source_location source_location;
330 	/**
331 	 * The type that is returned when computing the result.  The boolean value
332 	 * indicates whether this is a valid expression.
333 	 *
334 	 * FIXME: Once we can use C++17, this should be `std::optional`.
335 	 */
336 	typedef std::pair<valty, bool> result;
337 	/**
338 	 * Evaluate this node, taking into account operator precedence.
339 	 */
340 	virtual result operator()() = 0;
341 	/**
342 	 * Returns the precedence of this node.  Lower values indicate higher
343 	 * precedence.
344 	 */
345 	virtual int precedence() = 0;
346 	/**
347 	 * Constructs an expression, storing the location where it was created.
348 	 */
349 	expression(source_location l) : loc(l) {}
350 	virtual ~expression() {}
351 #ifndef NDEBUG
352 	/**
353 	 * Dumps this expression to `std::cerr`, appending a newline if `nl` is
354 	 * `true`.
355 	 */
356 	void dump(bool nl=false)
357 	{
358 		void *ptr = this;
359 		if (ptr == nullptr)
360 		{
361 			std::cerr << "{nullptr}\n";
362 			return;
363 		}
364 		dump_impl();
365 		if (nl)
366 		{
367 			std::cerr << '\n';
368 		}
369 	}
370 	private:
371 	/**
372 	 * Method that sublcasses override to implement the behaviour of `dump()`.
373 	 */
374 	virtual void dump_impl() = 0;
375 #endif
376 	protected:
377 	source_location loc;
378 };
379 
380 /**
381  * Expression wrapping a single integer.  Leaf nodes in the expression tree.
382  */
383 class terminal_expr : public expression
384 {
385 	/**
386 	 * The value that this wraps.
387 	 */
388 	valty val;
389 	/**
390 	 * Evaluate.  Trivially returns the value that this class wraps.
391 	 */
392 	result operator()() override
393 	{
394 		return {val, true};
395 	}
396 	int precedence() override
397 	{
398 		return 0;
399 	}
400 	public:
401 	/**
402 	 * Constructor.
403 	 */
404 	terminal_expr(source_location l, valty v) : expression(l), val(v) {}
405 #ifndef NDEBUG
406 	void dump_impl() override { std::cerr << val; }
407 #endif
408 };
409 
410 /**
411  * Parenthetical expression.  Exists to make the contents opaque.
412  */
413 struct paren_expression : public expression
414 {
415 	/**
416 	 * The expression within the parentheses.
417 	 */
418 	expression_ptr subexpr;
419 	/**
420 	 * Constructor.  Takes the child expression as the only argument.
421 	 */
422 	paren_expression(source_location l, expression_ptr p) : expression(l),
423 	subexpr(std::move(p)) {}
424 	int precedence() override
425 	{
426 		return 0;
427 	}
428 	/**
429 	 * Evaluate - just forwards to the underlying expression.
430 	 */
431 	result operator()() override
432 	{
433 		return (*subexpr)();
434 	}
435 #ifndef NDEBUG
436 	void dump_impl() override
437 	{
438 		std::cerr << " (";
439 		subexpr->dump();
440 		std::cerr << ") ";
441 	}
442 #endif
443 };
444 
445 /**
446  * Template class for unary operators.  The `OpChar` template parameter is
447  * solely for debugging and makes it easy to print the expression.  The `Op`
448  * template parameter is a function object that implements the operator that
449  * this class provides.  Most of these are provided by the `<functional>`
450  * header.
451  */
452 template<char OpChar, class Op>
453 class unary_operator : public expression
454 {
455 	/**
456 	 * The subexpression for this unary operator.
457 	 */
458 	expression_ptr subexpr;
459 	result operator()() override
460 	{
461 		Op op;
462 		result s = (*subexpr)();
463 		if (!s.second)
464 		{
465 			return s;
466 		}
467 		return {op(s.first), true};
468 	}
469 	/**
470 	 * All unary operators have the same precedence.  They are all evaluated
471 	 * before binary expressions, but after parentheses.
472 	 */
473 	int precedence() override
474 	{
475 		return 3;
476 	}
477 	public:
478 	unary_operator(source_location l, expression_ptr p) :
479 		expression(l), subexpr(std::move(p)) {}
480 #ifndef NDEBUG
481 	void dump_impl() override
482 	{
483 		std::cerr << OpChar;
484 		subexpr->dump();
485 	}
486 #endif
487 };
488 
489 /**
490  * Abstract base class for binary operators.  Allows the tree to be modified
491  * without knowing what the operations actually are.
492  */
493 struct binary_operator_base : public expression
494 {
495 	using expression::expression;
496 	/**
497 	 * The left side of the expression.
498 	 */
499 	expression_ptr lhs;
500 	/**
501 	 * The right side of the expression.
502 	 */
503 	expression_ptr rhs;
504 	/**
505 	 * Insert a node somewhere down the path of left children, until it would
506 	 * be preempting something that should execute first.
507 	 */
508 	void insert_left(binary_operator_base *new_left)
509 	{
510 		if (lhs->precedence() < new_left->precedence())
511 		{
512 			new_left->rhs = std::move(lhs);
513 			lhs.reset(new_left);
514 		}
515 		else
516 		{
517 			static_cast<binary_operator_base*>(lhs.get())->insert_left(new_left);
518 		}
519 	}
520 };
521 
522 /**
523  * Template class for binary operators.  The precedence and the operation are
524  * provided as template parameters.
525  */
526 template<int Precedence, class Op>
527 struct binary_operator : public binary_operator_base
528 {
529 	result operator()() override
530 	{
531 		Op op;
532 		result l = (*lhs)();
533 		result r = (*rhs)();
534 		if (!(l.second && r.second))
535 		{
536 			return {0, false};
537 		}
538 		return {op(l.first, r.first), true};
539 	}
540 	int precedence() override
541 	{
542 		return Precedence;
543 	}
544 #ifdef NDEBUG
545 	/**
546 	 * Constructor.  Takes the name of the operator as an argument, for
547 	 * debugging.  Only stores it in debug mode.
548 	 */
549 	binary_operator(source_location l, const char *) :
550 		binary_operator_base(l) {}
551 #else
552 	const char *opName;
553 	binary_operator(source_location l, const char *o) :
554 		binary_operator_base(l), opName(o) {}
555 	void dump_impl() override
556 	{
557 		lhs->dump();
558 		std::cerr << opName;
559 		rhs->dump();
560 	}
561 #endif
562 };
563 
564 /**
565  * Ternary conditional operators (`cond ? true : false`) are a special case -
566  * there are no other ternary operators.
567  */
568 class ternary_conditional_operator : public expression
569 {
570 	/**
571 	 * The condition for the clause.
572 	 */
573 	expression_ptr cond;
574 	/**
575 	 * The expression that this evaluates to if the condition is true.
576 	 */
577 	expression_ptr lhs;
578 	/**
579 	 * The expression that this evaluates to if the condition is false.
580 	 */
581 	expression_ptr rhs;
582 	result operator()() override
583 	{
584 		result c = (*cond)();
585 		result l = (*lhs)();
586 		result r = (*rhs)();
587 		if (!(l.second && r.second && c.second))
588 		{
589 			return {0, false};
590 		}
591 		return c.first ? l : r;
592 	}
593 	int precedence() override
594 	{
595 		// The actual precedence of a ternary conditional operator is 15, but
596 		// its associativity is the opposite way around to the other operators,
597 		// so we fudge it slightly.
598 		return 3;
599 	}
600 #ifndef NDEBUG
601 	void dump_impl() override
602 	{
603 		cond->dump();
604 		std::cerr << " ? ";
605 		lhs->dump();
606 		std::cerr << " : ";
607 		rhs->dump();
608 	}
609 #endif
610 	public:
611 	ternary_conditional_operator(source_location sl,
612 	                             expression_ptr c,
613 	                             expression_ptr l,
614 	                             expression_ptr r) :
615 		expression(sl), cond(std::move(c)), lhs(std::move(l)),
616 		rhs(std::move(r)) {}
617 };
618 
619 template<typename T>
620 struct lshift
621 {
622 	constexpr T operator()(const T &lhs, const T &rhs) const
623 	{
624 		return lhs << rhs;
625 	}
626 };
627 template<typename T>
628 struct rshift
629 {
630 	constexpr T operator()(const T &lhs, const T &rhs) const
631 	{
632 		return lhs >> rhs;
633 	}
634 };
635 template<typename T>
636 struct unary_plus
637 {
638 	constexpr T operator()(const T &val) const
639 	{
640 		return +val;
641 	}
642 };
643 // TODO: Replace with std::bit_not once we can guarantee C++14 as a baseline.
644 template<typename T>
645 struct bit_not
646 {
647 	constexpr T operator()(const T &val) const
648 	{
649 		return ~val;
650 	}
651 };
652 
653 template<typename T>
654 struct divmod : public binary_operator<5, T>
655 {
656 	using binary_operator<5, T>::binary_operator;
657 	using binary_operator_base::result;
658 	result operator()() override
659 	{
660 		result r = (*binary_operator_base::rhs)();
661 		if (r.second && (r.first == 0))
662 		{
663 			expression::loc.report_error("Division by zero");
664 			return {0, false};
665 		}
666 		return binary_operator<5, T>::operator()();
667 	}
668 };
669 
670 } // anonymous namespace
671 
672 
673 expression_ptr text_input_buffer::parse_binary_expression(expression_ptr lhs)
674 {
675 	next_token();
676 	binary_operator_base *expr = nullptr;
677 	char op = *(*this);
678 	source_location l = location();
679 	switch (op)
680 	{
681 		default:
682 			return lhs;
683 		case '+':
684 			expr = new binary_operator<6, std::plus<valty>>(l, "+");
685 			break;
686 		case '-':
687 			expr = new binary_operator<6, std::minus<valty>>(l, "-");
688 			break;
689 		case '%':
690 			expr = new divmod<std::modulus<valty>>(l, "/");
691 			break;
692 		case '*':
693 			expr = new binary_operator<5, std::multiplies<valty>>(l, "*");
694 			break;
695 		case '/':
696 			expr = new divmod<std::divides<valty>>(l, "/");
697 			break;
698 		case '<':
699 			switch (peek())
700 			{
701 				default:
702 					parse_error("Invalid operator");
703 					return nullptr;
704 				case ' ':
705 				case '(':
706 				case '0'...'9':
707 					expr = new binary_operator<8, std::less<valty>>(l, "<");
708 					break;
709 				case '=':
710 					++(*this);
711 					expr = new binary_operator<8, std::less_equal<valty>>(l, "<=");
712 					break;
713 				case '<':
714 					++(*this);
715 					expr = new binary_operator<7, lshift<valty>>(l, "<<");
716 					break;
717 			}
718 			break;
719 		case '>':
720 			switch (peek())
721 			{
722 				default:
723 					parse_error("Invalid operator");
724 					return nullptr;
725 				case '(':
726 				case ' ':
727 				case '0'...'9':
728 					expr = new binary_operator<8, std::greater<valty>>(l, ">");
729 					break;
730 				case '=':
731 					++(*this);
732 					expr = new binary_operator<8, std::greater_equal<valty>>(l, ">=");
733 					break;
734 				case '>':
735 					++(*this);
736 					expr = new binary_operator<7, rshift<valty>>(l, ">>");
737 					break;
738 					return lhs;
739 			}
740 			break;
741 		case '=':
742 			if (peek() != '=')
743 			{
744 				parse_error("Invalid operator");
745 				return nullptr;
746 			}
747 			expr = new binary_operator<9, std::equal_to<valty>>(l, "==");
748 			break;
749 		case '!':
750 			if (peek() != '=')
751 			{
752 				parse_error("Invalid operator");
753 				return nullptr;
754 			}
755 			cursor++;
756 			expr = new binary_operator<9, std::not_equal_to<valty>>(l, "!=");
757 			break;
758 		case '&':
759 			if (peek() == '&')
760 			{
761 				expr = new binary_operator<13, std::logical_and<valty>>(l, "&&");
762 			}
763 			else
764 			{
765 				expr = new binary_operator<10, std::bit_and<valty>>(l, "&");
766 			}
767 			break;
768 		case '|':
769 			if (peek() == '|')
770 			{
771 				expr = new binary_operator<12, std::logical_or<valty>>(l, "||");
772 			}
773 			else
774 			{
775 				expr = new binary_operator<14, std::bit_or<valty>>(l, "|");
776 			}
777 			break;
778 		case '?':
779 		{
780 			consume('?');
781 			expression_ptr true_case = parse_expression();
782 			next_token();
783 			if (!true_case || !consume(':'))
784 			{
785 				parse_error("Expected : in ternary conditional operator");
786 				return nullptr;
787 			}
788 			expression_ptr false_case = parse_expression();
789 			if (!false_case)
790 			{
791 				parse_error("Expected false condition for ternary operator");
792 				return nullptr;
793 			}
794 			return expression_ptr(new ternary_conditional_operator(l, std::move(lhs),
795 						std::move(true_case), std::move(false_case)));
796 		}
797 	}
798 	++(*this);
799 	next_token();
800 	expression_ptr e(expr);
801 	expression_ptr rhs(parse_expression());
802 	if (!rhs)
803 	{
804 		return nullptr;
805 	}
806 	expr->lhs = std::move(lhs);
807 	if (rhs->precedence() < expr->precedence())
808 	{
809 		expr->rhs = std::move(rhs);
810 	}
811 	else
812 	{
813 		// If we're a normal left-to-right expression, then we need to insert
814 		// this as the far-left child node of the rhs expression
815 		binary_operator_base *rhs_op =
816 			static_cast<binary_operator_base*>(rhs.get());
817 		rhs_op->insert_left(expr);
818 		e.release();
819 		return rhs;
820 	}
821 	return e;
822 }
823 
824 expression_ptr text_input_buffer::parse_expression(bool stopAtParen)
825 {
826 	next_token();
827 	unsigned long long leftVal;
828 	expression_ptr lhs;
829 	source_location l = location();
830 	switch (*(*this))
831 	{
832 		case '0'...'9':
833 			if (!consume_integer(leftVal))
834 			{
835 				return nullptr;
836 			}
837 			lhs.reset(new terminal_expr(l, leftVal));
838 			break;
839 		case '(':
840 		{
841 			consume('(');
842 			expression_ptr &&subexpr = parse_expression();
843 			if (!subexpr)
844 			{
845 				return nullptr;
846 			}
847 			lhs.reset(new paren_expression(l, std::move(subexpr)));
848 			if (!consume(')'))
849 			{
850 				return nullptr;
851 			}
852 			if (stopAtParen)
853 			{
854 				return lhs;
855 			}
856 			break;
857 		}
858 		case '+':
859 		{
860 			consume('+');
861 			expression_ptr &&subexpr = parse_expression();
862 			if (!subexpr)
863 			{
864 				return nullptr;
865 			}
866 			lhs.reset(new unary_operator<'+', unary_plus<valty>>(l, std::move(subexpr)));
867 			break;
868 		}
869 		case '-':
870 		{
871 			consume('-');
872 			expression_ptr &&subexpr = parse_expression();
873 			if (!subexpr)
874 			{
875 				return nullptr;
876 			}
877 			lhs.reset(new unary_operator<'-', std::negate<valty>>(l, std::move(subexpr)));
878 			break;
879 		}
880 		case '!':
881 		{
882 			consume('!');
883 			expression_ptr &&subexpr = parse_expression();
884 			if (!subexpr)
885 			{
886 				return nullptr;
887 			}
888 			lhs.reset(new unary_operator<'!', std::logical_not<valty>>(l, std::move(subexpr)));
889 			break;
890 		}
891 		case '~':
892 		{
893 			consume('~');
894 			expression_ptr &&subexpr = parse_expression();
895 			if (!subexpr)
896 			{
897 				return nullptr;
898 			}
899 			lhs.reset(new unary_operator<'~', bit_not<valty>>(l, std::move(subexpr)));
900 			break;
901 		}
902 	}
903 	if (!lhs)
904 	{
905 		return nullptr;
906 	}
907 	return parse_binary_expression(std::move(lhs));
908 }
909 
910 bool
911 text_input_buffer::consume_integer_expression(unsigned long long &outInt)
912 {
913 	switch (*(*this))
914 	{
915 		case '(':
916 		{
917 			expression_ptr e(parse_expression(true));
918 			if (!e)
919 			{
920 				return false;
921 			}
922 			auto r = (*e)();
923 			if (r.second)
924 			{
925 				outInt = r.first;
926 				return true;
927 			}
928 			return false;
929 		}
930 		case '0'...'9':
931 			return consume_integer(outInt);
932 		default:
933 			return false;
934 	}
935 }
936 
937 bool
938 input_buffer::consume_hex_byte(uint8_t &outByte)
939 {
940 	if (!ishexdigit((*this)[0]) && !ishexdigit((*this)[1]))
941 	{
942 		return false;
943 	}
944 	outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]);
945 	cursor += 2;
946 	return true;
947 }
948 
949 text_input_buffer&
950 text_input_buffer::next_token()
951 {
952 	auto &self = *this;
953 	int start;
954 	do {
955 		start = cursor;
956 		skip_spaces();
957 		if (finished())
958 		{
959 			return self;
960 		}
961 		// Parse /* comments
962 		if (*self == '/' && peek() == '*')
963 		{
964 			// eat the start of the comment
965 			++self;
966 			++self;
967 			do {
968 				// Find the ending * of */
969 				while ((*self != '\0') && (*self != '*') && !finished())
970 				{
971 					++self;
972 				}
973 				// Eat the *
974 				++self;
975 			} while ((*self != '\0') && (*self != '/') && !finished());
976 			// Eat the /
977 			++self;
978 		}
979 		// Parse // comments
980 		if ((*self == '/' && peek() == '/'))
981 		{
982 			// eat the start of the comment
983 			++self;
984 			++self;
985 			// Find the ending of the line
986 			while (*self != '\n' && !finished())
987 			{
988 				++self;
989 			}
990 			// Eat the \n
991 			++self;
992 		}
993 	} while (start != cursor);
994 	return self;
995 }
996 
997 void
998 text_input_buffer::parse_error(const char *msg)
999 {
1000 	if (input_stack.empty())
1001 	{
1002 		fprintf(stderr, "Error: %s\n", msg);
1003 		return;
1004 	}
1005 	input_buffer &b = *input_stack.top();
1006 	parse_error(msg, b, b.cursor);
1007 }
1008 void
1009 text_input_buffer::parse_error(const char *msg,
1010                                input_buffer &b,
1011                                int loc)
1012 {
1013 	int line_count = 1;
1014 	int line_start = 0;
1015 	int line_end = loc;
1016 	if (loc < 0 || loc > b.size)
1017 	{
1018 		return;
1019 	}
1020 	for (int i=loc ; i>0 ; --i)
1021 	{
1022 		if (b.buffer[i] == '\n')
1023 		{
1024 			line_count++;
1025 			if (line_start == 0)
1026 			{
1027 				line_start = i+1;
1028 			}
1029 		}
1030 	}
1031 	for (int i=loc+1 ; i<b.size ; ++i)
1032 	{
1033 		if (b.buffer[i] == '\n')
1034 		{
1035 			line_end = i;
1036 			break;
1037 		}
1038 	}
1039 	fprintf(stderr, "Error at %s:%d:%d: %s\n", b.filename().c_str(), line_count, loc - line_start, msg);
1040 	fwrite(&b.buffer[line_start], line_end-line_start, 1, stderr);
1041 	putc('\n', stderr);
1042 	for (int i=0 ; i<(loc-line_start) ; ++i)
1043 	{
1044 		char c = (b.buffer[i+line_start] == '\t') ? '\t' : ' ';
1045 		putc(c, stderr);
1046 	}
1047 	putc('^', stderr);
1048 	putc('\n', stderr);
1049 }
1050 #ifndef NDEBUG
1051 void
1052 input_buffer::dump()
1053 {
1054 	fprintf(stderr, "Current cursor: %d\n", cursor);
1055 	fwrite(&buffer[cursor], size-cursor, 1, stderr);
1056 }
1057 #endif
1058 
1059 
1060 namespace
1061 {
1062 /**
1063  * The source files are ASCII, so we provide a non-locale-aware version of
1064  * isalpha.  This is a class so that it can be used with a template function
1065  * for parsing strings.
1066  */
1067 struct is_alpha
1068 {
1069 	static inline bool check(const char c)
1070 	{
1071 		return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') &&
1072 			(c <= 'Z'));
1073 	}
1074 };
1075 /**
1076  * Check whether a character is in the set allowed for node names.  This is a
1077  * class so that it can be used with a template function for parsing strings.
1078  */
1079 struct is_node_name_character
1080 {
1081 	static inline bool check(const char c)
1082 	{
1083 		switch(c)
1084 		{
1085 			default:
1086 				return false;
1087 			case 'a'...'z': case 'A'...'Z': case '0'...'9':
1088 			case ',': case '.': case '+': case '-':
1089 			case '_':
1090 				return true;
1091 		}
1092 	}
1093 };
1094 /**
1095  * Check whether a character is in the set allowed for property names.  This is
1096  * a class so that it can be used with a template function for parsing strings.
1097  */
1098 struct is_property_name_character
1099 {
1100 	static inline bool check(const char c)
1101 	{
1102 		switch(c)
1103 		{
1104 			default:
1105 				return false;
1106 			case 'a'...'z': case 'A'...'Z': case '0'...'9':
1107 			case ',': case '.': case '+': case '-':
1108 			case '_': case '#':
1109 				return true;
1110 		}
1111 	}
1112 };
1113 
1114 template<class T>
1115 string parse(text_input_buffer &s)
1116 {
1117 	std::vector<char> bytes;
1118 	for (char c=*s ; T::check(c) ; c=*(++s))
1119 	{
1120 		bytes.push_back(c);
1121 	}
1122 	return string(bytes.begin(), bytes.end());
1123 }
1124 
1125 }
1126 
1127 string
1128 text_input_buffer::parse_node_name()
1129 {
1130 	return parse<is_node_name_character>(*this);
1131 }
1132 
1133 string
1134 text_input_buffer::parse_property_name()
1135 {
1136 	return parse<is_property_name_character>(*this);
1137 }
1138 
1139 string
1140 text_input_buffer::parse_node_or_property_name(bool &is_property)
1141 {
1142 	if (is_property)
1143 	{
1144 		return parse_property_name();
1145 	}
1146 	std::vector<char> bytes;
1147 	for (char c=*(*this) ; is_node_name_character::check(c) ; c=*(++(*this)))
1148 	{
1149 		bytes.push_back(c);
1150 	}
1151 	for (char c=*(*this) ; is_property_name_character::check(c) ; c=*(++(*this)))
1152 	{
1153 		bytes.push_back(c);
1154 		is_property = true;
1155 	}
1156 	return string(bytes.begin(), bytes.end());
1157 }
1158 
1159 string
1160 input_buffer::parse_to(char stop)
1161 {
1162 	std::vector<char> bytes;
1163 	for (char c=*(*this) ; c != stop ; c=*(++(*this)))
1164 	{
1165 		bytes.push_back(c);
1166 	}
1167 	return string(bytes.begin(), bytes.end());
1168 }
1169 
1170 string
1171 text_input_buffer::parse_to(char stop)
1172 {
1173 	std::vector<char> bytes;
1174 	for (char c=*(*this) ; c != stop ; c=*(++(*this)))
1175 	{
1176 		if (finished())
1177 		{
1178 			break;
1179 		}
1180 		bytes.push_back(c);
1181 	}
1182 	return string(bytes.begin(), bytes.end());
1183 }
1184 
1185 char
1186 text_input_buffer::peek()
1187 {
1188 	return (*input_stack.top())[1];
1189 }
1190 
1191 std::unique_ptr<input_buffer>
1192 input_buffer::buffer_for_file(const string &path, bool warn)
1193 {
1194 	if (path == "-")
1195 	{
1196 		std::unique_ptr<input_buffer> b(new stream_input_buffer());
1197 		return b;
1198 	}
1199 	int source = open(path.c_str(), O_RDONLY);
1200 	if (source == -1)
1201 	{
1202 		if (warn)
1203 		{
1204 			fprintf(stderr, "Unable to open file '%s'.  %s\n", path.c_str(), strerror(errno));
1205 		}
1206 		return 0;
1207 	}
1208 	struct stat st;
1209 	if (fstat(source, &st) == 0 && S_ISDIR(st.st_mode))
1210 	{
1211 		if (warn)
1212 		{
1213 			fprintf(stderr, "File %s is a directory\n", path.c_str());
1214 		}
1215 		close(source);
1216 		return 0;
1217 	}
1218 	std::unique_ptr<input_buffer> b(new mmap_input_buffer(source, string(path)));
1219 	close(source);
1220 	return b;
1221 }
1222 
1223 } // namespace dtc
1224 
1225