input_buffer.cc (009e81b16465ea457c0e63fd49fe77f47cc27a5a) input_buffer.cc (bbe31b709a653884e18995a1c97cdafd7392999a)
1/*-
2 * Copyright (c) 2013 David Chisnall
3 * All rights reserved.
4 *
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7 * ("CTSRD"), as part of the DARPA CRASH research programme.
8 *

--- 32 unchanged lines hidden (view full) ---

41#ifndef NDEBUG
42#include <iostream>
43#endif
44
45
46#include <sys/stat.h>
47#include <sys/mman.h>
48#include <assert.h>
1/*-
2 * Copyright (c) 2013 David Chisnall
3 * All rights reserved.
4 *
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7 * ("CTSRD"), as part of the DARPA CRASH research programme.
8 *

--- 32 unchanged lines hidden (view full) ---

41#ifndef NDEBUG
42#include <iostream>
43#endif
44
45
46#include <sys/stat.h>
47#include <sys/mman.h>
48#include <assert.h>
49#include <fcntl.h>
50#include <unistd.h>
49
50#ifndef MAP_PREFAULT_READ
51#define MAP_PREFAULT_READ 0
52#endif
53
51
52#ifndef MAP_PREFAULT_READ
53#define MAP_PREFAULT_READ 0
54#endif
55
56using std::string;
57
58namespace
59{
60/**
61 * Subclass of input_buffer that mmap()s a file and owns the resulting memory.
62 * When this object is destroyed, the memory is unmapped.
63 */
64struct mmap_input_buffer : public dtc::input_buffer
65{
66 string fn;
67 const string &filename() const override
68 {
69 return fn;
70 }
71 /**
72 * Constructs a new buffer from the file passed in as a file
73 * descriptor.
74 */
75 mmap_input_buffer(int fd, string &&filename);
76 /**
77 * Unmaps the buffer, if one exists.
78 */
79 virtual ~mmap_input_buffer();
80};
81/**
82 * Input buffer read from standard input. This is used for reading device tree
83 * blobs and source from standard input. It reads the entire input into
84 * malloc'd memory, so will be very slow for large inputs. DTS and DTB files
85 * are very rarely more than 10KB though, so this is probably not a problem.
86 */
87struct stream_input_buffer : public dtc::input_buffer
88{
89 const string &filename() const override
90 {
91 static string n = "<standard input>";
92 return n;
93 }
94 /**
95 * The buffer that will store the data read from the standard input.
96 */
97 std::vector<char> b;
98 /**
99 * Constructs a new buffer from the standard input.
100 */
101 stream_input_buffer();
102};
103
104mmap_input_buffer::mmap_input_buffer(int fd, std::string &&filename)
105 : input_buffer(0, 0), fn(filename)
106{
107 struct stat sb;
108 if (fstat(fd, &sb))
109 {
110 perror("Failed to stat file");
111 }
112 size = sb.st_size;
113 buffer = (const char*)mmap(0, size, PROT_READ, MAP_PRIVATE |
114 MAP_PREFAULT_READ, fd, 0);
115 if (buffer == MAP_FAILED)
116 {
117 perror("Failed to mmap file");
118 exit(EXIT_FAILURE);
119 }
120}
121
122mmap_input_buffer::~mmap_input_buffer()
123{
124 if (buffer != 0)
125 {
126 munmap((void*)buffer, size);
127 }
128}
129
130stream_input_buffer::stream_input_buffer() : input_buffer(0, 0)
131{
132 int c;
133 while ((c = fgetc(stdin)) != EOF)
134 {
135 b.push_back(c);
136 }
137 buffer = b.data();
138 size = b.size();
139}
140
141} // Anonymous namespace
142
143
54namespace dtc
55{
144namespace dtc
145{
146
56void
147void
57input_buffer::skip_spaces()
148input_buffer::skip_to(char c)
58{
149{
59 if (cursor >= size) { return; }
60 if (cursor < 0) { return; }
61 char c = buffer[cursor];
150 while ((cursor < size) && (buffer[cursor] != c))
151 {
152 cursor++;
153 }
154}
155
156void
157text_input_buffer::skip_to(char c)
158{
159 while (!finished() && (*(*this) != c))
160 {
161 ++(*this);
162 }
163}
164
165void
166text_input_buffer::skip_spaces()
167{
168 if (finished()) { return; }
169 char c = *(*this);
170 bool last_nl = false;
62 while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f')
63 || (c == '\v') || (c == '\r'))
64 {
171 while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f')
172 || (c == '\v') || (c == '\r'))
173 {
65 cursor++;
66 if (cursor > size)
174 last_nl = ((c == '\n') || (c == '\r'));
175 ++(*this);
176 if (finished())
67 {
68 c = '\0';
69 }
70 else
71 {
177 {
178 c = '\0';
179 }
180 else
181 {
72 c = buffer[cursor];
182 c = *(*this);
73 }
74 }
183 }
184 }
185 // Skip C preprocessor leftovers
186 if ((c == '#') && ((cursor == 0) || last_nl))
187 {
188 skip_to('\n');
189 skip_spaces();
190 }
191 if (consume("/include/"))
192 {
193 handle_include();
194 skip_spaces();
195 }
75}
76
196}
197
198void
199text_input_buffer::handle_include()
200{
201 bool reallyInclude = true;
202 if (consume("if "))
203 {
204 next_token();
205 string name = parse_property_name();
206 if (defines.count(name) > 0)
207 {
208 reallyInclude = true;
209 }
210 consume('/');
211 }
212 next_token();
213 if (!consume('"'))
214 {
215 parse_error("Expected quoted filename");
216 return;
217 }
218 string file = parse_to('"');
219 consume('"');
220 if (!reallyInclude)
221 {
222 return;
223 }
224 string include_file = dir + '/' + file;
225 auto include_buffer = input_buffer::buffer_for_file(include_file, false);
226 if (include_buffer == 0)
227 {
228 for (auto i : include_paths)
229 {
230 include_file = i + '/' + file;
231 include_buffer = input_buffer::buffer_for_file(include_file, false);
232 if (include_buffer != 0)
233 {
234 break;
235 }
236 }
237 }
238 if (depfile)
239 {
240 putc(' ', depfile);
241 fputs(include_file.c_str(), depfile);
242 }
243 if (!include_buffer)
244 {
245 parse_error("Unable to locate input file");
246 return;
247 }
248 input_stack.push(std::move(include_buffer));
249}
250
77input_buffer
78input_buffer::buffer_from_offset(int offset, int s)
79{
251input_buffer
252input_buffer::buffer_from_offset(int offset, int s)
253{
254 if (offset < 0)
255 {
256 return input_buffer();
257 }
80 if (s == 0)
81 {
82 s = size - offset;
83 }
84 if (offset > size)
85 {
86 return input_buffer();
87 }

--- 11 unchanged lines hidden (view full) ---

99 if (len > size - cursor)
100 {
101 return false;
102 }
103 else
104 {
105 for (int i=0 ; i<len ; ++i)
106 {
258 if (s == 0)
259 {
260 s = size - offset;
261 }
262 if (offset > size)
263 {
264 return input_buffer();
265 }

--- 11 unchanged lines hidden (view full) ---

277 if (len > size - cursor)
278 {
279 return false;
280 }
281 else
282 {
283 for (int i=0 ; i<len ; ++i)
284 {
107 if (str[i] != buffer[cursor + i])
285 if (str[i] != (*this)[i])
108 {
109 return false;
110 }
111 }
112 cursor += len;
113 return true;
114 }
115 return false;
116}
117
118bool
119input_buffer::consume_integer(unsigned long long &outInt)
120{
121 // The first character must be a digit. Hex and octal strings
122 // are prefixed by 0 and 0x, respectively.
123 if (!isdigit((*this)[0]))
124 {
125 return false;
126 }
286 {
287 return false;
288 }
289 }
290 cursor += len;
291 return true;
292 }
293 return false;
294}
295
296bool
297input_buffer::consume_integer(unsigned long long &outInt)
298{
299 // The first character must be a digit. Hex and octal strings
300 // are prefixed by 0 and 0x, respectively.
301 if (!isdigit((*this)[0]))
302 {
303 return false;
304 }
127 char *end=0;
305 char *end= const_cast<char*>(&buffer[size]);
128 outInt = strtoull(&buffer[cursor], &end, 0);
129 if (end == &buffer[cursor])
130 {
131 return false;
132 }
133 cursor = end - buffer;
134 return true;
135}

--- 5 unchanged lines hidden (view full) ---

141 */
142typedef unsigned long long valty;
143
144/**
145 * Expression tree currently being parsed.
146 */
147struct expression
148{
306 outInt = strtoull(&buffer[cursor], &end, 0);
307 if (end == &buffer[cursor])
308 {
309 return false;
310 }
311 cursor = end - buffer;
312 return true;
313}

--- 5 unchanged lines hidden (view full) ---

319 */
320typedef unsigned long long valty;
321
322/**
323 * Expression tree currently being parsed.
324 */
325struct expression
326{
327 typedef text_input_buffer::source_location source_location;
149 /**
328 /**
329 * The type that is returned when computing the result. The boolean value
330 * indicates whether this is a valid expression.
331 *
332 * FIXME: Once we can use C++17, this should be `std::optional`.
333 */
334 typedef std::pair<valty, bool> result;
335 /**
150 * Evaluate this node, taking into account operator precedence.
151 */
336 * Evaluate this node, taking into account operator precedence.
337 */
152 virtual valty operator()() = 0;
338 virtual result operator()() = 0;
153 /**
154 * Returns the precedence of this node. Lower values indicate higher
155 * precedence.
156 */
157 virtual int precedence() = 0;
339 /**
340 * Returns the precedence of this node. Lower values indicate higher
341 * precedence.
342 */
343 virtual int precedence() = 0;
344 /**
345 * Constructs an expression, storing the location where it was created.
346 */
347 expression(source_location l) : loc(l) {}
158 virtual ~expression() {}
159#ifndef NDEBUG
160 /**
161 * Dumps this expression to `std::cerr`, appending a newline if `nl` is
162 * `true`.
163 */
164 void dump(bool nl=false)
165 {
348 virtual ~expression() {}
349#ifndef NDEBUG
350 /**
351 * Dumps this expression to `std::cerr`, appending a newline if `nl` is
352 * `true`.
353 */
354 void dump(bool nl=false)
355 {
166 if (this == nullptr)
356 void *ptr = this;
357 if (ptr == nullptr)
167 {
168 std::cerr << "{nullptr}\n";
169 return;
170 }
171 dump_impl();
172 if (nl)
173 {
174 std::cerr << '\n';
175 }
176 }
177 private:
178 /**
179 * Method that sublcasses override to implement the behaviour of `dump()`.
180 */
181 virtual void dump_impl() = 0;
182#endif
358 {
359 std::cerr << "{nullptr}\n";
360 return;
361 }
362 dump_impl();
363 if (nl)
364 {
365 std::cerr << '\n';
366 }
367 }
368 private:
369 /**
370 * Method that sublcasses override to implement the behaviour of `dump()`.
371 */
372 virtual void dump_impl() = 0;
373#endif
374 protected:
375 source_location loc;
183};
184
185/**
186 * Expression wrapping a single integer. Leaf nodes in the expression tree.
187 */
188class terminal_expr : public expression
189{
190 /**
191 * The value that this wraps.
192 */
193 valty val;
194 /**
195 * Evaluate. Trivially returns the value that this class wraps.
196 */
376};
377
378/**
379 * Expression wrapping a single integer. Leaf nodes in the expression tree.
380 */
381class terminal_expr : public expression
382{
383 /**
384 * The value that this wraps.
385 */
386 valty val;
387 /**
388 * Evaluate. Trivially returns the value that this class wraps.
389 */
197 valty operator()() override
390 result operator()() override
198 {
391 {
199 return val;
392 return {val, true};
200 }
201 int precedence() override
202 {
203 return 0;
204 }
205 public:
206 /**
207 * Constructor.
208 */
393 }
394 int precedence() override
395 {
396 return 0;
397 }
398 public:
399 /**
400 * Constructor.
401 */
209 terminal_expr(valty v) : val(v) {}
402 terminal_expr(source_location l, valty v) : expression(l), val(v) {}
210#ifndef NDEBUG
211 void dump_impl() override { std::cerr << val; }
212#endif
213};
214
215/**
216 * Parenthetical expression. Exists to make the contents opaque.
217 */
218struct paren_expression : public expression
219{
220 /**
221 * The expression within the parentheses.
222 */
223 expression_ptr subexpr;
224 /**
225 * Constructor. Takes the child expression as the only argument.
226 */
403#ifndef NDEBUG
404 void dump_impl() override { std::cerr << val; }
405#endif
406};
407
408/**
409 * Parenthetical expression. Exists to make the contents opaque.
410 */
411struct paren_expression : public expression
412{
413 /**
414 * The expression within the parentheses.
415 */
416 expression_ptr subexpr;
417 /**
418 * Constructor. Takes the child expression as the only argument.
419 */
227 paren_expression(expression_ptr p) : subexpr(std::move(p)) {}
420 paren_expression(source_location l, expression_ptr p) : expression(l),
421 subexpr(std::move(p)) {}
228 int precedence() override
229 {
230 return 0;
231 }
232 /**
233 * Evaluate - just forwards to the underlying expression.
234 */
422 int precedence() override
423 {
424 return 0;
425 }
426 /**
427 * Evaluate - just forwards to the underlying expression.
428 */
235 valty operator()() override
429 result operator()() override
236 {
237 return (*subexpr)();
238 }
239#ifndef NDEBUG
240 void dump_impl() override
241 {
242 std::cerr << " (";
243 subexpr->dump();

--- 11 unchanged lines hidden (view full) ---

255 */
256template<char OpChar, class Op>
257class unary_operator : public expression
258{
259 /**
260 * The subexpression for this unary operator.
261 */
262 expression_ptr subexpr;
430 {
431 return (*subexpr)();
432 }
433#ifndef NDEBUG
434 void dump_impl() override
435 {
436 std::cerr << " (";
437 subexpr->dump();

--- 11 unchanged lines hidden (view full) ---

449 */
450template<char OpChar, class Op>
451class unary_operator : public expression
452{
453 /**
454 * The subexpression for this unary operator.
455 */
456 expression_ptr subexpr;
263 valty operator()() override
457 result operator()() override
264 {
265 Op op;
458 {
459 Op op;
266 return op((*subexpr)());
460 result s = (*subexpr)();
461 if (!s.second)
462 {
463 return s;
464 }
465 return {op(s.first), true};
267 }
268 /**
269 * All unary operators have the same precedence. They are all evaluated
270 * before binary expressions, but after parentheses.
271 */
272 int precedence() override
273 {
274 return 3;
275 }
276 public:
466 }
467 /**
468 * All unary operators have the same precedence. They are all evaluated
469 * before binary expressions, but after parentheses.
470 */
471 int precedence() override
472 {
473 return 3;
474 }
475 public:
277 unary_operator(expression_ptr p) : subexpr(std::move(p)) {}
476 unary_operator(source_location l, expression_ptr p) :
477 expression(l), subexpr(std::move(p)) {}
278#ifndef NDEBUG
279 void dump_impl() override
280 {
281 std::cerr << OpChar;
282 subexpr->dump();
283 }
284#endif
285};
286
287/**
288 * Abstract base class for binary operators. Allows the tree to be modified
289 * without knowing what the operations actually are.
290 */
291struct binary_operator_base : public expression
292{
478#ifndef NDEBUG
479 void dump_impl() override
480 {
481 std::cerr << OpChar;
482 subexpr->dump();
483 }
484#endif
485};
486
487/**
488 * Abstract base class for binary operators. Allows the tree to be modified
489 * without knowing what the operations actually are.
490 */
491struct binary_operator_base : public expression
492{
493 using expression::expression;
293 /**
294 * The left side of the expression.
295 */
296 expression_ptr lhs;
297 /**
298 * The right side of the expression.
299 */
300 expression_ptr rhs;

--- 17 unchanged lines hidden (view full) ---

318
319/**
320 * Template class for binary operators. The precedence and the operation are
321 * provided as template parameters.
322 */
323template<int Precedence, class Op>
324struct binary_operator : public binary_operator_base
325{
494 /**
495 * The left side of the expression.
496 */
497 expression_ptr lhs;
498 /**
499 * The right side of the expression.
500 */
501 expression_ptr rhs;

--- 17 unchanged lines hidden (view full) ---

519
520/**
521 * Template class for binary operators. The precedence and the operation are
522 * provided as template parameters.
523 */
524template<int Precedence, class Op>
525struct binary_operator : public binary_operator_base
526{
326 valty operator()() override
527 result operator()() override
327 {
328 Op op;
528 {
529 Op op;
329 return op((*lhs)(), (*rhs)());
530 result l = (*lhs)();
531 result r = (*rhs)();
532 if (!(l.second && r.second))
533 {
534 return {0, false};
535 }
536 return {op(l.first, r.first), true};
330 }
331 int precedence() override
332 {
333 return Precedence;
334 }
335#ifdef NDEBUG
336 /**
337 * Constructor. Takes the name of the operator as an argument, for
338 * debugging. Only stores it in debug mode.
339 */
537 }
538 int precedence() override
539 {
540 return Precedence;
541 }
542#ifdef NDEBUG
543 /**
544 * Constructor. Takes the name of the operator as an argument, for
545 * debugging. Only stores it in debug mode.
546 */
340 binary_operator(const char *) {}
547 binary_operator(source_location l, const char *) : expression(l) {}
341#else
342 const char *opName;
548#else
549 const char *opName;
343 binary_operator(const char *o) : opName(o) {}
550 binary_operator(source_location l, const char *o) :
551 binary_operator_base(l), opName(o) {}
344 void dump_impl() override
345 {
346 lhs->dump();
347 std::cerr << opName;
348 rhs->dump();
349 }
350#endif
351};

--- 11 unchanged lines hidden (view full) ---

363 /**
364 * The expression that this evaluates to if the condition is true.
365 */
366 expression_ptr lhs;
367 /**
368 * The expression that this evaluates to if the condition is false.
369 */
370 expression_ptr rhs;
552 void dump_impl() override
553 {
554 lhs->dump();
555 std::cerr << opName;
556 rhs->dump();
557 }
558#endif
559};

--- 11 unchanged lines hidden (view full) ---

571 /**
572 * The expression that this evaluates to if the condition is true.
573 */
574 expression_ptr lhs;
575 /**
576 * The expression that this evaluates to if the condition is false.
577 */
578 expression_ptr rhs;
371 valty operator()() override
579 result operator()() override
372 {
580 {
373 return (*cond)() ? (*lhs)() : (*rhs)();
581 result c = (*cond)();
582 result l = (*lhs)();
583 result r = (*rhs)();
584 if (!(l.second && r.second && c.second))
585 {
586 return {0, false};
587 }
588 return c.first ? l : r;
374 }
375 int precedence() override
376 {
377 // The actual precedence of a ternary conditional operator is 15, but
378 // its associativity is the opposite way around to the other operators,
379 // so we fudge it slightly.
380 return 3;
381 }
382#ifndef NDEBUG
383 void dump_impl() override
384 {
385 cond->dump();
386 std::cerr << " ? ";
387 lhs->dump();
388 std::cerr << " : ";
389 rhs->dump();
390 }
391#endif
392 public:
589 }
590 int precedence() override
591 {
592 // The actual precedence of a ternary conditional operator is 15, but
593 // its associativity is the opposite way around to the other operators,
594 // so we fudge it slightly.
595 return 3;
596 }
597#ifndef NDEBUG
598 void dump_impl() override
599 {
600 cond->dump();
601 std::cerr << " ? ";
602 lhs->dump();
603 std::cerr << " : ";
604 rhs->dump();
605 }
606#endif
607 public:
393 ternary_conditional_operator(expression_ptr c,
608 ternary_conditional_operator(source_location sl,
609 expression_ptr c,
394 expression_ptr l,
395 expression_ptr r) :
610 expression_ptr l,
611 expression_ptr r) :
396 cond(std::move(c)), lhs(std::move(l)), rhs(std::move(r)) {}
612 expression(sl), cond(std::move(c)), lhs(std::move(l)),
613 rhs(std::move(r)) {}
397};
398
399template<typename T>
400struct lshift
401{
402 constexpr T operator()(const T &lhs, const T &rhs) const
403 {
404 return lhs << rhs;

--- 20 unchanged lines hidden (view full) ---

425struct bit_not
426{
427 constexpr T operator()(const T &val) const
428 {
429 return ~val;
430 }
431};
432
614};
615
616template<typename T>
617struct lshift
618{
619 constexpr T operator()(const T &lhs, const T &rhs) const
620 {
621 return lhs << rhs;

--- 20 unchanged lines hidden (view full) ---

642struct bit_not
643{
644 constexpr T operator()(const T &val) const
645 {
646 return ~val;
647 }
648};
649
650template<typename T>
651struct divmod : public binary_operator<5, T>
652{
653 using binary_operator<5, T>::binary_operator;
654 using binary_operator_base::result;
655 result operator()() override
656 {
657 result r = (*binary_operator_base::rhs)();
658 if (r.second && (r.first == 0))
659 {
660 expression::loc.report_error("Division by zero");
661 return {0, false};
662 }
663 return binary_operator<5, T>::operator()();
664 }
665};
666
433} // anonymous namespace
434
435
667} // anonymous namespace
668
669
436expression_ptr input_buffer::parse_binary_expression(expression_ptr lhs)
670expression_ptr text_input_buffer::parse_binary_expression(expression_ptr lhs)
437{
438 next_token();
439 binary_operator_base *expr = nullptr;
671{
672 next_token();
673 binary_operator_base *expr = nullptr;
440 char op = ((*this)[0]);
674 char op = *(*this);
675 source_location l = location();
441 switch (op)
442 {
443 default:
444 return lhs;
445 case '+':
676 switch (op)
677 {
678 default:
679 return lhs;
680 case '+':
446 expr = new binary_operator<6, std::plus<valty>>("+");
681 expr = new binary_operator<6, std::plus<valty>>(l, "+");
447 break;
448 case '-':
682 break;
683 case '-':
449 expr = new binary_operator<6, std::minus<valty>>("-");
684 expr = new binary_operator<6, std::minus<valty>>(l, "-");
450 break;
451 case '%':
685 break;
686 case '%':
452 expr = new binary_operator<5, std::modulus<valty>>("%");
687 expr = new divmod<std::modulus<valty>>(l, "/");
453 break;
454 case '*':
688 break;
689 case '*':
455 expr = new binary_operator<5, std::multiplies<valty>>("*");
690 expr = new binary_operator<5, std::multiplies<valty>>(l, "*");
456 break;
457 case '/':
691 break;
692 case '/':
458 expr = new binary_operator<5, std::divides<valty>>("/");
693 expr = new divmod<std::divides<valty>>(l, "/");
459 break;
460 case '<':
694 break;
695 case '<':
461 cursor++;
462 switch ((*this)[0])
696 switch (peek())
463 {
464 default:
465 parse_error("Invalid operator");
466 return nullptr;
467 case ' ':
468 case '(':
469 case '0'...'9':
697 {
698 default:
699 parse_error("Invalid operator");
700 return nullptr;
701 case ' ':
702 case '(':
703 case '0'...'9':
470 cursor--;
471 expr = new binary_operator<8, std::less<valty>>("<");
704 expr = new binary_operator<8, std::less<valty>>(l, "<");
472 break;
473 case '=':
705 break;
706 case '=':
474 expr = new binary_operator<8, std::less_equal<valty>>("<=");
707 ++(*this);
708 expr = new binary_operator<8, std::less_equal<valty>>(l, "<=");
475 break;
476 case '<':
709 break;
710 case '<':
477 expr = new binary_operator<7, lshift<valty>>("<<");
711 ++(*this);
712 expr = new binary_operator<7, lshift<valty>>(l, "<<");
478 break;
479 }
480 break;
481 case '>':
713 break;
714 }
715 break;
716 case '>':
482 cursor++;
483 switch ((*this)[0])
717 switch (peek())
484 {
485 default:
486 parse_error("Invalid operator");
487 return nullptr;
488 case '(':
489 case ' ':
490 case '0'...'9':
718 {
719 default:
720 parse_error("Invalid operator");
721 return nullptr;
722 case '(':
723 case ' ':
724 case '0'...'9':
491 cursor--;
492 expr = new binary_operator<8, std::greater<valty>>(">");
725 expr = new binary_operator<8, std::greater<valty>>(l, ">");
493 break;
494 case '=':
726 break;
727 case '=':
495 expr = new binary_operator<8, std::greater_equal<valty>>(">=");
728 ++(*this);
729 expr = new binary_operator<8, std::greater_equal<valty>>(l, ">=");
496 break;
497 case '>':
730 break;
731 case '>':
498 expr = new binary_operator<7, rshift<valty>>(">>");
732 ++(*this);
733 expr = new binary_operator<7, rshift<valty>>(l, ">>");
499 break;
500 return lhs;
501 }
502 break;
503 case '=':
734 break;
735 return lhs;
736 }
737 break;
738 case '=':
504 if ((*this)[1] != '=')
739 if (peek() != '=')
505 {
506 parse_error("Invalid operator");
507 return nullptr;
508 }
740 {
741 parse_error("Invalid operator");
742 return nullptr;
743 }
509 consume('=');
510 expr = new binary_operator<9, std::equal_to<valty>>("==");
744 expr = new binary_operator<9, std::equal_to<valty>>(l, "==");
511 break;
512 case '!':
745 break;
746 case '!':
513 if ((*this)[1] != '=')
747 if (peek() != '=')
514 {
515 parse_error("Invalid operator");
516 return nullptr;
517 }
518 cursor++;
748 {
749 parse_error("Invalid operator");
750 return nullptr;
751 }
752 cursor++;
519 expr = new binary_operator<9, std::not_equal_to<valty>>("!=");
753 expr = new binary_operator<9, std::not_equal_to<valty>>(l, "!=");
520 break;
521 case '&':
754 break;
755 case '&':
522 if ((*this)[1] == '&')
756 if (peek() == '&')
523 {
757 {
524 expr = new binary_operator<13, std::logical_and<valty>>("&&");
758 expr = new binary_operator<13, std::logical_and<valty>>(l, "&&");
525 }
526 else
527 {
759 }
760 else
761 {
528 expr = new binary_operator<10, std::bit_and<valty>>("&");
762 expr = new binary_operator<10, std::bit_and<valty>>(l, "&");
529 }
530 break;
531 case '|':
763 }
764 break;
765 case '|':
532 if ((*this)[1] == '|')
766 if (peek() == '|')
533 {
767 {
534 expr = new binary_operator<12, std::logical_or<valty>>("||");
768 expr = new binary_operator<12, std::logical_or<valty>>(l, "||");
535 }
536 else
537 {
769 }
770 else
771 {
538 expr = new binary_operator<14, std::bit_or<valty>>("|");
772 expr = new binary_operator<14, std::bit_or<valty>>(l, "|");
539 }
540 break;
541 case '?':
542 {
543 consume('?');
544 expression_ptr true_case = parse_expression();
545 next_token();
546 if (!true_case || !consume(':'))
547 {
548 parse_error("Expected : in ternary conditional operator");
549 return nullptr;
550 }
551 expression_ptr false_case = parse_expression();
552 if (!false_case)
553 {
554 parse_error("Expected false condition for ternary operator");
555 return nullptr;
556 }
773 }
774 break;
775 case '?':
776 {
777 consume('?');
778 expression_ptr true_case = parse_expression();
779 next_token();
780 if (!true_case || !consume(':'))
781 {
782 parse_error("Expected : in ternary conditional operator");
783 return nullptr;
784 }
785 expression_ptr false_case = parse_expression();
786 if (!false_case)
787 {
788 parse_error("Expected false condition for ternary operator");
789 return nullptr;
790 }
557 return expression_ptr(new ternary_conditional_operator(std::move(lhs),
791 return expression_ptr(new ternary_conditional_operator(l, std::move(lhs),
558 std::move(true_case), std::move(false_case)));
559 }
560 }
792 std::move(true_case), std::move(false_case)));
793 }
794 }
561 cursor++;
795 ++(*this);
562 next_token();
563 expression_ptr e(expr);
564 expression_ptr rhs(parse_expression());
565 if (!rhs)
566 {
567 return nullptr;
568 }
569 expr->lhs = std::move(lhs);

--- 9 unchanged lines hidden (view full) ---

579 static_cast<binary_operator_base*>(rhs.get());
580 rhs_op->insert_left(expr);
581 e.release();
582 return rhs;
583 }
584 return e;
585}
586
796 next_token();
797 expression_ptr e(expr);
798 expression_ptr rhs(parse_expression());
799 if (!rhs)
800 {
801 return nullptr;
802 }
803 expr->lhs = std::move(lhs);

--- 9 unchanged lines hidden (view full) ---

813 static_cast<binary_operator_base*>(rhs.get());
814 rhs_op->insert_left(expr);
815 e.release();
816 return rhs;
817 }
818 return e;
819}
820
587expression_ptr input_buffer::parse_expression(bool stopAtParen)
821expression_ptr text_input_buffer::parse_expression(bool stopAtParen)
588{
589 next_token();
590 unsigned long long leftVal;
591 expression_ptr lhs;
822{
823 next_token();
824 unsigned long long leftVal;
825 expression_ptr lhs;
592 switch ((*this)[0])
826 source_location l = location();
827 switch (*(*this))
593 {
594 case '0'...'9':
595 if (!consume_integer(leftVal))
596 {
597 return nullptr;
598 }
828 {
829 case '0'...'9':
830 if (!consume_integer(leftVal))
831 {
832 return nullptr;
833 }
599 lhs.reset(new terminal_expr(leftVal));
834 lhs.reset(new terminal_expr(l, leftVal));
600 break;
601 case '(':
602 {
603 consume('(');
604 expression_ptr &&subexpr = parse_expression();
605 if (!subexpr)
606 {
607 return nullptr;
608 }
835 break;
836 case '(':
837 {
838 consume('(');
839 expression_ptr &&subexpr = parse_expression();
840 if (!subexpr)
841 {
842 return nullptr;
843 }
609 lhs.reset(new paren_expression(std::move(subexpr)));
844 lhs.reset(new paren_expression(l, std::move(subexpr)));
610 if (!consume(')'))
611 {
612 return nullptr;
613 }
614 if (stopAtParen)
615 {
616 return lhs;
617 }
618 break;
619 }
620 case '+':
621 {
622 consume('+');
623 expression_ptr &&subexpr = parse_expression();
624 if (!subexpr)
625 {
626 return nullptr;
627 }
845 if (!consume(')'))
846 {
847 return nullptr;
848 }
849 if (stopAtParen)
850 {
851 return lhs;
852 }
853 break;
854 }
855 case '+':
856 {
857 consume('+');
858 expression_ptr &&subexpr = parse_expression();
859 if (!subexpr)
860 {
861 return nullptr;
862 }
628 lhs.reset(new unary_operator<'+', unary_plus<valty>>(std::move(subexpr)));
863 lhs.reset(new unary_operator<'+', unary_plus<valty>>(l, std::move(subexpr)));
629 break;
630 }
631 case '-':
632 {
633 consume('-');
634 expression_ptr &&subexpr = parse_expression();
635 if (!subexpr)
636 {
637 return nullptr;
638 }
864 break;
865 }
866 case '-':
867 {
868 consume('-');
869 expression_ptr &&subexpr = parse_expression();
870 if (!subexpr)
871 {
872 return nullptr;
873 }
639 lhs.reset(new unary_operator<'-', std::negate<valty>>(std::move(subexpr)));
874 lhs.reset(new unary_operator<'-', std::negate<valty>>(l, std::move(subexpr)));
640 break;
641 }
642 case '!':
643 {
644 consume('!');
645 expression_ptr &&subexpr = parse_expression();
646 if (!subexpr)
647 {
648 return nullptr;
649 }
875 break;
876 }
877 case '!':
878 {
879 consume('!');
880 expression_ptr &&subexpr = parse_expression();
881 if (!subexpr)
882 {
883 return nullptr;
884 }
650 lhs.reset(new unary_operator<'!', std::logical_not<valty>>(std::move(subexpr)));
885 lhs.reset(new unary_operator<'!', std::logical_not<valty>>(l, std::move(subexpr)));
651 break;
652 }
653 case '~':
654 {
655 consume('~');
656 expression_ptr &&subexpr = parse_expression();
657 if (!subexpr)
658 {
659 return nullptr;
660 }
886 break;
887 }
888 case '~':
889 {
890 consume('~');
891 expression_ptr &&subexpr = parse_expression();
892 if (!subexpr)
893 {
894 return nullptr;
895 }
661 lhs.reset(new unary_operator<'~', bit_not<valty>>(std::move(subexpr)));
896 lhs.reset(new unary_operator<'~', bit_not<valty>>(l, std::move(subexpr)));
662 break;
663 }
664 }
665 if (!lhs)
666 {
667 return nullptr;
668 }
669 return parse_binary_expression(std::move(lhs));
670}
671
672bool
897 break;
898 }
899 }
900 if (!lhs)
901 {
902 return nullptr;
903 }
904 return parse_binary_expression(std::move(lhs));
905}
906
907bool
673input_buffer::consume_integer_expression(unsigned long long &outInt)
908text_input_buffer::consume_integer_expression(unsigned long long &outInt)
674{
909{
675 switch ((*this)[0])
910 switch (*(*this))
676 {
677 case '(':
678 {
679 expression_ptr e(parse_expression(true));
680 if (!e)
681 {
682 return false;
683 }
911 {
912 case '(':
913 {
914 expression_ptr e(parse_expression(true));
915 if (!e)
916 {
917 return false;
918 }
684 outInt = (*e)();
685 return true;
919 auto r = (*e)();
920 if (r.second)
921 {
922 outInt = r.first;
923 return true;
924 }
925 return false;
686 }
687 case '0'...'9':
688 return consume_integer(outInt);
689 default:
690 return false;
691 }
692}
693

--- 4 unchanged lines hidden (view full) ---

698 {
699 return false;
700 }
701 outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]);
702 cursor += 2;
703 return true;
704}
705
926 }
927 case '0'...'9':
928 return consume_integer(outInt);
929 default:
930 return false;
931 }
932}
933

--- 4 unchanged lines hidden (view full) ---

938 {
939 return false;
940 }
941 outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]);
942 cursor += 2;
943 return true;
944}
945
706input_buffer&
707input_buffer::next_token()
946text_input_buffer&
947text_input_buffer::next_token()
708{
948{
949 auto &self = *this;
709 int start;
710 do {
711 start = cursor;
712 skip_spaces();
950 int start;
951 do {
952 start = cursor;
953 skip_spaces();
954 if (finished())
955 {
956 return self;
957 }
713 // Parse /* comments
958 // Parse /* comments
714 if ((*this)[0] == '/' && (*this)[1] == '*')
959 if (*self == '/' && peek() == '*')
715 {
716 // eat the start of the comment
960 {
961 // eat the start of the comment
717 ++(*this);
718 ++(*this);
962 ++self;
963 ++self;
719 do {
720 // Find the ending * of */
964 do {
965 // Find the ending * of */
721 while ((**this != '\0') && (**this != '*'))
966 while ((*self != '\0') && (*self != '*') && !finished())
722 {
967 {
723 ++(*this);
968 ++self;
724 }
725 // Eat the *
969 }
970 // Eat the *
726 ++(*this);
727 } while ((**this != '\0') && (**this != '/'));
971 ++self;
972 } while ((*self != '\0') && (*self != '/') && !finished());
728 // Eat the /
973 // Eat the /
729 ++(*this);
974 ++self;
730 }
731 // Parse // comments
975 }
976 // Parse // comments
732 if (((*this)[0] == '/' && (*this)[1] == '/'))
977 if ((*self == '/' && peek() == '/'))
733 {
734 // eat the start of the comment
978 {
979 // eat the start of the comment
735 ++(*this);
736 ++(*this);
980 ++self;
981 ++self;
737 // Find the ending of the line
982 // Find the ending of the line
738 while (**this != '\n')
983 while (*self != '\n' && !finished())
739 {
984 {
740 ++(*this);
985 ++self;
741 }
742 // Eat the \n
986 }
987 // Eat the \n
743 ++(*this);
988 ++self;
744 }
745 } while (start != cursor);
989 }
990 } while (start != cursor);
746 return *this;
991 return self;
747}
748
749void
992}
993
994void
750input_buffer::parse_error(const char *msg)
995text_input_buffer::parse_error(const char *msg)
751{
996{
997 if (input_stack.empty())
998 {
999 fprintf(stderr, "Error: %s\n", msg);
1000 return;
1001 }
1002 input_buffer &b = *input_stack.top();
1003 parse_error(msg, b, b.cursor);
1004}
1005void
1006text_input_buffer::parse_error(const char *msg,
1007 input_buffer &b,
1008 int loc)
1009{
752 int line_count = 1;
753 int line_start = 0;
1010 int line_count = 1;
1011 int line_start = 0;
754 int line_end = cursor;
755 for (int i=cursor ; i>0 ; --i)
1012 int line_end = loc;
1013 if (loc < 0 || loc > b.size)
756 {
1014 {
757 if (buffer[i] == '\n')
1015 return;
1016 }
1017 for (int i=loc ; i>0 ; --i)
1018 {
1019 if (b.buffer[i] == '\n')
758 {
759 line_count++;
760 if (line_start == 0)
761 {
762 line_start = i+1;
763 }
764 }
765 }
1020 {
1021 line_count++;
1022 if (line_start == 0)
1023 {
1024 line_start = i+1;
1025 }
1026 }
1027 }
766 for (int i=cursor+1 ; i<size ; ++i)
1028 for (int i=loc+1 ; i<b.size ; ++i)
767 {
1029 {
768 if (buffer[i] == '\n')
1030 if (b.buffer[i] == '\n')
769 {
770 line_end = i;
771 break;
772 }
773 }
1031 {
1032 line_end = i;
1033 break;
1034 }
1035 }
774 fprintf(stderr, "Error on line %d: %s\n", line_count, msg);
775 fwrite(&buffer[line_start], line_end-line_start, 1, stderr);
1036 fprintf(stderr, "Error at %s:%d:%d: %s\n", b.filename().c_str(), line_count, loc - line_start, msg);
1037 fwrite(&b.buffer[line_start], line_end-line_start, 1, stderr);
776 putc('\n', stderr);
1038 putc('\n', stderr);
777 for (int i=0 ; i<(cursor-line_start) ; ++i)
1039 for (int i=0 ; i<(loc-line_start) ; ++i)
778 {
1040 {
779 char c = (buffer[i+line_start] == '\t') ? '\t' : ' ';
1041 char c = (b.buffer[i+line_start] == '\t') ? '\t' : ' ';
780 putc(c, stderr);
781 }
782 putc('^', stderr);
783 putc('\n', stderr);
784}
785#ifndef NDEBUG
786void
787input_buffer::dump()
788{
789 fprintf(stderr, "Current cursor: %d\n", cursor);
790 fwrite(&buffer[cursor], size-cursor, 1, stderr);
791}
792#endif
793
1042 putc(c, stderr);
1043 }
1044 putc('^', stderr);
1045 putc('\n', stderr);
1046}
1047#ifndef NDEBUG
1048void
1049input_buffer::dump()
1050{
1051 fprintf(stderr, "Current cursor: %d\n", cursor);
1052 fwrite(&buffer[cursor], size-cursor, 1, stderr);
1053}
1054#endif
1055
794mmap_input_buffer::mmap_input_buffer(int fd) : input_buffer(0, 0)
1056
1057namespace
795{
1058{
796 struct stat sb;
797 if (fstat(fd, &sb))
1059/**
1060 * The source files are ASCII, so we provide a non-locale-aware version of
1061 * isalpha. This is a class so that it can be used with a template function
1062 * for parsing strings.
1063 */
1064struct is_alpha
1065{
1066 static inline bool check(const char c)
798 {
1067 {
799 perror("Failed to stat file");
1068 return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') &&
1069 (c <= 'Z'));
800 }
1070 }
801 size = sb.st_size;
802 buffer = (const char*)mmap(0, size, PROT_READ, MAP_PRIVATE |
803 MAP_PREFAULT_READ, fd, 0);
804 if (buffer == MAP_FAILED)
1071};
1072/**
1073 * Check whether a character is in the set allowed for node names. This is a
1074 * class so that it can be used with a template function for parsing strings.
1075 */
1076struct is_node_name_character
1077{
1078 static inline bool check(const char c)
805 {
1079 {
806 perror("Failed to mmap file");
807 exit(EXIT_FAILURE);
1080 switch(c)
1081 {
1082 default:
1083 return false;
1084 case 'a'...'z': case 'A'...'Z': case '0'...'9':
1085 case ',': case '.': case '+': case '-':
1086 case '_':
1087 return true;
1088 }
808 }
1089 }
1090};
1091/**
1092 * Check whether a character is in the set allowed for property names. This is
1093 * a class so that it can be used with a template function for parsing strings.
1094 */
1095struct is_property_name_character
1096{
1097 static inline bool check(const char c)
1098 {
1099 switch(c)
1100 {
1101 default:
1102 return false;
1103 case 'a'...'z': case 'A'...'Z': case '0'...'9':
1104 case ',': case '.': case '+': case '-':
1105 case '_': case '#':
1106 return true;
1107 }
1108 }
1109};
1110
1111template<class T>
1112string parse(text_input_buffer &s)
1113{
1114 std::vector<char> bytes;
1115 for (char c=*s ; T::check(c) ; c=*(++s))
1116 {
1117 bytes.push_back(c);
1118 }
1119 return string(bytes.begin(), bytes.end());
809}
810
1120}
1121
811mmap_input_buffer::~mmap_input_buffer()
1122}
1123
1124string
1125text_input_buffer::parse_node_name()
812{
1126{
813 if (buffer != 0)
1127 return parse<is_node_name_character>(*this);
1128}
1129
1130string
1131text_input_buffer::parse_property_name()
1132{
1133 return parse<is_property_name_character>(*this);
1134}
1135
1136string
1137text_input_buffer::parse_node_or_property_name(bool &is_property)
1138{
1139 if (is_property)
814 {
1140 {
815 munmap((void*)buffer, size);
1141 return parse_property_name();
816 }
1142 }
1143 std::vector<char> bytes;
1144 for (char c=*(*this) ; is_node_name_character::check(c) ; c=*(++(*this)))
1145 {
1146 bytes.push_back(c);
1147 }
1148 for (char c=*(*this) ; is_property_name_character::check(c) ; c=*(++(*this)))
1149 {
1150 bytes.push_back(c);
1151 is_property = true;
1152 }
1153 return string(bytes.begin(), bytes.end());
817}
818
1154}
1155
819stream_input_buffer::stream_input_buffer() : input_buffer(0, 0)
1156string
1157input_buffer::parse_to(char stop)
820{
1158{
821 int c;
822 while ((c = fgetc(stdin)) != EOF)
1159 std::vector<char> bytes;
1160 for (char c=*(*this) ; c != stop ; c=*(++(*this)))
823 {
1161 {
824 b.push_back(c);
1162 bytes.push_back(c);
825 }
1163 }
826 buffer = b.data();
827 size = b.size();
1164 return string(bytes.begin(), bytes.end());
828}
829
1165}
1166
1167string
1168text_input_buffer::parse_to(char stop)
1169{
1170 std::vector<char> bytes;
1171 for (char c=*(*this) ; c != stop ; c=*(++(*this)))
1172 {
1173 if (finished())
1174 {
1175 break;
1176 }
1177 bytes.push_back(c);
1178 }
1179 return string(bytes.begin(), bytes.end());
1180}
1181
1182char
1183text_input_buffer::peek()
1184{
1185 return (*input_stack.top())[1];
1186}
1187
1188std::unique_ptr<input_buffer>
1189input_buffer::buffer_for_file(const string &path, bool warn)
1190{
1191 if (path == "-")
1192 {
1193 std::unique_ptr<input_buffer> b(new stream_input_buffer());
1194 return b;
1195 }
1196 int source = open(path.c_str(), O_RDONLY);
1197 if (source == -1)
1198 {
1199 if (warn)
1200 {
1201 fprintf(stderr, "Unable to open file '%s'. %s\n", path.c_str(), strerror(errno));
1202 }
1203 return 0;
1204 }
1205 struct stat st;
1206 if (fstat(source, &st) == 0 && S_ISDIR(st.st_mode))
1207 {
1208 if (warn)
1209 {
1210 fprintf(stderr, "File %s is a directory\n", path.c_str());
1211 }
1212 close(source);
1213 return 0;
1214 }
1215 std::unique_ptr<input_buffer> b(new mmap_input_buffer(source, std::string(path)));
1216 close(source);
1217 return b;
1218}
1219
830} // namespace dtc
831
1220} // namespace dtc
1221