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