]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/wave/grammars/cpp_expression_value.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / wave / grammars / cpp_expression_value.hpp
1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 http://www.boost.org/
5
6 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
7 Software License, Version 1.0. (See accompanying file
8 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10
11 #if !defined(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)
12 #define CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED
13
14 #if defined (BOOST_SPIRIT_DEBUG)
15 #include <iostream>
16 #endif // defined(BOOST_SPIRIT_DEBUG)
17
18 #include <boost/wave/wave_config.hpp>
19 #include <boost/wave/grammars/cpp_value_error.hpp> // value_error
20
21 // this must occur after all of the includes and before any code appears
22 #ifdef BOOST_HAS_ABI_HEADERS
23 #include BOOST_ABI_PREFIX
24 #endif
25
26 ///////////////////////////////////////////////////////////////////////////////
27 namespace boost {
28 namespace wave {
29 namespace grammars {
30 namespace closures {
31
32 class closure_value;
33 inline bool as_bool(closure_value const& v);
34
35 ///////////////////////////////////////////////////////////////////////////////
36 //
37 // The closure_value class represents the closure type, which is used for the
38 // expression grammar.
39 //
40 // This class was introduced to allow the expression grammar to respect
41 // the numeric type of a numeric literal or expression result.
42 //
43 ///////////////////////////////////////////////////////////////////////////////
44 class closure_value {
45 public:
46
47 enum value_type {
48 is_int = 1,
49 is_uint = 2,
50 is_bool = 3
51 };
52
53 closure_value(value_error valid_ = error_noerror)
54 : type(is_int), valid(valid_)
55 { value.i = 0; }
56 explicit closure_value(int i, value_error valid_ = error_noerror)
57 : type(is_int), valid(valid_)
58 { value.i = i; }
59 explicit closure_value(unsigned int ui, value_error valid_ = error_noerror)
60 : type(is_uint), valid(valid_)
61 { value.ui = ui; }
62 explicit closure_value(int_literal_type i, value_error valid_ = error_noerror)
63 : type(is_int), valid(valid_)
64 { value.i = i; }
65 explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror)
66 : type(is_uint), valid(valid_)
67 { value.ui = ui; }
68 explicit closure_value(bool b, value_error valid_ = error_noerror)
69 : type(is_bool), valid(valid_)
70 { value.b = b; }
71
72 value_type get_type() const { return type; }
73 value_error is_valid() const { return valid; }
74
75 // explicit conversion
76 friend int_literal_type as_int(closure_value const& v)
77 {
78 switch (v.type) {
79 case is_uint: return v.value.ui;
80 case is_bool: return v.value.b ? 1 : 0;
81 case is_int: break;
82 }
83 return v.value.i;
84 }
85 friend uint_literal_type as_uint(closure_value const& v)
86 {
87 switch (v.type) {
88 case is_uint: return v.value.ui;
89 case is_bool: return v.value.b ? 1 : 0;
90 case is_int: break;
91 }
92 return v.value.i;
93 }
94 friend int_literal_type as_long(closure_value const& v)
95 {
96 switch (v.type) {
97 case is_uint: return v.value.ui;
98 case is_bool: return v.value.b ? 1 : 0;
99 case is_int: break;
100 }
101 return v.value.i;
102 }
103 friend uint_literal_type as_ulong(closure_value const& v)
104 {
105 switch (v.type) {
106 case is_uint: return v.value.ui;
107 case is_bool: return v.value.b ? 1 : 0;
108 case is_int: break;
109 }
110 return v.value.i;
111 }
112 friend bool as_bool(closure_value const& v)
113 {
114 switch (v.type) {
115 case is_uint: return v.value.ui != 0;
116 case is_bool: return v.value.b;
117 case is_int: break;
118 }
119 return v.value.i != 0.0;
120 }
121
122 // assignment
123 closure_value &operator= (closure_value const &rhs)
124 {
125 switch (rhs.get_type()) {
126 case is_int:
127 value.i = as_long(rhs);
128 type = is_int;
129 break;
130
131 case is_uint:
132 value.ui = as_ulong(rhs);
133 type = is_uint;
134 break;
135
136 case is_bool:
137 value.b = as_bool(rhs);
138 type = is_bool;
139 break;
140 }
141 valid = rhs.valid;
142 return *this;
143 }
144 closure_value &operator= (int rhs)
145 {
146 type = is_int;
147 value.i = rhs;
148 valid = error_noerror;
149 return *this;
150 }
151 closure_value &operator= (unsigned int rhs)
152 {
153 type = is_uint;
154 value.ui = rhs;
155 valid = error_noerror;
156 return *this;
157 }
158 closure_value &operator= (int_literal_type rhs)
159 {
160 type = is_int;
161 value.i = rhs;
162 valid = error_noerror;
163 return *this;
164 }
165 closure_value &operator= (uint_literal_type rhs)
166 {
167 type = is_uint;
168 value.ui = rhs;
169 valid = error_noerror;
170 return *this;
171 }
172 closure_value &operator= (bool rhs)
173 {
174 type = is_bool;
175 value.b = rhs;
176 valid = error_noerror;
177 return *this;
178 }
179
180 // arithmetics
181 closure_value &operator+= (closure_value const &rhs)
182 {
183 switch (type) {
184 case is_int:
185 switch(rhs.type) {
186 case is_bool:
187 {
188 int_literal_type result = value.i + as_long(rhs);
189 if ((rhs.value.i > 0L && value.i > result) ||
190 (rhs.value.i < 0L && value.i < result))
191 {
192 valid = error_integer_overflow;
193 }
194 else {
195 value.i = result;
196 }
197 }
198 break;
199
200 case is_int:
201 {
202 int_literal_type result = value.i + rhs.value.i;
203 if ((rhs.value.i > 0L && value.i > result) ||
204 (rhs.value.i < 0L && value.i < result))
205 {
206 valid = error_integer_overflow;
207 }
208 else {
209 value.i = result;
210 }
211 }
212 break;
213
214 case is_uint:
215 {
216 uint_literal_type result = value.ui + rhs.value.ui;
217 if (result < value.ui) {
218 valid = error_integer_overflow;
219 }
220 else {
221 value.ui = result;
222 type = is_uint;
223 }
224 }
225 break;
226 }
227 break;
228
229 case is_uint:
230 {
231 uint_literal_type result = value.ui + as_ulong(rhs);
232 if (result < value.ui) {
233 valid = error_integer_overflow;
234 }
235 else {
236 value.ui = result;
237 }
238 }
239 break;
240
241 case is_bool:
242 value.i = value.b + as_bool(rhs);
243 type = is_int;
244 }
245 valid = (value_error)(valid | rhs.valid);
246 return *this;
247 }
248 closure_value &operator-= (closure_value const &rhs)
249 {
250 switch (type) {
251 case is_int:
252 switch(rhs.type) {
253 case is_bool:
254 {
255 int_literal_type result = value.i - as_long(rhs);
256 if ((rhs.value.i > 0L && result > value.i) ||
257 (rhs.value.i < 0L && result < value.i))
258 {
259 valid = error_integer_overflow;
260 }
261 else {
262 value.i = result;
263 }
264 }
265 break;
266
267 case is_int:
268 {
269 int_literal_type result = value.i - rhs.value.i;
270 if ((rhs.value.i > 0L && result > value.i) ||
271 (rhs.value.i < 0L && result < value.i))
272 {
273 valid = error_integer_overflow;
274 }
275 else {
276 value.i = result;
277 }
278 }
279 break;
280
281 case is_uint:
282 {
283 uint_literal_type result = value.ui - rhs.value.ui;
284 if (result > value.ui) {
285 valid = error_integer_overflow;
286 }
287 else {
288 value.ui = result;
289 type = is_uint;
290 }
291 }
292 break;
293 }
294 break;
295
296 case is_uint:
297 switch(rhs.type) {
298 case is_bool:
299 {
300 uint_literal_type result = value.ui - as_ulong(rhs);
301 if (result > value.ui)
302 {
303 valid = error_integer_overflow;
304 }
305 else {
306 value.ui = result;
307 }
308 }
309 break;
310
311 case is_int:
312 {
313 uint_literal_type result = value.ui - rhs.value.i;
314 if ((rhs.value.i > 0L && result > value.ui) ||
315 (rhs.value.i < 0L && result < value.ui))
316 {
317 valid = error_integer_overflow;
318 }
319 else {
320 value.ui = result;
321 }
322 }
323 break;
324
325 case is_uint:
326 {
327 uint_literal_type result = value.ui - rhs.value.ui;
328 if (result > value.ui) {
329 valid = error_integer_overflow;
330 }
331 else {
332 value.ui = result;
333 }
334 }
335 break;
336 }
337 break;
338
339 case is_bool:
340 value.i = value.b - as_bool(rhs);
341 type = is_int;
342 }
343 valid = (value_error)(valid | rhs.valid);
344 return *this;
345 }
346 closure_value &operator*= (closure_value const &rhs)
347 {
348 switch (type) {
349 case is_int:
350 switch(rhs.type) {
351 case is_bool: value.i *= as_long(rhs); break;
352 case is_int:
353 {
354 int_literal_type result = value.i * rhs.value.i;
355 if (0 != value.i && 0 != rhs.value.i &&
356 (result / value.i != rhs.value.i ||
357 result / rhs.value.i != value.i)
358 )
359 {
360 valid = error_integer_overflow;
361 }
362 else {
363 value.i = result;
364 }
365 }
366 break;
367
368 case is_uint:
369 {
370 uint_literal_type result = value.ui * rhs.value.ui;
371 if (0 != value.ui && 0 != rhs.value.ui &&
372 (result / value.ui != rhs.value.ui ||
373 result / rhs.value.ui != value.ui)
374 )
375 {
376 valid = error_integer_overflow;
377 }
378 else {
379 value.ui = result;
380 type = is_uint;
381 }
382 }
383 break;
384 }
385 break;
386
387 case is_uint:
388 {
389 uint_literal_type rhs_val = as_ulong(rhs);
390 uint_literal_type result = value.ui * rhs_val;
391 if (0 != value.ui && 0 != rhs_val &&
392 (result / value.ui != rhs_val ||
393 result / rhs_val != value.ui)
394 )
395 {
396 valid = error_integer_overflow;
397 }
398 else {
399 value.ui = result;
400 type = is_uint;
401 }
402 }
403 break;
404
405 case is_bool:
406 switch (rhs.type) {
407 case is_int:
408 value.i = (value.b ? 1 : 0) * rhs.value.i;
409 type = is_int;
410 break;
411
412 case is_uint:
413 value.ui = (value.b ? 1 : 0) * rhs.value.ui;
414 type = is_uint;
415 break;
416
417 case is_bool:
418 value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0));
419 break;
420 }
421 }
422 valid = (value_error)(valid | rhs.valid);
423 return *this;
424 }
425 closure_value &operator/= (closure_value const &rhs)
426 {
427 switch (type) {
428 case is_int:
429 switch(rhs.type) {
430 case is_bool:
431 case is_int:
432 if (as_long(rhs) != 0) {
433 if (value.i == -value.i && -1 == rhs.value.i) {
434 // LONG_MIN / -1 on two's complement
435 valid = error_integer_overflow;
436 }
437 else {
438 value.i /= as_long(rhs);
439 }
440 }
441 else {
442 valid = error_division_by_zero; // division by zero
443 }
444 break;
445
446 case is_uint:
447 if (rhs.value.ui != 0) {
448 value.ui /= rhs.value.ui;
449 type = is_uint;
450 }
451 else {
452 valid = error_division_by_zero; // division by zero
453 }
454 break;
455 }
456 break;
457
458 case is_uint:
459 if (as_ulong(rhs) != 0)
460 value.ui /= as_ulong(rhs);
461 else
462 valid = error_division_by_zero; // division by zero
463 break;
464
465 case is_bool:
466 if (as_bool(rhs)) {
467 switch(rhs.type) {
468 case is_int:
469 value.i = (value.b ? 1 : 0) / rhs.value.i;
470 type = is_int;
471 break;
472
473 case is_uint:
474 value.i = (value.b ? 1 : 0) / rhs.value.ui;
475 type = is_int;
476 break;
477
478 case is_bool:
479 break;
480 }
481 }
482 else {
483 valid = error_division_by_zero; // division by zero
484 }
485 }
486 return *this;
487 }
488 closure_value &operator%= (closure_value const &rhs)
489 {
490 switch (type) {
491 case is_int:
492 switch(rhs.type) {
493 case is_bool:
494 case is_int:
495 if (as_long(rhs) != 0) {
496 if (value.i == -value.i && -1 == rhs.value.i) {
497 // LONG_MIN % -1 on two's complement
498 valid = error_integer_overflow;
499 }
500 else {
501 value.i %= as_long(rhs);
502 }
503 }
504 else {
505 valid = error_division_by_zero; // division by zero
506 }
507 break;
508
509 case is_uint:
510 if (rhs.value.ui != 0) {
511 value.ui %= rhs.value.ui;
512 type = is_uint;
513 }
514 else {
515 valid = error_division_by_zero; // division by zero
516 }
517 break;
518 }
519 break;
520
521 case is_uint:
522 if (as_ulong(rhs) != 0)
523 value.ui %= as_ulong(rhs);
524 else
525 valid = error_division_by_zero; // division by zero
526 break;
527
528 case is_bool:
529 if (as_bool(rhs)) {
530 switch(rhs.type) {
531 case is_int:
532 value.i = (value.b ? 1 : 0) % rhs.value.i;
533 type = is_int;
534 break;
535
536 case is_uint:
537 value.i = (value.b ? 1 : 0) % rhs.value.ui;
538 type = is_int;
539 break;
540
541 case is_bool:
542 break;
543 }
544 }
545 else {
546 valid = error_division_by_zero; // division by zero
547 }
548 }
549 return *this;
550 }
551
552 friend closure_value
553 operator- (closure_value const &rhs)
554 {
555 switch (rhs.type) {
556 case is_int:
557 {
558 int_literal_type value = as_long(rhs);
559 if (value != 0 && value == -value)
560 return closure_value(-value, error_integer_overflow);
561 return closure_value(-value, rhs.valid);
562 }
563
564 case is_bool: return closure_value(-as_long(rhs), rhs.valid);
565 case is_uint: break;
566 }
567
568 int_literal_type value = as_ulong(rhs);
569 if (value != 0 && value == -value)
570 return closure_value(-value, error_integer_overflow);
571 return closure_value(-value, rhs.valid);
572 }
573 friend closure_value
574 operator~ (closure_value const &rhs)
575 {
576 return closure_value(~as_ulong(rhs), rhs.valid);
577 }
578 friend closure_value
579 operator! (closure_value const &rhs)
580 {
581 switch (rhs.type) {
582 case is_int: return closure_value(!as_long(rhs), rhs.valid);
583 case is_bool: return closure_value(!as_bool(rhs), rhs.valid);
584 case is_uint: break;
585 }
586 return closure_value(!as_ulong(rhs), rhs.valid);
587 }
588
589 // comparison
590 friend closure_value
591 operator== (closure_value const &lhs, closure_value const &rhs)
592 {
593 bool cmp = false;
594 switch (lhs.type) {
595 case is_int:
596 switch(rhs.type) {
597 case is_bool: cmp = as_bool(lhs) == rhs.value.b; break;
598 case is_int: cmp = lhs.value.i == rhs.value.i; break;
599 case is_uint: cmp = lhs.value.ui == rhs.value.ui; break;
600 }
601 break;
602
603 case is_uint: cmp = lhs.value.ui == as_ulong(rhs); break;
604 case is_bool: cmp = lhs.value.b == as_bool(rhs); break;
605 }
606 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
607 }
608 friend closure_value
609 operator!= (closure_value const &lhs, closure_value const &rhs)
610 {
611 return closure_value(!as_bool(lhs == rhs), (value_error)(lhs.valid | rhs.valid));
612 }
613 friend closure_value
614 operator> (closure_value const &lhs, closure_value const &rhs)
615 {
616 bool cmp = false;
617 switch (lhs.type) {
618 case is_int:
619 switch(rhs.type) {
620 case is_bool: cmp = lhs.value.i > as_long(rhs); break;
621 case is_int: cmp = lhs.value.i > rhs.value.i; break;
622 case is_uint: cmp = lhs.value.ui > rhs.value.ui; break;
623 }
624 break;
625
626 case is_uint: cmp = lhs.value.ui > as_ulong(rhs); break;
627 case is_bool: cmp = lhs.value.b > as_bool(rhs); break;
628 }
629 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
630 }
631 friend closure_value
632 operator< (closure_value const &lhs, closure_value const &rhs)
633 {
634 bool cmp = false;
635 switch (lhs.type) {
636 case is_int:
637 switch(rhs.type) {
638 case is_bool: cmp = lhs.value.i < as_long(rhs); break;
639 case is_int: cmp = lhs.value.i < rhs.value.i; break;
640 case is_uint: cmp = lhs.value.ui < rhs.value.ui; break;
641 }
642 break;
643
644 case is_uint: cmp = lhs.value.ui < as_ulong(rhs); break;
645 case is_bool: cmp = as_bool(lhs) < as_bool(rhs); break;
646 }
647 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
648 }
649 friend closure_value
650 operator<= (closure_value const &lhs, closure_value const &rhs)
651 {
652 return closure_value(!as_bool(lhs > rhs), (value_error)(lhs.valid | rhs.valid));
653 }
654 friend closure_value
655 operator>= (closure_value const &lhs, closure_value const &rhs)
656 {
657 return closure_value(!as_bool(lhs < rhs), (value_error)(lhs.valid | rhs.valid));
658 }
659
660 closure_value &
661 operator<<= (closure_value const &rhs)
662 {
663 switch (type) {
664 case is_bool:
665 case is_int:
666 switch (rhs.type) {
667 case is_bool:
668 case is_int:
669 {
670 int_literal_type shift_by = as_long(rhs);
671
672 if (shift_by > 64)
673 shift_by = 64;
674 else if (shift_by < -64)
675 shift_by = -64;
676 value.i <<= shift_by;
677 }
678 break;
679
680 case is_uint:
681 {
682 uint_literal_type shift_by = as_ulong(rhs);
683
684 if (shift_by > 64)
685 shift_by = 64;
686 value.ui <<= shift_by;
687
688 // Note: The usual arithmetic conversions are not performed on
689 // bit shift operations.
690 }
691 break;
692 }
693 break;
694
695 case is_uint:
696 switch (rhs.type) {
697 case is_bool:
698 case is_int:
699 {
700 int_literal_type shift_by = as_long(rhs);
701
702 if (shift_by > 64)
703 shift_by = 64;
704 else if (shift_by < -64)
705 shift_by = -64;
706 value.ui <<= shift_by;
707 }
708 break;
709
710 case is_uint:
711 {
712 uint_literal_type shift_by = as_ulong(rhs);
713
714 if (shift_by > 64)
715 shift_by = 64;
716 value.ui <<= shift_by;
717 }
718 break;
719 }
720 }
721 valid = (value_error)(valid | rhs.valid);
722 return *this;
723 }
724
725 closure_value &
726 operator>>= (closure_value const &rhs)
727 {
728 switch (type) {
729 case is_bool:
730 case is_int:
731 switch (rhs.type) {
732 case is_bool:
733 case is_int:
734 {
735 int_literal_type shift_by = as_long(rhs);
736
737 if (shift_by > 64)
738 shift_by = 64;
739 else if (shift_by < -64)
740 shift_by = -64;
741 value.i >>= shift_by;
742 }
743 break;
744
745 case is_uint:
746 {
747 uint_literal_type shift_by = as_ulong(rhs);
748
749 if (shift_by > 64)
750 shift_by = 64;
751 value.ui >>= shift_by;
752
753 // Note: The usual arithmetic conversions are not performed on
754 // bit shift operations.
755 }
756 break;
757 }
758 break;
759
760 case is_uint:
761 switch (rhs.type) {
762 case is_bool:
763 case is_int:
764 {
765 int_literal_type shift_by = as_long(rhs);
766
767 if (shift_by > 64)
768 shift_by = 64;
769 else if (shift_by < -64)
770 shift_by = -64;
771 value.ui >>= shift_by;
772 }
773 break;
774
775 case is_uint:
776 {
777 uint_literal_type shift_by = as_ulong(rhs);
778
779 if (shift_by > 64)
780 shift_by = 64;
781 value.ui >>= shift_by;
782 }
783 break;
784 }
785 break;
786 }
787 valid = (value_error)(valid | rhs.valid);
788 return *this;
789 }
790
791 friend closure_value
792 operator|| (closure_value const &lhs, closure_value const &rhs)
793 {
794 bool result = as_bool(lhs) || as_bool(rhs);
795 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
796 }
797
798 friend closure_value
799 operator&& (closure_value const &lhs, closure_value const &rhs)
800 {
801 bool result = as_bool(lhs) && as_bool(rhs);
802 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
803 }
804
805 friend closure_value
806 operator| (closure_value const &lhs, closure_value const &rhs)
807 {
808 uint_literal_type result = as_ulong(lhs) | as_ulong(rhs);
809 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
810 }
811
812 friend closure_value
813 operator& (closure_value const &lhs, closure_value const &rhs)
814 {
815 uint_literal_type result = as_ulong(lhs) & as_ulong(rhs);
816 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
817 }
818
819 friend closure_value
820 operator^ (closure_value const &lhs, closure_value const &rhs)
821 {
822 uint_literal_type result = as_ulong(lhs) ^ as_ulong(rhs);
823 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
824 }
825
826 // handle the ?: operator
827 closure_value &
828 handle_questionmark(closure_value const &cond, closure_value const &val2)
829 {
830 switch (type) {
831 case is_int:
832 switch (val2.type) {
833 case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break;
834 case is_int: value.i = as_bool(cond) ? value.i : as_long(val2); break;
835 case is_uint:
836 value.ui = as_bool(cond) ? value.ui : as_ulong(val2);
837 type = is_uint; // changing type!
838 break;
839 }
840 break;
841
842 case is_uint: value.ui = as_bool(cond) ? value.ui : as_ulong(val2); break;
843 case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break;
844 }
845 valid = as_bool(cond) ? valid : val2.valid;
846 return *this;
847 }
848
849 #if defined (BOOST_SPIRIT_DEBUG)
850 friend std::ostream&
851 operator<< (std::ostream &o, closure_value const &val)
852 {
853 switch (val.type) {
854 case is_int: o << "int(" << as_long(val) << ")"; break;
855 case is_uint: o << "unsigned int(" << as_ulong(val) << ")"; break;
856 case is_bool: o << "bool(" << as_bool(val) << ")"; break;
857 }
858 return o;
859 }
860 #endif // defined(BOOST_SPIRIT_DEBUG)
861
862 private:
863 value_type type;
864 union {
865 int_literal_type i;
866 uint_literal_type ui;
867 bool b;
868 } value;
869 value_error valid;
870 };
871
872 ///////////////////////////////////////////////////////////////////////////////
873 } // namespace closures
874 } // namespace grammars
875 } // namespace wave
876 } // namespace boost
877
878 // the suffix header occurs after all of the code
879 #ifdef BOOST_HAS_ABI_HEADERS
880 #include BOOST_ABI_SUFFIX
881 #endif
882
883 #endif // !defined(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)