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_char_literal(unsigned long long & outInt)341 input_buffer::consume_char_literal(unsigned long long &outInt)
342 {
343 outInt = (unsigned char)((*this)[0]);
344 cursor++;
345
346 if(outInt != '\\')
347 {
348 return true;
349 }
350 else if(cursor >= size)
351 {
352 return false;
353 }
354
355 outInt = (unsigned char)((*this)[0]);
356 cursor++;
357
358 switch (outInt) {
359 default:
360 return false;
361 case 'n':
362 outInt = (unsigned char)'\n';
363 break;
364 case 'r':
365 outInt = (unsigned char)'\r';
366 break;
367 case 't':
368 outInt = (unsigned char)'\t';
369 break;
370 case '0':
371 outInt = 0;
372 break;
373 case '\'':
374 case '\\':
375 break;
376 }
377
378 return true;
379 }
380
381 bool
consume_integer(unsigned long long & outInt)382 input_buffer::consume_integer(unsigned long long &outInt)
383 {
384 // The first character must be a digit. Hex and octal strings
385 // are prefixed by 0 and 0x, respectively.
386 if (!isdigit((*this)[0]))
387 {
388 return false;
389 }
390 char *end= const_cast<char*>(&buffer[size]);
391 errno = 0;
392 outInt = strtoull(&buffer[cursor], &end, 0);
393 if (end == &buffer[cursor] ||
394 (outInt == std::numeric_limits<unsigned long long>::max() &&
395 errno == ERANGE))
396 {
397 return false;
398 }
399 cursor = end - buffer;
400 return true;
401 }
402
403 namespace {
404
405 /**
406 * Convenience typedef for the type that we use for all values.
407 */
408 typedef unsigned long long valty;
409
410 /**
411 * Expression tree currently being parsed.
412 */
413 struct expression
414 {
415 typedef text_input_buffer::source_location source_location;
416 /**
417 * The type that is returned when computing the result. The boolean value
418 * indicates whether this is a valid expression.
419 *
420 * FIXME: Once we can use C++17, this should be `std::optional`.
421 */
422 typedef std::pair<valty, bool> result;
423 /**
424 * Evaluate this node, taking into account operator precedence.
425 */
426 virtual result operator()() = 0;
427 /**
428 * Returns the precedence of this node. Lower values indicate higher
429 * precedence.
430 */
431 virtual int precedence() = 0;
432 /**
433 * Constructs an expression, storing the location where it was created.
434 */
expressiondtc::__anon3998a5d80211::expression435 expression(source_location l) : loc(l) {}
~expressiondtc::__anon3998a5d80211::expression436 virtual ~expression() {}
437 #ifndef NDEBUG
438 /**
439 * Dumps this expression to `std::cerr`, appending a newline if `nl` is
440 * `true`.
441 */
dumpdtc::__anon3998a5d80211::expression442 void dump(bool nl=false)
443 {
444 void *ptr = this;
445 if (ptr == nullptr)
446 {
447 std::cerr << "{nullptr}\n";
448 return;
449 }
450 dump_impl();
451 if (nl)
452 {
453 std::cerr << '\n';
454 }
455 }
456 private:
457 /**
458 * Method that sublcasses override to implement the behaviour of `dump()`.
459 */
460 virtual void dump_impl() = 0;
461 #endif
462 protected:
463 source_location loc;
464 };
465
466 /**
467 * Expression wrapping a single integer. Leaf nodes in the expression tree.
468 */
469 class terminal_expr : public expression
470 {
471 /**
472 * The value that this wraps.
473 */
474 valty val;
475 /**
476 * Evaluate. Trivially returns the value that this class wraps.
477 */
operator ()()478 result operator()() override
479 {
480 return {val, true};
481 }
precedence()482 int precedence() override
483 {
484 return 0;
485 }
486 public:
487 /**
488 * Constructor.
489 */
terminal_expr(source_location l,valty v)490 terminal_expr(source_location l, valty v) : expression(l), val(v) {}
491 #ifndef NDEBUG
dump_impl()492 void dump_impl() override { std::cerr << val; }
493 #endif
494 };
495
496 /**
497 * Parenthetical expression. Exists to make the contents opaque.
498 */
499 struct paren_expression : public expression
500 {
501 /**
502 * The expression within the parentheses.
503 */
504 expression_ptr subexpr;
505 /**
506 * Constructor. Takes the child expression as the only argument.
507 */
paren_expressiondtc::__anon3998a5d80211::paren_expression508 paren_expression(source_location l, expression_ptr p) : expression(l),
509 subexpr(std::move(p)) {}
precedencedtc::__anon3998a5d80211::paren_expression510 int precedence() override
511 {
512 return 0;
513 }
514 /**
515 * Evaluate - just forwards to the underlying expression.
516 */
operator ()dtc::__anon3998a5d80211::paren_expression517 result operator()() override
518 {
519 return (*subexpr)();
520 }
521 #ifndef NDEBUG
dump_impldtc::__anon3998a5d80211::paren_expression522 void dump_impl() override
523 {
524 std::cerr << " (";
525 subexpr->dump();
526 std::cerr << ") ";
527 }
528 #endif
529 };
530
531 /**
532 * Template class for unary operators. The `OpChar` template parameter is
533 * solely for debugging and makes it easy to print the expression. The `Op`
534 * template parameter is a function object that implements the operator that
535 * this class provides. Most of these are provided by the `<functional>`
536 * header.
537 */
538 template<char OpChar, class Op>
539 class unary_operator : public expression
540 {
541 /**
542 * The subexpression for this unary operator.
543 */
544 expression_ptr subexpr;
operator ()()545 result operator()() override
546 {
547 Op op;
548 result s = (*subexpr)();
549 if (!s.second)
550 {
551 return s;
552 }
553 return {op(s.first), true};
554 }
555 /**
556 * All unary operators have the same precedence. They are all evaluated
557 * before binary expressions, but after parentheses.
558 */
precedence()559 int precedence() override
560 {
561 return 3;
562 }
563 public:
unary_operator(source_location l,expression_ptr p)564 unary_operator(source_location l, expression_ptr p) :
565 expression(l), subexpr(std::move(p)) {}
566 #ifndef NDEBUG
dump_impl()567 void dump_impl() override
568 {
569 std::cerr << OpChar;
570 subexpr->dump();
571 }
572 #endif
573 };
574
575 /**
576 * Abstract base class for binary operators. Allows the tree to be modified
577 * without knowing what the operations actually are.
578 */
579 struct binary_operator_base : public expression
580 {
581 using expression::expression;
582 /**
583 * The left side of the expression.
584 */
585 expression_ptr lhs;
586 /**
587 * The right side of the expression.
588 */
589 expression_ptr rhs;
590 /**
591 * Insert a node somewhere down the path of left children, until it would
592 * be preempting something that should execute first.
593 */
insert_leftdtc::__anon3998a5d80211::binary_operator_base594 void insert_left(binary_operator_base *new_left)
595 {
596 if (lhs->precedence() < new_left->precedence())
597 {
598 new_left->rhs = std::move(lhs);
599 lhs.reset(new_left);
600 }
601 else
602 {
603 static_cast<binary_operator_base*>(lhs.get())->insert_left(new_left);
604 }
605 }
606 };
607
608 /**
609 * Template class for binary operators. The precedence and the operation are
610 * provided as template parameters.
611 */
612 template<int Precedence, class Op>
613 struct binary_operator : public binary_operator_base
614 {
operator ()dtc::__anon3998a5d80211::binary_operator615 result operator()() override
616 {
617 Op op;
618 result l = (*lhs)();
619 result r = (*rhs)();
620 if (!(l.second && r.second))
621 {
622 return {0, false};
623 }
624 return {op(l.first, r.first), true};
625 }
precedencedtc::__anon3998a5d80211::binary_operator626 int precedence() override
627 {
628 return Precedence;
629 }
630 #ifdef NDEBUG
631 /**
632 * Constructor. Takes the name of the operator as an argument, for
633 * debugging. Only stores it in debug mode.
634 */
binary_operatordtc::__anon3998a5d80211::binary_operator635 binary_operator(source_location l, const char *) :
636 binary_operator_base(l) {}
637 #else
638 const char *opName;
binary_operatordtc::__anon3998a5d80211::binary_operator639 binary_operator(source_location l, const char *o) :
640 binary_operator_base(l), opName(o) {}
dump_impldtc::__anon3998a5d80211::binary_operator641 void dump_impl() override
642 {
643 lhs->dump();
644 std::cerr << opName;
645 rhs->dump();
646 }
647 #endif
648 };
649
650 /**
651 * Ternary conditional operators (`cond ? true : false`) are a special case -
652 * there are no other ternary operators.
653 */
654 class ternary_conditional_operator : public expression
655 {
656 /**
657 * The condition for the clause.
658 */
659 expression_ptr cond;
660 /**
661 * The expression that this evaluates to if the condition is true.
662 */
663 expression_ptr lhs;
664 /**
665 * The expression that this evaluates to if the condition is false.
666 */
667 expression_ptr rhs;
operator ()()668 result operator()() override
669 {
670 result c = (*cond)();
671 result l = (*lhs)();
672 result r = (*rhs)();
673 if (!(l.second && r.second && c.second))
674 {
675 return {0, false};
676 }
677 return c.first ? l : r;
678 }
precedence()679 int precedence() override
680 {
681 // The actual precedence of a ternary conditional operator is 15, but
682 // its associativity is the opposite way around to the other operators,
683 // so we fudge it slightly.
684 return 3;
685 }
686 #ifndef NDEBUG
dump_impl()687 void dump_impl() override
688 {
689 cond->dump();
690 std::cerr << " ? ";
691 lhs->dump();
692 std::cerr << " : ";
693 rhs->dump();
694 }
695 #endif
696 public:
ternary_conditional_operator(source_location sl,expression_ptr c,expression_ptr l,expression_ptr r)697 ternary_conditional_operator(source_location sl,
698 expression_ptr c,
699 expression_ptr l,
700 expression_ptr r) :
701 expression(sl), cond(std::move(c)), lhs(std::move(l)),
702 rhs(std::move(r)) {}
703 };
704
705 template<typename T>
706 struct lshift
707 {
operator ()dtc::__anon3998a5d80211::lshift708 constexpr T operator()(const T &lhs, const T &rhs) const
709 {
710 return lhs << rhs;
711 }
712 };
713 template<typename T>
714 struct rshift
715 {
operator ()dtc::__anon3998a5d80211::rshift716 constexpr T operator()(const T &lhs, const T &rhs) const
717 {
718 return lhs >> rhs;
719 }
720 };
721 template<typename T>
722 struct unary_plus
723 {
operator ()dtc::__anon3998a5d80211::unary_plus724 constexpr T operator()(const T &val) const
725 {
726 return +val;
727 }
728 };
729 // TODO: Replace with std::bit_not once we can guarantee C++14 as a baseline.
730 template<typename T>
731 struct bit_not
732 {
operator ()dtc::__anon3998a5d80211::bit_not733 constexpr T operator()(const T &val) const
734 {
735 return ~val;
736 }
737 };
738
739 template<typename T>
740 struct divmod : public binary_operator<5, T>
741 {
742 using binary_operator<5, T>::binary_operator;
743 using typename binary_operator_base::result;
operator ()dtc::__anon3998a5d80211::divmod744 result operator()() override
745 {
746 result r = (*binary_operator_base::rhs)();
747 if (r.second && (r.first == 0))
748 {
749 expression::loc.report_error("Division by zero");
750 return {0, false};
751 }
752 return binary_operator<5, T>::operator()();
753 }
754 };
755
756 } // anonymous namespace
757
758
parse_binary_expression(expression_ptr lhs)759 expression_ptr text_input_buffer::parse_binary_expression(expression_ptr lhs)
760 {
761 next_token();
762 binary_operator_base *expr = nullptr;
763 char op = *(*this);
764 source_location l = location();
765 switch (op)
766 {
767 default:
768 return lhs;
769 case '+':
770 expr = new binary_operator<6, std::plus<valty>>(l, "+");
771 break;
772 case '-':
773 expr = new binary_operator<6, std::minus<valty>>(l, "-");
774 break;
775 case '%':
776 expr = new divmod<std::modulus<valty>>(l, "/");
777 break;
778 case '*':
779 expr = new binary_operator<5, std::multiplies<valty>>(l, "*");
780 break;
781 case '/':
782 expr = new divmod<std::divides<valty>>(l, "/");
783 break;
784 case '<':
785 switch (peek())
786 {
787 default:
788 parse_error("Invalid operator");
789 return nullptr;
790 case ' ':
791 case '(':
792 case '0'...'9':
793 expr = new binary_operator<8, std::less<valty>>(l, "<");
794 break;
795 case '=':
796 ++(*this);
797 expr = new binary_operator<8, std::less_equal<valty>>(l, "<=");
798 break;
799 case '<':
800 ++(*this);
801 expr = new binary_operator<7, lshift<valty>>(l, "<<");
802 break;
803 }
804 break;
805 case '>':
806 switch (peek())
807 {
808 default:
809 parse_error("Invalid operator");
810 return nullptr;
811 case '(':
812 case ' ':
813 case '0'...'9':
814 expr = new binary_operator<8, std::greater<valty>>(l, ">");
815 break;
816 case '=':
817 ++(*this);
818 expr = new binary_operator<8, std::greater_equal<valty>>(l, ">=");
819 break;
820 case '>':
821 ++(*this);
822 expr = new binary_operator<7, rshift<valty>>(l, ">>");
823 break;
824 return lhs;
825 }
826 break;
827 case '=':
828 if (peek() != '=')
829 {
830 parse_error("Invalid operator");
831 return nullptr;
832 }
833 expr = new binary_operator<9, std::equal_to<valty>>(l, "==");
834 break;
835 case '!':
836 if (peek() != '=')
837 {
838 parse_error("Invalid operator");
839 return nullptr;
840 }
841 cursor++;
842 expr = new binary_operator<9, std::not_equal_to<valty>>(l, "!=");
843 break;
844 case '&':
845 if (peek() == '&')
846 {
847 expr = new binary_operator<13, std::logical_and<valty>>(l, "&&");
848 }
849 else
850 {
851 expr = new binary_operator<10, std::bit_and<valty>>(l, "&");
852 }
853 break;
854 case '|':
855 if (peek() == '|')
856 {
857 expr = new binary_operator<12, std::logical_or<valty>>(l, "||");
858 }
859 else
860 {
861 expr = new binary_operator<14, std::bit_or<valty>>(l, "|");
862 }
863 break;
864 case '?':
865 {
866 consume('?');
867 expression_ptr true_case = parse_expression();
868 next_token();
869 if (!true_case || !consume(':'))
870 {
871 parse_error("Expected : in ternary conditional operator");
872 return nullptr;
873 }
874 expression_ptr false_case = parse_expression();
875 if (!false_case)
876 {
877 parse_error("Expected false condition for ternary operator");
878 return nullptr;
879 }
880 return expression_ptr(new ternary_conditional_operator(l, std::move(lhs),
881 std::move(true_case), std::move(false_case)));
882 }
883 }
884 ++(*this);
885 next_token();
886 expression_ptr e(expr);
887 expression_ptr rhs(parse_expression());
888 if (!rhs)
889 {
890 return nullptr;
891 }
892 expr->lhs = std::move(lhs);
893 if (rhs->precedence() < expr->precedence())
894 {
895 expr->rhs = std::move(rhs);
896 }
897 else
898 {
899 // If we're a normal left-to-right expression, then we need to insert
900 // this as the far-left child node of the rhs expression
901 binary_operator_base *rhs_op =
902 static_cast<binary_operator_base*>(rhs.get());
903 rhs_op->insert_left(expr);
904 e.release();
905 return rhs;
906 }
907 return e;
908 }
909
parse_expression(bool stopAtParen)910 expression_ptr text_input_buffer::parse_expression(bool stopAtParen)
911 {
912 next_token();
913 unsigned long long leftVal;
914 expression_ptr lhs;
915 source_location l = location();
916 switch (*(*this))
917 {
918 case '\'':
919 consume('\'');
920 if(!consume_char_literal(leftVal))
921 {
922 return nullptr;
923 }
924 if (!consume('\''))
925 {
926 return nullptr;
927 }
928 lhs.reset(new terminal_expr(l, leftVal));
929 break;
930 case '0'...'9':
931 if (!consume_integer(leftVal))
932 {
933 return nullptr;
934 }
935 lhs.reset(new terminal_expr(l, leftVal));
936 break;
937 case '(':
938 {
939 consume('(');
940 expression_ptr &&subexpr = parse_expression();
941 if (!subexpr)
942 {
943 return nullptr;
944 }
945 lhs.reset(new paren_expression(l, std::move(subexpr)));
946 if (!consume(')'))
947 {
948 return nullptr;
949 }
950 if (stopAtParen)
951 {
952 return lhs;
953 }
954 break;
955 }
956 case '+':
957 {
958 consume('+');
959 expression_ptr &&subexpr = parse_expression();
960 if (!subexpr)
961 {
962 return nullptr;
963 }
964 lhs.reset(new unary_operator<'+', unary_plus<valty>>(l, std::move(subexpr)));
965 break;
966 }
967 case '-':
968 {
969 consume('-');
970 expression_ptr &&subexpr = parse_expression();
971 if (!subexpr)
972 {
973 return nullptr;
974 }
975 lhs.reset(new unary_operator<'-', std::negate<valty>>(l, std::move(subexpr)));
976 break;
977 }
978 case '!':
979 {
980 consume('!');
981 expression_ptr &&subexpr = parse_expression();
982 if (!subexpr)
983 {
984 return nullptr;
985 }
986 lhs.reset(new unary_operator<'!', std::logical_not<valty>>(l, std::move(subexpr)));
987 break;
988 }
989 case '~':
990 {
991 consume('~');
992 expression_ptr &&subexpr = parse_expression();
993 if (!subexpr)
994 {
995 return nullptr;
996 }
997 lhs.reset(new unary_operator<'~', bit_not<valty>>(l, std::move(subexpr)));
998 break;
999 }
1000 }
1001 if (!lhs)
1002 {
1003 return nullptr;
1004 }
1005 return parse_binary_expression(std::move(lhs));
1006 }
1007
1008 bool
consume_integer_expression(unsigned long long & outInt)1009 text_input_buffer::consume_integer_expression(unsigned long long &outInt)
1010 {
1011 switch (*(*this))
1012 {
1013 case '(':
1014 {
1015 expression_ptr e(parse_expression(true));
1016 if (!e)
1017 {
1018 return false;
1019 }
1020 auto r = (*e)();
1021 if (r.second)
1022 {
1023 outInt = r.first;
1024 return true;
1025 }
1026 return false;
1027 }
1028 case '0'...'9':
1029 return consume_integer(outInt);
1030 default:
1031 return false;
1032 }
1033 }
1034
1035 bool
consume_hex_byte(uint8_t & outByte)1036 input_buffer::consume_hex_byte(uint8_t &outByte)
1037 {
1038 if (!ishexdigit((*this)[0]) && !ishexdigit((*this)[1]))
1039 {
1040 return false;
1041 }
1042 outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]);
1043 cursor += 2;
1044 return true;
1045 }
1046
1047 text_input_buffer&
next_token()1048 text_input_buffer::next_token()
1049 {
1050 auto &self = *this;
1051 int start;
1052 do {
1053 start = cursor;
1054 skip_spaces();
1055 if (finished())
1056 {
1057 return self;
1058 }
1059 // Parse /* comments
1060 if (*self == '/' && peek() == '*')
1061 {
1062 // eat the start of the comment
1063 ++self;
1064 ++self;
1065 do {
1066 // Find the ending * of */
1067 while ((*self != '\0') && (*self != '*') && !finished())
1068 {
1069 ++self;
1070 }
1071 // Eat the *
1072 ++self;
1073 } while ((*self != '\0') && (*self != '/') && !finished());
1074 // Eat the /
1075 ++self;
1076 }
1077 // Parse // comments
1078 if ((*self == '/' && peek() == '/'))
1079 {
1080 // eat the start of the comment
1081 ++self;
1082 ++self;
1083 // Find the ending of the line
1084 while (*self != '\n' && !finished())
1085 {
1086 ++self;
1087 }
1088 // Eat the \n
1089 ++self;
1090 }
1091 } while (start != cursor);
1092 return self;
1093 }
1094
1095 void
parse_error(const char * msg)1096 text_input_buffer::parse_error(const char *msg)
1097 {
1098 if (input_stack.empty())
1099 {
1100 fprintf(stderr, "Error: %s\n", msg);
1101 return;
1102 }
1103 input_buffer &b = *input_stack.top();
1104 parse_error(msg, b, b.cursor);
1105 }
1106 void
parse_error(const char * msg,input_buffer & b,int loc)1107 text_input_buffer::parse_error(const char *msg,
1108 input_buffer &b,
1109 int loc)
1110 {
1111 int line_count = 1;
1112 int line_start = 0;
1113 int line_end = loc;
1114 if (loc < 0 || loc > b.size)
1115 {
1116 return;
1117 }
1118 for (int i=loc ; i>0 ; --i)
1119 {
1120 if (b.buffer[i] == '\n')
1121 {
1122 line_count++;
1123 if (line_start == 0)
1124 {
1125 line_start = i+1;
1126 }
1127 }
1128 }
1129 for (int i=loc+1 ; i<b.size ; ++i)
1130 {
1131 if (b.buffer[i] == '\n')
1132 {
1133 line_end = i;
1134 break;
1135 }
1136 }
1137 fprintf(stderr, "Error at %s:%d:%d: %s\n", b.filename().c_str(), line_count, loc - line_start, msg);
1138 fwrite(&b.buffer[line_start], line_end-line_start, 1, stderr);
1139 putc('\n', stderr);
1140 for (int i=0 ; i<(loc-line_start) ; ++i)
1141 {
1142 char c = (b.buffer[i+line_start] == '\t') ? '\t' : ' ';
1143 putc(c, stderr);
1144 }
1145 putc('^', stderr);
1146 putc('\n', stderr);
1147 }
1148 #ifndef NDEBUG
1149 void
dump()1150 input_buffer::dump()
1151 {
1152 fprintf(stderr, "Current cursor: %d\n", cursor);
1153 fwrite(&buffer[cursor], size-cursor, 1, stderr);
1154 }
1155 #endif
1156
1157
1158 namespace
1159 {
1160 /**
1161 * The source files are ASCII, so we provide a non-locale-aware version of
1162 * isalpha. This is a class so that it can be used with a template function
1163 * for parsing strings.
1164 */
1165 struct is_alpha
1166 {
checkdtc::__anon3998a5d80311::is_alpha1167 static inline bool check(const char c)
1168 {
1169 return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') &&
1170 (c <= 'Z'));
1171 }
1172 };
1173 /**
1174 * Check whether a character is in the set allowed for node names. This is a
1175 * class so that it can be used with a template function for parsing strings.
1176 */
1177 struct is_node_name_character
1178 {
checkdtc::__anon3998a5d80311::is_node_name_character1179 static inline bool check(const char c)
1180 {
1181 switch(c)
1182 {
1183 default:
1184 return false;
1185 case 'a'...'z': case 'A'...'Z': case '0'...'9':
1186 case ',': case '.': case '+': case '-':
1187 case '_':
1188 return true;
1189 }
1190 }
1191 };
1192 /**
1193 * Check whether a character is in the set allowed for property names. This is
1194 * a class so that it can be used with a template function for parsing strings.
1195 */
1196 struct is_property_name_character
1197 {
checkdtc::__anon3998a5d80311::is_property_name_character1198 static inline bool check(const char c)
1199 {
1200 switch(c)
1201 {
1202 default:
1203 return false;
1204 case 'a'...'z': case 'A'...'Z': case '0'...'9':
1205 case ',': case '.': case '+': case '-':
1206 case '_': case '#':
1207 return true;
1208 }
1209 }
1210 };
1211
1212 template<class T>
parse(text_input_buffer & s)1213 string parse(text_input_buffer &s)
1214 {
1215 std::vector<char> bytes;
1216 for (char c=*s ; T::check(c) ; c=*(++s))
1217 {
1218 bytes.push_back(c);
1219 }
1220 return string(bytes.begin(), bytes.end());
1221 }
1222
1223 }
1224
1225 string
parse_node_name()1226 text_input_buffer::parse_node_name()
1227 {
1228 return parse<is_node_name_character>(*this);
1229 }
1230
1231 string
parse_property_name()1232 text_input_buffer::parse_property_name()
1233 {
1234 return parse<is_property_name_character>(*this);
1235 }
1236
1237 string
parse_node_or_property_name(bool & is_property)1238 text_input_buffer::parse_node_or_property_name(bool &is_property)
1239 {
1240 if (is_property)
1241 {
1242 return parse_property_name();
1243 }
1244 std::vector<char> bytes;
1245 for (char c=*(*this) ; is_node_name_character::check(c) ; c=*(++(*this)))
1246 {
1247 bytes.push_back(c);
1248 }
1249 for (char c=*(*this) ; is_property_name_character::check(c) ; c=*(++(*this)))
1250 {
1251 bytes.push_back(c);
1252 is_property = true;
1253 }
1254 return string(bytes.begin(), bytes.end());
1255 }
1256
1257 string
parse_to(char stop)1258 input_buffer::parse_to(char stop)
1259 {
1260 std::vector<char> bytes;
1261 for (char c=*(*this) ; c != stop ; c=*(++(*this)))
1262 {
1263 bytes.push_back(c);
1264 }
1265 return string(bytes.begin(), bytes.end());
1266 }
1267
1268 string
parse_to(char stop)1269 text_input_buffer::parse_to(char stop)
1270 {
1271 std::vector<char> bytes;
1272 for (char c=*(*this) ; c != stop ; c=*(++(*this)))
1273 {
1274 if (finished())
1275 {
1276 break;
1277 }
1278 bytes.push_back(c);
1279 }
1280 return string(bytes.begin(), bytes.end());
1281 }
1282
1283 char
peek()1284 text_input_buffer::peek()
1285 {
1286 return (*input_stack.top())[1];
1287 }
1288
1289 std::unique_ptr<input_buffer>
buffer_for_file(const string & path,bool warn)1290 input_buffer::buffer_for_file(const string &path, bool warn)
1291 {
1292 if (path == "-")
1293 {
1294 std::unique_ptr<input_buffer> b(new stream_input_buffer());
1295 return b;
1296 }
1297 int source = open(path.c_str(), O_RDONLY);
1298 if (source == -1)
1299 {
1300 if (warn)
1301 {
1302 fprintf(stderr, "Unable to open file '%s'. %s\n", path.c_str(), strerror(errno));
1303 }
1304 return 0;
1305 }
1306 struct stat st;
1307 if (fstat(source, &st) == 0 && S_ISDIR(st.st_mode))
1308 {
1309 if (warn)
1310 {
1311 fprintf(stderr, "File %s is a directory\n", path.c_str());
1312 }
1313 close(source);
1314 return 0;
1315 }
1316 std::unique_ptr<input_buffer> b(new mmap_input_buffer(source, string(path)));
1317 close(source);
1318 return b;
1319 }
1320
1321 } // namespace dtc
1322
1323