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