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