]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/input_buffer.cc
ident(1): Normalizing date format
[FreeBSD/FreeBSD.git] / usr.bin / dtc / input_buffer.cc
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;
70         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 {
92         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
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
125 mmap_input_buffer::~mmap_input_buffer()
126 {
127         if (buffer != 0)
128         {
129                 munmap(const_cast<char*>(buffer), size);
130         }
131 }
132
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
151 input_buffer::skip_to(char c)
152 {
153         while ((cursor < size) && (buffer[cursor] != c))
154         {
155                 cursor++;
156         }
157 }
158
159 void
160 text_input_buffer::skip_to(char c)
161 {
162         while (!finished() && (*(*this) != c))
163         {
164                 ++(*this);
165         }
166 }
167
168 void
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
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
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
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
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
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          */
393         expression(source_location l) : loc(l) {}
394         virtual ~expression() {}
395 #ifndef NDEBUG
396         /**
397          * Dumps this expression to `std::cerr`, appending a newline if `nl` is
398          * `true`.
399          */
400         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          */
436         result operator()() override
437         {
438                 return {val, true};
439         }
440         int precedence() override
441         {
442                 return 0;
443         }
444         public:
445         /**
446          * Constructor.
447          */
448         terminal_expr(source_location l, valty v) : expression(l), val(v) {}
449 #ifndef NDEBUG
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          */
466         paren_expression(source_location l, expression_ptr p) : expression(l),
467         subexpr(std::move(p)) {}
468         int precedence() override
469         {
470                 return 0;
471         }
472         /**
473          * Evaluate - just forwards to the underlying expression.
474          */
475         result operator()() override
476         {
477                 return (*subexpr)();
478         }
479 #ifndef NDEBUG
480         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;
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          */
517         int precedence() override
518         {
519                 return 3;
520         }
521         public:
522         unary_operator(source_location l, expression_ptr p) :
523                 expression(l), subexpr(std::move(p)) {}
524 #ifndef NDEBUG
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          */
552         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 {
573         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         }
584         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          */
593         binary_operator(source_location l, const char *) :
594                 binary_operator_base(l) {}
595 #else
596         const char *opName;
597         binary_operator(source_location l, const char *o) :
598                 binary_operator_base(l), opName(o) {}
599         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;
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         }
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
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:
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 {
666         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 {
674         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 {
682         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 {
691         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;
702         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
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
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
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
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&
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
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
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
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 {
1113         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 {
1125         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 {
1144         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>
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
1172 text_input_buffer::parse_node_name()
1173 {
1174         return parse<is_node_name_character>(*this);
1175 }
1176
1177 string
1178 text_input_buffer::parse_property_name()
1179 {
1180         return parse<is_property_name_character>(*this);
1181 }
1182
1183 string
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
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
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
1230 text_input_buffer::peek()
1231 {
1232         return (*input_stack.top())[1];
1233 }
1234
1235 std::unique_ptr<input_buffer>
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