]> sourceware.org Git - systemtap.git/blame - staptree.cxx
Don't use -d on $netcat. Redirect from /dev/null instead.
[systemtap.git] / staptree.cxx
CommitLineData
56099f08 1// parse tree functions
0f16be72 2// Copyright (C) 2005-2008 Red Hat Inc.
69c68955
FCE
3//
4// This file is part of systemtap, and is free software. You can
5// redistribute it and/or modify it under the terms of the GNU General
6// Public License (GPL); either version 2, or (at your option) any
7// later version.
2f1a1aea 8
2b066ec1 9#include "config.h"
2f1a1aea
FCE
10#include "staptree.h"
11#include "parse.h"
72dbc915
FCE
12#include "util.h"
13
2f1a1aea 14#include <iostream>
56099f08 15#include <typeinfo>
d02548c0 16#include <sstream>
56099f08 17#include <cassert>
b2199bb3 18#include <cstring>
c3a3c0c9 19#include <vector>
66e00001 20#include <algorithm>
edc22ba9 21#include <cstring>
2f1a1aea 22
2b066ec1
FCE
23using namespace std;
24
2f1a1aea 25
c1d5f3f6 26
56099f08
FCE
27expression::expression ():
28 type (pe_unknown), tok (0)
29{
dff50e09 30}
56099f08
FCE
31
32
33expression::~expression ()
34{
35}
36
37
38statement::statement ():
39 tok (0)
40{
dff50e09 41}
56099f08
FCE
42
43
44statement::~statement ()
45{
46}
47
48
49symbol::symbol ():
50 referent (0)
51{
52}
53
54
55arrayindex::arrayindex ():
d02548c0 56 base (0)
56099f08
FCE
57{
58}
59
60
61functioncall::functioncall ():
62 referent (0)
63{
64}
65
66
67symboldecl::symboldecl ():
68 tok (0),
69 type (pe_unknown)
70{
dff50e09 71}
56099f08
FCE
72
73
74symboldecl::~symboldecl ()
75{
76}
77
a229fcd7
GH
78probe_point::probe_point (std::vector<component*> const & comps,
79 const token * t):
cbbe8080 80 components(comps), tok(t), optional (false), sufficient (false),
80342244 81 condition (0)
a229fcd7
GH
82{
83}
56099f08 84
1939ea32
FCE
85// NB: shallow-copy of compoonents & condition!
86probe_point::probe_point (const probe_point& pp):
87 components(pp.components), tok(pp.tok), optional (pp.optional), sufficient (pp.sufficient),
88 condition (pp.condition)
89{
90}
91
92
9c0c0e46 93probe_point::probe_point ():
80342244 94 tok (0), optional (false), sufficient (false), condition (0)
82919855
FCE
95{
96}
97
98
c1d5f3f6 99unsigned probe::last_probeidx = 0;
82919855 100probe::probe ():
5d23847d 101 body (0), tok (0)
9c0c0e46 102{
c1d5f3f6 103 this->name = string ("probe_") + lex_cast<string>(last_probeidx ++);
9c0c0e46
FCE
104}
105
106
107probe_point::component::component ():
108 arg (0)
109{
110}
111
112
dff50e09
FCE
113probe_point::component::component (std::string const & f, literal * a):
114 functor(f), arg(a)
a229fcd7
GH
115{
116}
117
118
2b066ec1 119vardecl::vardecl ():
ef474d24 120 arity (-1), maxsize(0), init(NULL)
56099f08
FCE
121{
122}
123
124
2b066ec1
FCE
125void
126vardecl::set_arity (int a)
56099f08 127{
d98d459c
GH
128 if (a < 0)
129 return;
8846477c 130
ef474d24 131 if ((arity != a && arity >= 0) || (a == 0 && maxsize > 0))
8846477c
FCE
132 throw semantic_error ("inconsistent arity", tok);
133
134 if (arity != a)
135 {
136 arity = a;
137 index_types.resize (arity);
138 for (int i=0; i<arity; i++)
139 index_types[i] = pe_unknown;
140 }
56099f08
FCE
141}
142
dff50e09 143bool
313b2f74
GH
144vardecl::compatible_arity (int a)
145{
ef474d24
JS
146 if (a == 0 && maxsize > 0)
147 return false;
d98d459c 148 if (arity == -1 || a == -1)
313b2f74
GH
149 return true;
150 return arity == a;
151}
152
56099f08
FCE
153
154functiondecl::functiondecl ():
155 body (0)
156{
157}
158
159
3a20432b 160literal_number::literal_number (int64_t v)
56099f08
FCE
161{
162 value = v;
163 type = pe_long;
164}
165
2f1a1aea 166
56099f08
FCE
167literal_string::literal_string (const string& v)
168{
169 value = v;
170 type = pe_string;
171}
172
173
174ostream&
175operator << (ostream& o, const exp_type& e)
176{
177 switch (e)
178 {
179 case pe_unknown: o << "unknown"; break;
180 case pe_long: o << "long"; break;
181 case pe_string: o << "string"; break;
182 case pe_stats: o << "stats"; break;
183 default: o << "???"; break;
184 }
185 return o;
186}
187
188
189// ------------------------------------------------------------------------
190// parse tree printing
191
cc9ee605 192ostream& operator << (ostream& o, const expression& k)
56099f08
FCE
193{
194 k.print (o);
195 return o;
196}
197
198
cc9ee605 199void literal_string::print (ostream& o) const
56099f08 200{
cc9ee605
FCE
201 o << '"';
202 for (unsigned i=0; i<value.size(); i++)
203 if (value[i] == '"') // or other escapeworthy characters?
204 o << '\\' << '"';
205 else
206 o << value[i];
207 o << '"';
56099f08
FCE
208}
209
f3c26ea5 210
cc9ee605 211void literal_number::print (ostream& o) const
56099f08
FCE
212{
213 o << value;
214}
215
216
cc9ee605 217void binary_expression::print (ostream& o) const
56099f08 218{
dff50e09
FCE
219 o << "(" << *left << ") "
220 << op
a9c62ac9 221 << " (" << *right << ")";
56099f08 222}
2f1a1aea
FCE
223
224
cc9ee605 225void unary_expression::print (ostream& o) const
2f1a1aea 226{
dff50e09 227 o << op << '(' << *operand << ")";
56099f08
FCE
228}
229
cc9ee605 230void array_in::print (ostream& o) const
69c68955
FCE
231{
232 o << "[";
233 for (unsigned i=0; i<operand->indexes.size(); i++)
234 {
235 if (i > 0) o << ", ";
236 operand->indexes[i]->print (o);
237 }
a9c62ac9
FCE
238 o << "] in ";
239 operand->base->print_indexable (o);
69c68955 240}
56099f08 241
cc9ee605 242void post_crement::print (ostream& o) const
56099f08 243{
dff50e09 244 o << '(' << *operand << ")" << op;
56099f08
FCE
245}
246
247
cc9ee605 248void ternary_expression::print (ostream& o) const
56099f08 249{
ae56fddd
FCE
250 o << "(" << *cond << ")?("
251 << *truevalue << "):("
dff50e09 252 << *falsevalue << ")";
56099f08
FCE
253}
254
255
cc9ee605 256void symbol::print (ostream& o) const
56099f08
FCE
257{
258 o << name;
259}
260
261
cc9ee605 262void target_symbol::print (std::ostream& o) const
d7f3e0c5
GH
263{
264 o << base_name;
265 for (unsigned i = 0; i < components.size(); ++i)
266 {
267 switch (components[i].first)
268 {
269 case comp_literal_array_index:
270 o << '[' << components[i].second << ']';
271 break;
246b383e 272 case comp_struct_member:
d7f3e0c5
GH
273 o << "->" << components[i].second;
274 break;
d7f3e0c5
GH
275 }
276 }
277}
278
279
cc9ee605 280void vardecl::print (ostream& o) const
56099f08
FCE
281{
282 o << name;
ef474d24
JS
283 if (maxsize > 0)
284 o << "[" << maxsize << "]";
bed7c0af 285 if (arity > 0 || index_types.size() > 0)
56099f08 286 o << "[...]";
9ba8c134
JS
287 if (init)
288 {
289 o << " = ";
290 init->print(o);
291 }
56099f08
FCE
292}
293
2f1a1aea 294
cc9ee605 295void vardecl::printsig (ostream& o) const
56099f08 296{
ef474d24
JS
297 o << name;
298 if (maxsize > 0)
299 o << "[" << maxsize << "]";
300 o << ":" << type;
56099f08 301 if (index_types.size() > 0)
2f1a1aea 302 {
56099f08
FCE
303 o << " [";
304 for (unsigned i=0; i<index_types.size(); i++)
305 o << (i>0 ? ", " : "") << index_types[i];
306 o << "]";
307 }
308}
309
310
cc9ee605 311void functiondecl::print (ostream& o) const
56099f08
FCE
312{
313 o << "function " << name << " (";
314 for (unsigned i=0; i<formal_args.size(); i++)
315 o << (i>0 ? ", " : "") << *formal_args[i];
316 o << ")" << endl;
317 body->print(o);
318}
319
320
cc9ee605 321void functiondecl::printsig (ostream& o) const
56099f08
FCE
322{
323 o << name << ":" << type << " (";
324 for (unsigned i=0; i<formal_args.size(); i++)
325 o << (i>0 ? ", " : "")
326 << *formal_args[i]
327 << ":"
328 << formal_args[i]->type;
329 o << ")";
330}
331
332
cc9ee605 333void arrayindex::print (ostream& o) const
56099f08 334{
a9c62ac9
FCE
335 base->print_indexable (o);
336 o << "[";
56099f08
FCE
337 for (unsigned i=0; i<indexes.size(); i++)
338 o << (i>0 ? ", " : "") << *indexes[i];
339 o << "]";
340}
341
342
cc9ee605 343void functioncall::print (ostream& o) const
56099f08
FCE
344{
345 o << function << "(";
346 for (unsigned i=0; i<args.size(); i++)
347 o << (i>0 ? ", " : "") << *args[i];
348 o << ")";
dff50e09 349}
56099f08
FCE
350
351
3cb17058
JS
352bool
353print_format::parse_print(const std::string &name,
32784362 354 bool &stream, bool &format, bool &delim, bool &newline, bool &_char)
3cb17058
JS
355{
356 const char *n = name.c_str();
357
358 stream = true;
32784362
MH
359 format = delim = newline = _char = false;
360
361 if (strcmp(n, "print_char") == 0)
362 {
363 _char = true;
364 return true;
365 }
3cb17058
JS
366
367 if (*n == 's')
368 {
369 stream = false;
370 ++n;
371 }
372
373 if (0 != strncmp(n, "print", 5))
374 return false;
375 n += 5;
376
377 if (*n == 'f')
378 {
379 format = true;
380 ++n;
381 }
382 else
383 {
384 if (*n == 'd')
385 {
386 delim = true;
387 ++n;
388 }
389
390 if (*n == 'l' && *(n+1) == 'n')
391 {
392 newline = true;
393 n += 2;
394 }
395 }
396
397 return (*n == '\0');
398}
399
400
dff50e09 401string
d02548c0
GH
402print_format::components_to_string(vector<format_component> const & components)
403{
404 ostringstream oss;
405
406 for (vector<format_component>::const_iterator i = components.begin();
407 i != components.end(); ++i)
408 {
409
410 assert (i->type != conv_unspecified);
411
412 if (i->type == conv_literal)
413 {
414 assert(!i->literal_string.empty());
415 for (string::const_iterator j = i->literal_string.begin();
416 j != i->literal_string.end(); ++j)
417 {
c4bb5be2 418 // See also: c_unparser::visit_literal_string and lex_cast_qstring
d02548c0
GH
419 if (*j == '%')
420 oss << '%';
c4bb5be2
FCE
421 else if(*j == '"')
422 oss << '\\';
d02548c0
GH
423 oss << *j;
424 }
425 }
426 else
427 {
428 oss << '%';
429
430 if (i->flags & static_cast<unsigned long>(fmt_flag_zeropad))
431 oss << '0';
432
433 if (i->flags & static_cast<unsigned long>(fmt_flag_plus))
434 oss << '+';
435
436 if (i->flags & static_cast<unsigned long>(fmt_flag_space))
437 oss << ' ';
438
439 if (i->flags & static_cast<unsigned long>(fmt_flag_left))
440 oss << '-';
441
442 if (i->flags & static_cast<unsigned long>(fmt_flag_special))
443 oss << '#';
444
34201621
DB
445 if (i->widthtype == width_dynamic)
446 oss << '*';
447 else if (i->widthtype != width_unspecified && i->width > 0)
d02548c0
GH
448 oss << i->width;
449
34201621
DB
450 if (i->prectype == prec_dynamic)
451 oss << ".*";
452 else if (i->prectype != prec_unspecified && i->precision > 0)
d02548c0
GH
453 oss << '.' << i->precision;
454
dff50e09 455 switch (i->type)
dc0b623a
MH
456 {
457 case conv_binary:
458 oss << "b";
459 break;
460
fecccf83
EB
461 case conv_char:
462 oss << "llc";
463 break;
464
d02548c0
GH
465 case conv_signed_decimal:
466 oss << "lld";
467 break;
468
469 case conv_unsigned_decimal:
470 oss << "llu";
471 break;
472
473 case conv_unsigned_octal:
474 oss << "llo";
475 break;
476
58cf0567
MH
477 case conv_unsigned_ptr:
478 oss << "p";
479 break;
480
d02548c0
GH
481 case conv_unsigned_uppercase_hex:
482 oss << "llX";
483 break;
484
485 case conv_unsigned_lowercase_hex:
486 oss << "llx";
487 break;
488
489 case conv_string:
490 oss << 's';
491 break;
dff50e09 492
34201621
DB
493 case conv_memory:
494 oss << 'm';
495 break;
dff50e09 496
d02548c0
GH
497 default:
498 break;
499 }
500 }
501 }
502 return oss.str ();
503}
dff50e09
FCE
504
505vector<print_format::format_component>
d02548c0
GH
506print_format::string_to_components(string const & str)
507{
508 format_component curr;
509 vector<format_component> res;
510
d02548c0
GH
511 curr.clear();
512
513 string::const_iterator i = str.begin();
dff50e09 514
d02548c0
GH
515 while (i != str.end())
516 {
07c17d67 517 if (*i != '%')
d02548c0 518 {
07c17d67
GH
519 assert (curr.type == conv_unspecified || curr.type == conv_literal);
520 curr.type = conv_literal;
dc0b623a 521 curr.literal_string += *i;
d02548c0 522 ++i;
07c17d67
GH
523 continue;
524 }
525 else if (i+1 == str.end() || *(i+1) == '%')
526 {
527 assert(*i == '%');
528 // *i == '%' and *(i+1) == '%'; append only one '%' to the literal string
529 assert (curr.type == conv_unspecified || curr.type == conv_literal);
530 curr.type = conv_literal;
531 curr.literal_string += '%';
2a99f48f 532 i += 2;
07c17d67
GH
533 continue;
534 }
dff50e09 535 else
07c17d67
GH
536 {
537 assert(*i == '%');
538 if (curr.type != conv_unspecified)
d02548c0 539 {
07c17d67
GH
540 // Flush any component we were previously accumulating
541 assert (curr.type == conv_literal);
542 res.push_back(curr);
543 curr.clear();
544 }
545 }
546 ++i;
dff50e09 547
07c17d67
GH
548 if (i == str.end())
549 break;
d02548c0 550
dff50e09 551 // Now we are definitely parsing a conversion.
d898100a 552 // Begin by parsing flags (which are optional).
d02548c0 553
07c17d67
GH
554 switch (*i)
555 {
556 case '0':
557 curr.flags |= static_cast<unsigned long>(fmt_flag_zeropad);
558 ++i;
d02548c0 559 break;
dff50e09 560
07c17d67
GH
561 case '+':
562 curr.flags |= static_cast<unsigned long>(fmt_flag_plus);
563 ++i;
d02548c0 564 break;
dff50e09 565
07c17d67
GH
566 case '-':
567 curr.flags |= static_cast<unsigned long>(fmt_flag_left);
568 ++i;
d02548c0 569 break;
dff50e09 570
07c17d67
GH
571 case ' ':
572 curr.flags |= static_cast<unsigned long>(fmt_flag_space);
573 ++i;
574 break;
dff50e09 575
07c17d67
GH
576 case '#':
577 curr.flags |= static_cast<unsigned long>(fmt_flag_special);
578 ++i;
579 break;
dc0b623a 580
07c17d67
GH
581 default:
582 break;
583 }
d02548c0 584
34201621
DB
585 if (i == str.end())
586 break;
587
07c17d67 588 // Parse optional width
34201621 589 if (*i == '*')
07c17d67 590 {
34201621 591 curr.widthtype = width_dynamic;
07c17d67
GH
592 ++i;
593 }
34201621
DB
594 else if (isdigit(*i))
595 {
596 curr.widthtype = width_static;
597 curr.width = 0;
598 do
599 {
600 curr.width *= 10;
601 curr.width += (*i - '0');
602 ++i;
603 }
604 while (i != str.end() && isdigit(*i));
605 }
d02548c0 606
07c17d67
GH
607 if (i == str.end())
608 break;
d02548c0 609
07c17d67
GH
610 // Parse optional precision
611 if (*i == '.')
612 {
613 ++i;
614 if (i == str.end())
615 break;
34201621 616 if (*i == '*')
07c17d67 617 {
34201621 618 curr.prectype = prec_dynamic;
d02548c0 619 ++i;
07c17d67 620 }
34201621
DB
621 else if (isdigit(*i))
622 {
623 curr.prectype = prec_static;
624 curr.precision = 0;
625 do
626 {
627 curr.precision *= 10;
628 curr.precision += (*i - '0');
629 ++i;
630 }
631 while (i != str.end() && isdigit(*i));
632 }
07c17d67 633 }
d02548c0 634
07c17d67
GH
635 if (i == str.end())
636 break;
d02548c0 637
fecccf83 638 // Parse the actual conversion specifier (bcsmdioupxXn)
07c17d67
GH
639 switch (*i)
640 {
641 // Valid conversion types
dc0b623a
MH
642 case 'b':
643 curr.type = conv_binary;
644 break;
dff50e09 645
fecccf83
EB
646 case 'c':
647 curr.type = conv_char;
648 break;
649
07c17d67
GH
650 case 's':
651 curr.type = conv_string;
652 break;
dff50e09 653
34201621
DB
654 case 'm':
655 curr.type = conv_memory;
656 break;
dff50e09 657
07c17d67
GH
658 case 'd':
659 case 'i':
660 curr.type = conv_signed_decimal;
661 break;
dff50e09 662
07c17d67
GH
663 case 'o':
664 curr.type = conv_unsigned_octal;
665 break;
dff50e09 666
07c17d67
GH
667 case 'u':
668 curr.type = conv_unsigned_decimal;
669 break;
dff50e09 670
58cf0567
MH
671 case 'p':
672 curr.type = conv_unsigned_ptr;
673 break;
674
07c17d67
GH
675 case 'X':
676 curr.type = conv_unsigned_uppercase_hex;
677 break;
dff50e09 678
07c17d67
GH
679 case 'x':
680 curr.type = conv_unsigned_lowercase_hex;
681 break;
dc0b623a 682
07c17d67 683 default:
d02548c0
GH
684 break;
685 }
dff50e09 686
07c17d67 687 if (curr.type == conv_unspecified)
a9c62ac9 688 throw parse_error("invalid or missing conversion specifier");
dff50e09 689
07c17d67 690 ++i;
dc0b623a 691 res.push_back(curr);
dff50e09 692 curr.clear();
d02548c0
GH
693 }
694
07c17d67
GH
695 // If there's a remaining partly-composed conversion, fail.
696 if (!curr.is_empty())
697 {
698 if (curr.type == conv_literal)
dff50e09 699 res.push_back(curr);
07c17d67 700 else
a9c62ac9 701 throw parse_error("trailing incomplete print format conversion");
07c17d67 702 }
d02548c0
GH
703
704 return res;
705}
706
707
708void print_format::print (ostream& o) const
709{
3cb17058 710 o << tok->content << "(";
d02548c0 711 if (print_with_format)
3cb17058
JS
712 o << lex_cast_qstring (raw_components);
713 if (print_with_delim)
714 o << lex_cast_qstring (delimiter.literal_string);
a9c62ac9
FCE
715 if (hist)
716 hist->print(o);
d02548c0
GH
717 for (vector<expression*>::const_iterator i = args.begin();
718 i != args.end(); ++i)
719 {
3cb17058 720 if (i != args.begin() || print_with_format || print_with_delim)
d02548c0
GH
721 o << ", ";
722 (*i)->print(o);
723 }
724 o << ")";
725}
726
727void stat_op::print (ostream& o) const
728{
729 o << '@';
730 switch (ctype)
731 {
732 case sc_average:
733 o << "avg(";
734 break;
735
736 case sc_count:
737 o << "count(";
738 break;
739
740 case sc_sum:
741 o << "sum(";
742 break;
743
744 case sc_min:
745 o << "min(";
746 break;
dff50e09 747
d02548c0
GH
748 case sc_max:
749 o << "max(";
750 break;
751 }
752 stat->print(o);
753 o << ")";
754}
755
dff50e09 756void
d02548c0
GH
757hist_op::print (ostream& o) const
758{
759 o << '@';
760 switch (htype)
761 {
762 case hist_linear:
763 assert(params.size() == 3);
764 o << "hist_linear(";
765 stat->print(o);
766 for (size_t i = 0; i < params.size(); ++i)
767 {
768 o << ", " << params[i];
769 }
770 o << ")";
771 break;
772
773 case hist_log:
e38723d2 774 assert(params.size() == 0);
d02548c0
GH
775 o << "hist_log(";
776 stat->print(o);
d02548c0
GH
777 o << ")";
778 break;
779 }
780}
781
cc9ee605 782ostream& operator << (ostream& o, const statement& k)
56099f08
FCE
783{
784 k.print (o);
785 return o;
786}
787
788
cc9ee605 789void embeddedcode::print (ostream &o) const
54dfabe9
FCE
790{
791 o << "%{";
792 o << code;
793 o << "%}";
794}
795
cc9ee605 796void block::print (ostream& o) const
56099f08
FCE
797{
798 o << "{" << endl;
799 for (unsigned i=0; i<statements.size(); i++)
69c68955 800 o << *statements [i] << endl;
bb2e3076 801 o << "}";
56099f08
FCE
802}
803
ba6f838d
FCE
804block::block (statement* car, statement* cdr)
805{
806 statements.push_back(car);
807 statements.push_back(cdr);
808 this->tok = car->tok;
809}
810
811
56099f08 812
cc9ee605 813void for_loop::print (ostream& o) const
56099f08 814{
f3c26ea5 815 o << "for (";
cbfbbf69 816 if (init) init->print (o);
f3c26ea5
FCE
817 o << "; ";
818 cond->print (o);
819 o << "; ";
cbfbbf69 820 if (incr) incr->print (o);
bb2e3076 821 o << ") ";
f3c26ea5 822 block->print (o);
56099f08
FCE
823}
824
825
cc9ee605 826void foreach_loop::print (ostream& o) const
69c68955
FCE
827{
828 o << "foreach ([";
829 for (unsigned i=0; i<indexes.size(); i++)
830 {
831 if (i > 0) o << ", ";
832 indexes[i]->print (o);
93484556
FCE
833 if (sort_direction != 0 && sort_column == i+1)
834 o << (sort_direction > 0 ? "+" : "-");
69c68955 835 }
a9c62ac9
FCE
836 o << "] in ";
837 base->print_indexable (o);
93484556
FCE
838 if (sort_direction != 0 && sort_column == 0)
839 o << (sort_direction > 0 ? "+" : "-");
27f21e8c
DS
840 if (limit)
841 {
842 o << " limit ";
843 limit->print (o);
844 }
93484556 845 o << ") ";
69c68955
FCE
846 block->print (o);
847}
848
849
cc9ee605 850void null_statement::print (ostream& o) const
56099f08 851{
dff50e09 852 o << ";";
56099f08
FCE
853}
854
855
cc9ee605 856void expr_statement::print (ostream& o) const
56099f08
FCE
857{
858 o << *value;
859}
860
861
cc9ee605 862void return_statement::print (ostream& o) const
56099f08
FCE
863{
864 o << "return " << *value;
865}
866
867
cc9ee605 868void delete_statement::print (ostream& o) const
56099f08
FCE
869{
870 o << "delete " << *value;
871}
872
cc9ee605 873void next_statement::print (ostream& o) const
f3c26ea5
FCE
874{
875 o << "next";
876}
877
cc9ee605 878void break_statement::print (ostream& o) const
f3c26ea5
FCE
879{
880 o << "break";
881}
882
cc9ee605 883void continue_statement::print (ostream& o) const
f3c26ea5
FCE
884{
885 o << "continue";
886}
56099f08 887
cc9ee605 888void if_statement::print (ostream& o) const
56099f08 889{
bb2e3076 890 o << "if (" << *condition << ") "
56099f08
FCE
891 << *thenblock << endl;
892 if (elseblock)
893 o << "else " << *elseblock << endl;
894}
895
896
cc9ee605 897void stapfile::print (ostream& o) const
56099f08
FCE
898{
899 o << "# file " << name << endl;
900
54dfabe9
FCE
901 for (unsigned i=0; i<embeds.size(); i++)
902 embeds[i]->print (o);
903
bed7c0af
FCE
904 for (unsigned i=0; i<globals.size(); i++)
905 {
906 o << "global ";
907 globals[i]->print (o);
908 o << endl;
909 }
910
20c6c071
GH
911 for (unsigned i=0; i<aliases.size(); i++)
912 {
913 aliases[i]->print (o);
914 o << endl;
915 }
916
bed7c0af 917 for (unsigned i=0; i<probes.size(); i++)
56099f08
FCE
918 {
919 probes[i]->print (o);
920 o << endl;
921 }
922
923 for (unsigned j = 0; j < functions.size(); j++)
924 {
925 functions[j]->print (o);
926 o << endl;
927 }
928}
929
930
cc9ee605 931void probe::print (ostream& o) const
56099f08
FCE
932{
933 o << "probe ";
40a1cb62
FCE
934 printsig (o);
935 o << *body;
936}
937
938
cc9ee605 939void probe::printsig (ostream& o) const
40a1cb62 940{
77b2151e
DB
941 const probe_alias *alias = get_alias ();
942 if (alias)
943 {
944 alias->printsig (o);
945 return;
946 }
dff50e09 947
9c0c0e46 948 for (unsigned i=0; i<locations.size(); i++)
56099f08 949 {
65aeaea0 950 if (i > 0) o << ",";
9c0c0e46 951 locations[i]->print (o);
56099f08 952 }
56099f08
FCE
953}
954
955
c3a3c0c9 956void
2c5a19c6 957probe::collect_derivation_chain (std::vector<probe*> &probes_list)
c3a3c0c9 958{
2c5a19c6 959 probes_list.push_back(this);
c3a3c0c9
WC
960}
961
962
cc9ee605 963void probe_point::print (ostream& o) const
56099f08 964{
9c0c0e46
FCE
965 for (unsigned i=0; i<components.size(); i++)
966 {
967 if (i>0) o << ".";
968 probe_point::component* c = components[i];
969 o << c->functor;
970 if (c->arg)
971 o << "(" << *c->arg << ")";
972 }
d898100a
FCE
973 if (sufficient)
974 o << "!";
975 else if (optional) // sufficient implies optional
6e3347a9 976 o << "?";
cbbe8080
MH
977 if (condition)
978 o<< " if (" << *condition << ")";
c3a3c0c9
WC
979}
980
981string probe_point::str ()
982{
983 ostringstream o;
984 for (unsigned i=0; i<components.size(); i++)
985 {
986 if (i>0) o << ".";
987 probe_point::component* c = components[i];
988 o << c->functor;
989 if (c->arg)
990 o << "(" << *c->arg << ")";
991 }
d898100a
FCE
992 if (sufficient)
993 o << "!";
994 else if (optional) // sufficient implies optional
c3a3c0c9 995 o << "?";
cbbe8080
MH
996 if (condition)
997 o<< " if (" << *condition << ")";
c3a3c0c9 998 return o.str();
56099f08
FCE
999}
1000
cc9ee605 1001
20c6c071
GH
1002probe_alias::probe_alias(std::vector<probe_point*> const & aliases):
1003 probe (), alias_names (aliases)
1004{
1005}
1006
cc9ee605 1007void probe_alias::printsig (ostream& o) const
20c6c071
GH
1008{
1009 for (unsigned i=0; i<alias_names.size(); i++)
1010 {
1011 o << (i>0 ? " = " : "");
1012 alias_names[i]->print (o);
1013 }
5227f1ea 1014 o << " = ";
20c6c071
GH
1015 for (unsigned i=0; i<locations.size(); i++)
1016 {
d898100a 1017 if (i > 0) o << ", ";
20c6c071
GH
1018 locations[i]->print (o);
1019 }
1020}
1021
56099f08 1022
cc9ee605 1023ostream& operator << (ostream& o, const probe_point& k)
82919855
FCE
1024{
1025 k.print (o);
1026 return o;
1027}
1028
1029
cc9ee605 1030ostream& operator << (ostream& o, const symboldecl& k)
56099f08
FCE
1031{
1032 k.print (o);
1033 return o;
1034}
1035
1036
82919855
FCE
1037
1038// ------------------------------------------------------------------------
1039// visitors
1040
1041
1042void
1043block::visit (visitor* u)
1044{
1045 u->visit_block (this);
1046}
1047
54dfabe9
FCE
1048
1049void
1050embeddedcode::visit (visitor* u)
1051{
1052 u->visit_embeddedcode (this);
1053}
1054
1055
82919855
FCE
1056void
1057for_loop::visit (visitor* u)
1058{
1059 u->visit_for_loop (this);
1060}
1061
69c68955
FCE
1062void
1063foreach_loop::visit (visitor* u)
1064{
1065 u->visit_foreach_loop (this);
1066}
1067
82919855
FCE
1068void
1069null_statement::visit (visitor* u)
1070{
1071 u->visit_null_statement (this);
1072}
1073
1074void
1075expr_statement::visit (visitor* u)
1076{
1077 u->visit_expr_statement (this);
1078}
1079
1080void
1081return_statement::visit (visitor* u)
1082{
1083 u->visit_return_statement (this);
1084}
1085
1086void
1087delete_statement::visit (visitor* u)
1088{
d7f3e0c5 1089 u->push_active_lvalue (this->value);
82919855 1090 u->visit_delete_statement (this);
d7f3e0c5 1091 u->pop_active_lvalue ();
82919855
FCE
1092}
1093
1094void
1095if_statement::visit (visitor* u)
1096{
1097 u->visit_if_statement (this);
1098}
1099
f3c26ea5
FCE
1100void
1101next_statement::visit (visitor* u)
1102{
1103 u->visit_next_statement (this);
1104}
1105
1106void
1107break_statement::visit (visitor* u)
1108{
1109 u->visit_break_statement (this);
1110}
1111
1112void
1113continue_statement::visit (visitor* u)
1114{
1115 u->visit_continue_statement (this);
1116}
1117
82919855
FCE
1118void
1119literal_string::visit(visitor* u)
1120{
1121 u->visit_literal_string (this);
1122}
1123
1124void
1125literal_number::visit(visitor* u)
1126{
1127 u->visit_literal_number (this);
1128}
1129
1130void
1131binary_expression::visit (visitor* u)
1132{
1133 u->visit_binary_expression (this);
1134}
1135
1136void
1137unary_expression::visit (visitor* u)
1138{
1139 u->visit_unary_expression (this);
1140}
1141
1142void
1143pre_crement::visit (visitor* u)
1144{
d7f3e0c5 1145 u->push_active_lvalue (this->operand);
82919855 1146 u->visit_pre_crement (this);
d7f3e0c5 1147 u->pop_active_lvalue ();
82919855
FCE
1148}
1149
1150void
1151post_crement::visit (visitor* u)
1152{
d7f3e0c5 1153 u->push_active_lvalue (this->operand);
82919855 1154 u->visit_post_crement (this);
d7f3e0c5 1155 u->pop_active_lvalue ();
82919855
FCE
1156}
1157
1158void
1159logical_or_expr::visit (visitor* u)
1160{
1161 u->visit_logical_or_expr (this);
1162}
1163
1164void
1165logical_and_expr::visit (visitor* u)
1166{
1167 u->visit_logical_and_expr (this);
1168}
1169
1170void
1171array_in::visit (visitor* u)
1172{
1173 u->visit_array_in (this);
1174}
1175
1176void
1177comparison::visit (visitor* u)
1178{
1179 u->visit_comparison (this);
1180}
1181
1182void
1183concatenation::visit (visitor* u)
1184{
1185 u->visit_concatenation (this);
1186}
1187
82919855
FCE
1188void
1189ternary_expression::visit (visitor* u)
1190{
1191 u->visit_ternary_expression (this);
1192}
1193
1194void
1195assignment::visit (visitor* u)
1196{
d7f3e0c5 1197 u->push_active_lvalue (this->left);
82919855 1198 u->visit_assignment (this);
d7f3e0c5 1199 u->pop_active_lvalue ();
82919855
FCE
1200}
1201
1202void
1203symbol::visit (visitor* u)
1204{
1205 u->visit_symbol (this);
1206}
1207
dff50e09 1208void
d7f3e0c5
GH
1209target_symbol::visit (visitor* u)
1210{
1211 u->visit_target_symbol(this);
1212}
1213
82919855
FCE
1214void
1215arrayindex::visit (visitor* u)
1216{
1217 u->visit_arrayindex (this);
1218}
1219
1220void
1221functioncall::visit (visitor* u)
1222{
1223 u->visit_functioncall (this);
1224}
1225
d02548c0
GH
1226void
1227print_format::visit (visitor *u)
1228{
1229 u->visit_print_format (this);
1230}
1231
1232void
1233stat_op::visit (visitor *u)
1234{
1235 u->visit_stat_op (this);
1236}
1237
1238void
1239hist_op::visit (visitor *u)
1240{
1241 u->visit_hist_op (this);
1242}
1243
dff50e09 1244void
d02548c0
GH
1245indexable::print_indexable (std::ostream& o) const
1246{
1247 const symbol *sym;
1248 const hist_op *hist;
1249 classify_const_indexable(this, sym, hist);
1250 if (sym)
1251 sym->print (o);
1252 else
1253 {
1254 assert (hist);
1255 hist->print (o);
dff50e09 1256 }
d02548c0
GH
1257}
1258
dff50e09 1259void
d02548c0
GH
1260indexable::visit_indexable (visitor* u)
1261{
1262 symbol *sym;
1263 hist_op *hist;
1264 classify_indexable(this, sym, hist);
1265 if (sym)
1266 sym->visit (u);
1267 else
1268 {
1269 assert (hist);
1270 hist->visit (u);
1271 }
1272}
1273
1274
dff50e09 1275bool
d02548c0
GH
1276indexable::is_symbol(symbol *& sym_out)
1277{
1278 sym_out = NULL;
1279 return false;
1280}
1281
dff50e09 1282bool
d02548c0
GH
1283indexable::is_hist_op(hist_op *& hist_out)
1284{
1285 hist_out = NULL;
1286 return false;
1287}
1288
dff50e09 1289bool
d02548c0
GH
1290indexable::is_const_symbol(const symbol *& sym_out) const
1291{
1292 sym_out = NULL;
1293 return false;
1294}
1295
dff50e09 1296bool
d02548c0
GH
1297indexable::is_const_hist_op(const hist_op *& hist_out) const
1298{
1299 hist_out = NULL;
1300 return false;
1301}
1302
dff50e09 1303bool
d02548c0
GH
1304symbol::is_symbol(symbol *& sym_out)
1305{
1306 sym_out = this;
1307 return true;
1308}
1309
dff50e09 1310bool
d02548c0
GH
1311symbol::is_const_symbol(const symbol *& sym_out) const
1312{
1313 sym_out = this;
1314 return true;
1315}
1316
1317const token *
1318symbol::get_tok() const
1319{
1320 return tok;
1321}
1322
dff50e09 1323bool
d02548c0
GH
1324hist_op::is_hist_op(hist_op *& hist_out)
1325{
1326 hist_out = this;
1327 return true;
1328}
1329
dff50e09 1330bool
d02548c0
GH
1331hist_op::is_const_hist_op(const hist_op *& hist_out) const
1332{
1333 hist_out = this;
1334 return true;
1335}
1336
1337const token *
1338hist_op::get_tok() const
1339{
1340 return tok;
1341}
1342
1343void
1344classify_indexable(indexable* ix,
1345 symbol *& array_out,
dff50e09 1346 hist_op *& hist_out)
d02548c0
GH
1347{
1348 array_out = NULL;
1349 hist_out = NULL;
1350 if (!(ix->is_symbol (array_out) || ix->is_hist_op (hist_out)))
1351 throw semantic_error("Expecting symbol or histogram operator", ix->get_tok());
1352 if (ix && !(hist_out || array_out))
1353 throw semantic_error("Failed to classify indexable", ix->get_tok());
1354}
1355
1356void
1357classify_const_indexable(const indexable* ix,
1358 const symbol *& array_out,
dff50e09 1359 const hist_op *& hist_out)
d02548c0
GH
1360{
1361 array_out = NULL;
1362 hist_out = NULL;
1363 if (!(ix->is_const_symbol(array_out) || ix->is_const_hist_op(hist_out)))
1364 throw semantic_error("Expecting symbol or histogram operator", ix->get_tok());
1365}
1366
d7f3e0c5
GH
1367// ------------------------------------------------------------------------
1368
dff50e09 1369bool
d7f3e0c5
GH
1370visitor::is_active_lvalue(expression *e)
1371{
1372 for (unsigned i = 0; i < active_lvalues.size(); ++i)
1373 {
1374 if (active_lvalues[i] == e)
1375 return true;
1376 }
1377 return false;
1378}
1379
dff50e09 1380void
d7f3e0c5
GH
1381visitor::push_active_lvalue(expression *e)
1382{
1383 active_lvalues.push_back(e);
1384}
1385
dff50e09 1386void
d7f3e0c5
GH
1387visitor::pop_active_lvalue()
1388{
1389 assert(!active_lvalues.empty());
1390 active_lvalues.pop_back();
1391}
1392
1393
82919855
FCE
1394
1395// ------------------------------------------------------------------------
1396
1397void
54dfabe9 1398traversing_visitor::visit_block (block* s)
82919855
FCE
1399{
1400 for (unsigned i=0; i<s->statements.size(); i++)
1401 s->statements[i]->visit (this);
1402}
1403
1404void
78f6bba6 1405traversing_visitor::visit_embeddedcode (embeddedcode*)
54dfabe9
FCE
1406{
1407}
1408
1409void
78f6bba6 1410traversing_visitor::visit_null_statement (null_statement*)
82919855
FCE
1411{
1412}
1413
1414void
54dfabe9 1415traversing_visitor::visit_expr_statement (expr_statement* s)
82919855
FCE
1416{
1417 s->value->visit (this);
1418}
1419
1420void
1421traversing_visitor::visit_if_statement (if_statement* s)
1422{
1423 s->condition->visit (this);
1424 s->thenblock->visit (this);
2b066ec1
FCE
1425 if (s->elseblock)
1426 s->elseblock->visit (this);
82919855
FCE
1427}
1428
1429void
1430traversing_visitor::visit_for_loop (for_loop* s)
1431{
cbfbbf69 1432 if (s->init) s->init->visit (this);
82919855 1433 s->cond->visit (this);
cbfbbf69 1434 if (s->incr) s->incr->visit (this);
82919855
FCE
1435 s->block->visit (this);
1436}
1437
69c68955
FCE
1438void
1439traversing_visitor::visit_foreach_loop (foreach_loop* s)
1440{
dff50e09 1441 symbol *array = NULL;
71572ba8
GH
1442 hist_op *hist = NULL;
1443 classify_indexable (s->base, array, hist);
1444 if (array)
1445 array->visit(this);
1446 else
1447 hist->visit(this);
1448
69c68955
FCE
1449 for (unsigned i=0; i<s->indexes.size(); i++)
1450 s->indexes[i]->visit (this);
27f21e8c
DS
1451
1452 if (s->limit)
1453 s->limit->visit (this);
1454
69c68955
FCE
1455 s->block->visit (this);
1456}
1457
82919855
FCE
1458void
1459traversing_visitor::visit_return_statement (return_statement* s)
1460{
1461 s->value->visit (this);
1462}
1463
1464void
1465traversing_visitor::visit_delete_statement (delete_statement* s)
1466{
1467 s->value->visit (this);
1468}
1469
f3c26ea5 1470void
78f6bba6 1471traversing_visitor::visit_next_statement (next_statement*)
f3c26ea5
FCE
1472{
1473}
1474
1475void
78f6bba6 1476traversing_visitor::visit_break_statement (break_statement*)
f3c26ea5
FCE
1477{
1478}
1479
1480void
78f6bba6 1481traversing_visitor::visit_continue_statement (continue_statement*)
f3c26ea5
FCE
1482{
1483}
1484
82919855 1485void
78f6bba6 1486traversing_visitor::visit_literal_string (literal_string*)
82919855
FCE
1487{
1488}
1489
1490void
78f6bba6 1491traversing_visitor::visit_literal_number (literal_number*)
82919855
FCE
1492{
1493}
1494
1495void
1496traversing_visitor::visit_binary_expression (binary_expression* e)
1497{
1498 e->left->visit (this);
1499 e->right->visit (this);
1500}
1501
1502void
1503traversing_visitor::visit_unary_expression (unary_expression* e)
1504{
1505 e->operand->visit (this);
1506}
1507
1508void
1509traversing_visitor::visit_pre_crement (pre_crement* e)
1510{
1511 e->operand->visit (this);
1512}
1513
1514void
1515traversing_visitor::visit_post_crement (post_crement* e)
1516{
1517 e->operand->visit (this);
1518}
1519
1520
1521void
1522traversing_visitor::visit_logical_or_expr (logical_or_expr* e)
1523{
1524 e->left->visit (this);
1525 e->right->visit (this);
1526}
1527
1528void
1529traversing_visitor::visit_logical_and_expr (logical_and_expr* e)
1530{
1531 e->left->visit (this);
1532 e->right->visit (this);
1533}
1534
1535void
1536traversing_visitor::visit_array_in (array_in* e)
1537{
ce10591c 1538 e->operand->visit (this);
82919855
FCE
1539}
1540
1541void
1542traversing_visitor::visit_comparison (comparison* e)
1543{
1544 e->left->visit (this);
1545 e->right->visit (this);
1546}
1547
1548void
1549traversing_visitor::visit_concatenation (concatenation* e)
1550{
1551 e->left->visit (this);
1552 e->right->visit (this);
1553}
1554
82919855
FCE
1555void
1556traversing_visitor::visit_ternary_expression (ternary_expression* e)
1557{
1558 e->cond->visit (this);
1559 e->truevalue->visit (this);
1560 e->falsevalue->visit (this);
1561}
1562
1563void
1564traversing_visitor::visit_assignment (assignment* e)
1565{
1566 e->left->visit (this);
1567 e->right->visit (this);
1568}
1569
1570void
78f6bba6 1571traversing_visitor::visit_symbol (symbol*)
82919855
FCE
1572{
1573}
1574
d7f3e0c5 1575void
78f6bba6 1576traversing_visitor::visit_target_symbol (target_symbol*)
d7f3e0c5
GH
1577{
1578}
1579
82919855
FCE
1580void
1581traversing_visitor::visit_arrayindex (arrayindex* e)
1582{
cbfbbf69
FCE
1583 for (unsigned i=0; i<e->indexes.size(); i++)
1584 e->indexes[i]->visit (this);
1585
1bbeef03
GH
1586 symbol *array = NULL;
1587 hist_op *hist = NULL;
1588 classify_indexable(e->base, array, hist);
1589 if (array)
1590 return array->visit(this);
1591 else
1592 return hist->visit(this);
82919855
FCE
1593}
1594
1595void
1596traversing_visitor::visit_functioncall (functioncall* e)
1597{
1598 for (unsigned i=0; i<e->args.size(); i++)
1599 e->args[i]->visit (this);
1600}
1601
d02548c0
GH
1602void
1603traversing_visitor::visit_print_format (print_format* e)
1604{
1605 for (unsigned i=0; i<e->args.size(); i++)
1606 e->args[i]->visit (this);
a4636912
GH
1607 if (e->hist)
1608 e->hist->visit(this);
d02548c0
GH
1609}
1610
1611void
1612traversing_visitor::visit_stat_op (stat_op* e)
1613{
1614 e->stat->visit (this);
1615}
1616
1617void
1618traversing_visitor::visit_hist_op (hist_op* e)
1619{
1620 e->stat->visit (this);
1621}
1622
82919855 1623
cbfbbf69 1624void
dff50e09 1625functioncall_traversing_visitor::visit_functioncall (functioncall* e)
cbfbbf69
FCE
1626{
1627 traversing_visitor::visit_functioncall (e);
1628
1629 // prevent infinite recursion
1630 if (traversed.find (e->referent) == traversed.end ())
1631 {
1632 traversed.insert (e->referent);
1633 // recurse
3066c15c
FCE
1634 functiondecl* last_current_function = current_function;
1635 current_function = e->referent;
cbfbbf69 1636 e->referent->body->visit (this);
3066c15c 1637 current_function = last_current_function;
cbfbbf69
FCE
1638 }
1639}
1640
1641
1642void
1643varuse_collecting_visitor::visit_embeddedcode (embeddedcode *s)
1644{
1b07c728
FCE
1645 // We want to elide embedded-C functions when possible. For
1646 // example, each $target variable access is expanded to an
1647 // embedded-C function call. Yet, for safety reasons, we should
1648 // presume that embedded-C functions have intentional side-effects.
1649 //
1650 // To tell these two types of functions apart, we apply a
1651 // Kludge(tm): we look for a magic string within the function body.
1652 // $target variables as rvalues will have this; lvalues won't.
1653 // Also, explicit side-effect-free tapset functions will have this.
dff50e09 1654
3066c15c 1655 assert (current_function); // only they get embedded code
1b07c728 1656 if (s->code.find ("/* pure */") != string::npos)
3066c15c
FCE
1657 return;
1658
cbfbbf69
FCE
1659 embedded_seen = true;
1660}
1661
b0be9bdb
FCE
1662void
1663varuse_collecting_visitor::visit_target_symbol (target_symbol *e)
1664{
1665 // Still-unresolved target symbol assignments get treated as
1666 // generating side-effects like embedded-C, to prevent premature
1667 // elision and later error message suppression (PR5516). rvalue use
1668 // of unresolved target symbols is OTOH not considered a side-effect.
1669
1670 if (is_active_lvalue (e))
1671 embedded_seen = true;
1672}
cbfbbf69
FCE
1673
1674void
1675varuse_collecting_visitor::visit_print_format (print_format* e)
1676{
1677 // NB: Instead of being top-level statements, "print" and "printf"
1678 // are implemented as statement-expressions containing a
1679 // print_format. They have side-effects, but not via the
dff50e09 1680 // embedded-code detection method above.
1b07c728
FCE
1681 //
1682 // But sprint and sprintf don't have side-effects.
1683
1684 if (e->print_to_stream)
1685 embedded_seen = true; // a proxy for "has unknown side-effects"
1686
cbfbbf69
FCE
1687 functioncall_traversing_visitor::visit_print_format (e);
1688}
1689
1690
1691void
1692varuse_collecting_visitor::visit_assignment (assignment *e)
1693{
1694 if (e->op == "=" || e->op == "<<<") // pure writes
1695 {
3066c15c 1696 expression* last_lvalue = current_lvalue;
cbfbbf69
FCE
1697 current_lvalue = e->left; // leave a mark for ::visit_symbol
1698 functioncall_traversing_visitor::visit_assignment (e);
1699 current_lvalue = last_lvalue;
1700 }
1701 else // read-modify-writes
1702 {
1703 expression* last_lrvalue = current_lrvalue;
1704 current_lrvalue = e->left; // leave a mark for ::visit_symbol
1705 functioncall_traversing_visitor::visit_assignment (e);
1706 current_lrvalue = last_lrvalue;
1707 }
1708}
1709
1710void
1711varuse_collecting_visitor::visit_symbol (symbol *e)
1712{
1713 if (e->referent == 0)
1714 throw semantic_error ("symbol without referent", e->tok);
1715
d0c4107b
FCE
1716 // We could handle initialized globals by marking them as "written".
1717 // However, this current visitor may be called for a function or
1718 // probe body, from the point of view of which this global is
1719 // already initialized, so not written.
1720 /*
27d24ae2
FCE
1721 if (e->referent->init)
1722 written.insert (e->referent);
d0c4107b 1723 */
27d24ae2 1724
cbfbbf69
FCE
1725 if (current_lvalue == e || current_lrvalue == e)
1726 {
1727 written.insert (e->referent);
1728 // clog << "write ";
1729 }
1730 if (current_lvalue != e || current_lrvalue == e)
1731 {
1732 read.insert (e->referent);
1733 // clog << "read ";
1734 }
1735 // clog << *e->tok << endl;
1736}
1737
1738// NB: stat_op need not be overridden, since it will get to
1739// visit_symbol and only as a possible rvalue.
1740
d20fd9e9 1741
cbfbbf69
FCE
1742void
1743varuse_collecting_visitor::visit_arrayindex (arrayindex *e)
1744{
1745 // Hooking this callback is necessary because of the hacky
1746 // statistics representation. For the expression "i[4] = 5", the
1747 // incoming lvalue will point to this arrayindex. However, the
1748 // symbol corresponding to the "i[4]" is multiply inherited with
1749 // arrayindex. If the symbol base part of this object is not at
1750 // offset 0, then static_cast<symbol*>(e) may result in a different
1751 // address, and not match lvalue by number when we recurse that way.
1752 // So we explicitly override the incoming lvalue/lrvalue values to
1753 // point at the embedded objects' actual base addresses.
1754
1755 expression* last_lrvalue = current_lrvalue;
1756 expression* last_lvalue = current_lvalue;
1757
1758 symbol *array = NULL;
1759 hist_op *hist = NULL;
1760 classify_indexable(e->base, array, hist);
1761
1762 if (array)
1763 {
1764 if (current_lrvalue == e) current_lrvalue = array;
1765 if (current_lvalue == e) current_lvalue = array;
1766 functioncall_traversing_visitor::visit_arrayindex (e);
1767 }
1768 else // if (hist)
1769 {
1770 if (current_lrvalue == e) current_lrvalue = hist->stat;
1771 if (current_lvalue == e) current_lvalue = hist->stat;
1772 functioncall_traversing_visitor::visit_arrayindex (e);
1773 }
1774
1775 current_lrvalue = last_lrvalue;
1776 current_lvalue = last_lvalue;
1777}
1778
1779
1780void
1781varuse_collecting_visitor::visit_pre_crement (pre_crement *e)
1782{
1783 expression* last_lrvalue = current_lrvalue;
1784 current_lrvalue = e->operand; // leave a mark for ::visit_symbol
1785 functioncall_traversing_visitor::visit_pre_crement (e);
1786 current_lrvalue = last_lrvalue;
1787}
1788
1789void
1790varuse_collecting_visitor::visit_post_crement (post_crement *e)
1791{
1792 expression* last_lrvalue = current_lrvalue;
1793 current_lrvalue = e->operand; // leave a mark for ::visit_symbol
1794 functioncall_traversing_visitor::visit_post_crement (e);
1795 current_lrvalue = last_lrvalue;
1796}
1797
3066c15c
FCE
1798void
1799varuse_collecting_visitor::visit_foreach_loop (foreach_loop* s)
1800{
27d24ae2
FCE
1801 // NB: we duplicate so don't bother call
1802 // functioncall_traversing_visitor::visit_foreach_loop (s);
1803
dff50e09 1804 symbol *array = NULL;
27d24ae2
FCE
1805 hist_op *hist = NULL;
1806 classify_indexable (s->base, array, hist);
1807 if (array)
1808 array->visit(this);
1809 else
1810 hist->visit(this);
1811
3066c15c 1812 // If the collection is sorted, imply a "write" access to the
27d24ae2 1813 // array in addition to the "read" one already noted above.
3066c15c
FCE
1814 if (s->sort_direction)
1815 {
dff50e09 1816 symbol *array = NULL;
3066c15c
FCE
1817 hist_op *hist = NULL;
1818 classify_indexable (s->base, array, hist);
1819 if (array) this->written.insert (array->referent);
1820 // XXX: Can hist_op iterations be sorted?
1821 }
27d24ae2
FCE
1822
1823 // NB: don't forget to visit the index expressions, which are lvalues.
1824 for (unsigned i=0; i<s->indexes.size(); i++)
1825 {
1826 expression* last_lvalue = current_lvalue;
1827 current_lvalue = s->indexes[i]; // leave a mark for ::visit_symbol
1828 s->indexes[i]->visit (this);
1829 current_lvalue = last_lvalue;
1830 }
1831
1832 if (s->limit)
1833 s->limit->visit (this);
1834
1835 s->block->visit (this);
3066c15c 1836}
cbfbbf69
FCE
1837
1838
3066c15c
FCE
1839void
1840varuse_collecting_visitor::visit_delete_statement (delete_statement* s)
1841{
1842 // Ideally, this would be treated like an assignment: a plain write
1843 // to the underlying value ("lvalue"). XXX: However, the
1844 // optimization pass is not smart enough to remove an unneeded
1845 // "delete" yet, so we pose more like a *crement ("lrvalue"). This
1846 // should protect the underlying value from optimizional mischief.
1847 expression* last_lrvalue = current_lrvalue;
1848 current_lrvalue = s->value; // leave a mark for ::visit_symbol
1849 functioncall_traversing_visitor::visit_delete_statement (s);
1850 current_lrvalue = last_lrvalue;
1851}
cbfbbf69 1852
cf9ff341
FCE
1853bool
1854varuse_collecting_visitor::side_effect_free ()
1855{
1856 return (written.empty() && !embedded_seen);
1857}
1858
1859
1860bool
1861varuse_collecting_visitor::side_effect_free_wrt (const set<vardecl*>& vars)
1862{
1863 // A looser notion of side-effect-freeness with respect to a given
1864 // list of variables.
1865
1866 // That's useful because the written list may consist of local
1867 // variables of called functions. But visible side-effects only
1868 // occur if the client's locals, or any globals are written-to.
1869
1870 set<vardecl*> intersection;
1871 insert_iterator<set<vardecl*> > int_it (intersection, intersection.begin());
1872 set_intersection (written.begin(), written.end(),
1873 vars.begin(), vars.end(),
1874 int_it);
1875
1876 return (intersection.empty() && !embedded_seen);
1877}
1878
1879
1880
cbfbbf69 1881
82919855
FCE
1882// ------------------------------------------------------------------------
1883
1884
1885throwing_visitor::throwing_visitor (const std::string& m): msg (m) {}
1886throwing_visitor::throwing_visitor (): msg ("invalid element") {}
1887
1888
1889void
1890throwing_visitor::throwone (const token* t)
1891{
1892 throw semantic_error (msg, t);
1893}
1894
1895void
54dfabe9
FCE
1896throwing_visitor::visit_block (block* s)
1897{
1898 throwone (s->tok);
1899}
1900
1901void
1902throwing_visitor::visit_embeddedcode (embeddedcode* s)
82919855
FCE
1903{
1904 throwone (s->tok);
1905}
1906
1907void
54dfabe9 1908throwing_visitor::visit_null_statement (null_statement* s)
82919855
FCE
1909{
1910 throwone (s->tok);
1911}
1912
1913void
54dfabe9 1914throwing_visitor::visit_expr_statement (expr_statement* s)
82919855
FCE
1915{
1916 throwone (s->tok);
1917}
1918
1919void
1920throwing_visitor::visit_if_statement (if_statement* s)
1921{
1922 throwone (s->tok);
1923}
1924
1925void
1926throwing_visitor::visit_for_loop (for_loop* s)
1927{
1928 throwone (s->tok);
1929}
1930
69c68955
FCE
1931void
1932throwing_visitor::visit_foreach_loop (foreach_loop* s)
1933{
1934 throwone (s->tok);
1935}
1936
82919855
FCE
1937void
1938throwing_visitor::visit_return_statement (return_statement* s)
1939{
1940 throwone (s->tok);
1941}
1942
1943void
1944throwing_visitor::visit_delete_statement (delete_statement* s)
1945{
1946 throwone (s->tok);
1947}
1948
f3c26ea5
FCE
1949void
1950throwing_visitor::visit_next_statement (next_statement* s)
1951{
1952 throwone (s->tok);
1953}
1954
1955void
1956throwing_visitor::visit_break_statement (break_statement* s)
1957{
1958 throwone (s->tok);
1959}
1960
1961void
1962throwing_visitor::visit_continue_statement (continue_statement* s)
1963{
1964 throwone (s->tok);
1965}
1966
82919855
FCE
1967void
1968throwing_visitor::visit_literal_string (literal_string* e)
1969{
1970 throwone (e->tok);
1971}
1972
1973void
1974throwing_visitor::visit_literal_number (literal_number* e)
1975{
1976 throwone (e->tok);
1977}
1978
1979void
1980throwing_visitor::visit_binary_expression (binary_expression* e)
1981{
1982 throwone (e->tok);
1983}
1984
1985void
1986throwing_visitor::visit_unary_expression (unary_expression* e)
1987{
1988 throwone (e->tok);
1989}
1990
1991void
1992throwing_visitor::visit_pre_crement (pre_crement* e)
1993{
1994 throwone (e->tok);
1995}
1996
1997void
1998throwing_visitor::visit_post_crement (post_crement* e)
1999{
2000 throwone (e->tok);
0054a7ea
FCE
2001}
2002
2003
82919855
FCE
2004void
2005throwing_visitor::visit_logical_or_expr (logical_or_expr* e)
2006{
2007 throwone (e->tok);
2008}
2009
2010void
2011throwing_visitor::visit_logical_and_expr (logical_and_expr* e)
2012{
2013 throwone (e->tok);
2014}
2015
2016void
2017throwing_visitor::visit_array_in (array_in* e)
2018{
2019 throwone (e->tok);
2020}
2021
2022void
2023throwing_visitor::visit_comparison (comparison* e)
2024{
2025 throwone (e->tok);
2026}
2027
2028void
2029throwing_visitor::visit_concatenation (concatenation* e)
2030{
2031 throwone (e->tok);
2032}
2033
82919855
FCE
2034void
2035throwing_visitor::visit_ternary_expression (ternary_expression* e)
2036{
2037 throwone (e->tok);
2038}
2039
2040void
2041throwing_visitor::visit_assignment (assignment* e)
2042{
2043 throwone (e->tok);
2044}
2045
2046void
2047throwing_visitor::visit_symbol (symbol* e)
2048{
2049 throwone (e->tok);
2050}
2051
d7f3e0c5
GH
2052void
2053throwing_visitor::visit_target_symbol (target_symbol* e)
2054{
2055 throwone (e->tok);
2056}
2057
82919855
FCE
2058void
2059throwing_visitor::visit_arrayindex (arrayindex* e)
2060{
2061 throwone (e->tok);
2062}
2063
2064void
2065throwing_visitor::visit_functioncall (functioncall* e)
2066{
2067 throwone (e->tok);
2068}
85365d1b 2069
d02548c0
GH
2070void
2071throwing_visitor::visit_print_format (print_format* e)
2072{
2073 throwone (e->tok);
2074}
2075
2076void
2077throwing_visitor::visit_stat_op (stat_op* e)
2078{
2079 throwone (e->tok);
2080}
2081
2082void
2083throwing_visitor::visit_hist_op (hist_op* e)
2084{
2085 throwone (e->tok);
2086}
2087
85365d1b
GH
2088
2089// ------------------------------------------------------------------------
2090
85365d1b
GH
2091
2092void
54dfabe9 2093deep_copy_visitor::visit_block (block* s)
85365d1b 2094{
54dfabe9 2095 block* n = new block;
67c0a579 2096 n->tok = s->tok;
85365d1b
GH
2097 for (unsigned i = 0; i < s->statements.size(); ++i)
2098 {
54dfabe9 2099 statement* ns;
85365d1b
GH
2100 require <statement*> (this, &ns, s->statements[i]);
2101 n->statements.push_back(ns);
2102 }
2103 provide <block*> (this, n);
2104}
2105
2106void
54dfabe9
FCE
2107deep_copy_visitor::visit_embeddedcode (embeddedcode* s)
2108{
2109 embeddedcode* n = new embeddedcode;
2110 n->tok = s->tok;
2111 n->code = s->code;
2112 provide <embeddedcode*> (this, n);
2113}
2114
2115void
2116deep_copy_visitor::visit_null_statement (null_statement* s)
85365d1b 2117{
54dfabe9 2118 null_statement* n = new null_statement;
67c0a579
GH
2119 n->tok = s->tok;
2120 provide <null_statement*> (this, n);
85365d1b
GH
2121}
2122
2123void
54dfabe9 2124deep_copy_visitor::visit_expr_statement (expr_statement* s)
85365d1b 2125{
54dfabe9 2126 expr_statement* n = new expr_statement;
67c0a579 2127 n->tok = s->tok;
85365d1b
GH
2128 require <expression*> (this, &(n->value), s->value);
2129 provide <expr_statement*> (this, n);
2130}
2131
2132void
2133deep_copy_visitor::visit_if_statement (if_statement* s)
2134{
54dfabe9 2135 if_statement* n = new if_statement;
67c0a579 2136 n->tok = s->tok;
85365d1b
GH
2137 require <expression*> (this, &(n->condition), s->condition);
2138 require <statement*> (this, &(n->thenblock), s->thenblock);
c37f6b36 2139 require <statement*> (this, &(n->elseblock), s->elseblock);
85365d1b
GH
2140 provide <if_statement*> (this, n);
2141}
2142
2143void
2144deep_copy_visitor::visit_for_loop (for_loop* s)
2145{
54dfabe9 2146 for_loop* n = new for_loop;
67c0a579 2147 n->tok = s->tok;
85365d1b
GH
2148 require <expr_statement*> (this, &(n->init), s->init);
2149 require <expression*> (this, &(n->cond), s->cond);
2150 require <expr_statement*> (this, &(n->incr), s->incr);
dff50e09 2151 require <statement*> (this, &(n->block), s->block);
85365d1b
GH
2152 provide <for_loop*> (this, n);
2153}
2154
2155void
2156deep_copy_visitor::visit_foreach_loop (foreach_loop* s)
2157{
54dfabe9 2158 foreach_loop* n = new foreach_loop;
67c0a579 2159 n->tok = s->tok;
85365d1b
GH
2160 for (unsigned i = 0; i < s->indexes.size(); ++i)
2161 {
54dfabe9 2162 symbol* sym;
85365d1b
GH
2163 require <symbol*> (this, &sym, s->indexes[i]);
2164 n->indexes.push_back(sym);
2165 }
d02548c0
GH
2166
2167 require <indexable*> (this, &(n->base), s->base);
2168
93484556
FCE
2169 n->sort_direction = s->sort_direction;
2170 n->sort_column = s->sort_column;
27f21e8c 2171 require <expression*> (this, &(n->limit), s->limit);
d02548c0 2172
85365d1b
GH
2173 require <statement*> (this, &(n->block), s->block);
2174 provide <foreach_loop*> (this, n);
2175}
2176
2177void
2178deep_copy_visitor::visit_return_statement (return_statement* s)
2179{
54dfabe9 2180 return_statement* n = new return_statement;
67c0a579 2181 n->tok = s->tok;
85365d1b
GH
2182 require <expression*> (this, &(n->value), s->value);
2183 provide <return_statement*> (this, n);
2184}
2185
2186void
2187deep_copy_visitor::visit_delete_statement (delete_statement* s)
2188{
54dfabe9 2189 delete_statement* n = new delete_statement;
67c0a579 2190 n->tok = s->tok;
85365d1b
GH
2191 require <expression*> (this, &(n->value), s->value);
2192 provide <delete_statement*> (this, n);
2193}
2194
2195void
2196deep_copy_visitor::visit_next_statement (next_statement* s)
2197{
54dfabe9 2198 next_statement* n = new next_statement;
67c0a579
GH
2199 n->tok = s->tok;
2200 provide <next_statement*> (this, n);
85365d1b
GH
2201}
2202
2203void
2204deep_copy_visitor::visit_break_statement (break_statement* s)
2205{
54dfabe9 2206 break_statement* n = new break_statement;
67c0a579
GH
2207 n->tok = s->tok;
2208 provide <break_statement*> (this, n);
85365d1b
GH
2209}
2210
2211void
2212deep_copy_visitor::visit_continue_statement (continue_statement* s)
2213{
54dfabe9 2214 continue_statement* n = new continue_statement;
67c0a579
GH
2215 n->tok = s->tok;
2216 provide <continue_statement*> (this, n);
85365d1b
GH
2217}
2218
2219void
2220deep_copy_visitor::visit_literal_string (literal_string* e)
2221{
54dfabe9 2222 literal_string* n = new literal_string(e->value);
67c0a579
GH
2223 n->tok = e->tok;
2224 provide <literal_string*> (this, n);
85365d1b
GH
2225}
2226
2227void
2228deep_copy_visitor::visit_literal_number (literal_number* e)
2229{
54dfabe9 2230 literal_number* n = new literal_number(e->value);
67c0a579
GH
2231 n->tok = e->tok;
2232 provide <literal_number*> (this, n);
85365d1b
GH
2233}
2234
2235void
2236deep_copy_visitor::visit_binary_expression (binary_expression* e)
2237{
54dfabe9 2238 binary_expression* n = new binary_expression;
85365d1b 2239 n->op = e->op;
67c0a579 2240 n->tok = e->tok;
85365d1b
GH
2241 require <expression*> (this, &(n->left), e->left);
2242 require <expression*> (this, &(n->right), e->right);
2243 provide <binary_expression*> (this, n);
2244}
2245
2246void
2247deep_copy_visitor::visit_unary_expression (unary_expression* e)
2248{
54dfabe9 2249 unary_expression* n = new unary_expression;
85365d1b 2250 n->op = e->op;
67c0a579 2251 n->tok = e->tok;
85365d1b
GH
2252 require <expression*> (this, &(n->operand), e->operand);
2253 provide <unary_expression*> (this, n);
2254}
2255
2256void
2257deep_copy_visitor::visit_pre_crement (pre_crement* e)
2258{
54dfabe9 2259 pre_crement* n = new pre_crement;
85365d1b 2260 n->op = e->op;
67c0a579 2261 n->tok = e->tok;
85365d1b
GH
2262 require <expression*> (this, &(n->operand), e->operand);
2263 provide <pre_crement*> (this, n);
2264}
2265
2266void
2267deep_copy_visitor::visit_post_crement (post_crement* e)
2268{
54dfabe9 2269 post_crement* n = new post_crement;
85365d1b 2270 n->op = e->op;
67c0a579 2271 n->tok = e->tok;
85365d1b
GH
2272 require <expression*> (this, &(n->operand), e->operand);
2273 provide <post_crement*> (this, n);
2274}
2275
2276
2277void
2278deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e)
2279{
54dfabe9 2280 logical_or_expr* n = new logical_or_expr;
85365d1b 2281 n->op = e->op;
67c0a579 2282 n->tok = e->tok;
85365d1b
GH
2283 require <expression*> (this, &(n->left), e->left);
2284 require <expression*> (this, &(n->right), e->right);
2285 provide <logical_or_expr*> (this, n);
2286}
2287
2288void
2289deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e)
2290{
54dfabe9 2291 logical_and_expr* n = new logical_and_expr;
85365d1b 2292 n->op = e->op;
67c0a579 2293 n->tok = e->tok;
85365d1b
GH
2294 require <expression*> (this, &(n->left), e->left);
2295 require <expression*> (this, &(n->right), e->right);
2296 provide <logical_and_expr*> (this, n);
2297}
2298
2299void
2300deep_copy_visitor::visit_array_in (array_in* e)
2301{
54dfabe9 2302 array_in* n = new array_in;
67c0a579 2303 n->tok = e->tok;
85365d1b
GH
2304 require <arrayindex*> (this, &(n->operand), e->operand);
2305 provide <array_in*> (this, n);
2306}
2307
2308void
2309deep_copy_visitor::visit_comparison (comparison* e)
2310{
54dfabe9 2311 comparison* n = new comparison;
85365d1b 2312 n->op = e->op;
67c0a579 2313 n->tok = e->tok;
85365d1b
GH
2314 require <expression*> (this, &(n->left), e->left);
2315 require <expression*> (this, &(n->right), e->right);
2316 provide <comparison*> (this, n);
2317}
2318
2319void
2320deep_copy_visitor::visit_concatenation (concatenation* e)
2321{
54dfabe9 2322 concatenation* n = new concatenation;
85365d1b 2323 n->op = e->op;
67c0a579 2324 n->tok = e->tok;
85365d1b
GH
2325 require <expression*> (this, &(n->left), e->left);
2326 require <expression*> (this, &(n->right), e->right);
2327 provide <concatenation*> (this, n);
2328}
2329
2330void
2331deep_copy_visitor::visit_ternary_expression (ternary_expression* e)
2332{
54dfabe9 2333 ternary_expression* n = new ternary_expression;
67c0a579 2334 n->tok = e->tok;
85365d1b
GH
2335 require <expression*> (this, &(n->cond), e->cond);
2336 require <expression*> (this, &(n->truevalue), e->truevalue);
2337 require <expression*> (this, &(n->falsevalue), e->falsevalue);
2338 provide <ternary_expression*> (this, n);
2339}
2340
2341void
2342deep_copy_visitor::visit_assignment (assignment* e)
2343{
54dfabe9 2344 assignment* n = new assignment;
85365d1b 2345 n->op = e->op;
67c0a579 2346 n->tok = e->tok;
85365d1b
GH
2347 require <expression*> (this, &(n->left), e->left);
2348 require <expression*> (this, &(n->right), e->right);
2349 provide <assignment*> (this, n);
2350}
2351
2352void
2353deep_copy_visitor::visit_symbol (symbol* e)
2354{
54dfabe9 2355 symbol* n = new symbol;
67c0a579 2356 n->tok = e->tok;
85365d1b
GH
2357 n->name = e->name;
2358 n->referent = NULL;
2359 provide <symbol*> (this, n);
d7f3e0c5
GH
2360}
2361
2362void
2363deep_copy_visitor::visit_target_symbol (target_symbol* e)
2364{
2365 target_symbol* n = new target_symbol;
2366 n->tok = e->tok;
2367 n->base_name = e->base_name;
2368 n->components = e->components;
2369 provide <target_symbol*> (this, n);
85365d1b
GH
2370}
2371
2372void
2373deep_copy_visitor::visit_arrayindex (arrayindex* e)
2374{
54dfabe9 2375 arrayindex* n = new arrayindex;
67c0a579 2376 n->tok = e->tok;
d02548c0
GH
2377
2378 require <indexable*> (this, &(n->base), e->base);
2379
85365d1b
GH
2380 for (unsigned i = 0; i < e->indexes.size(); ++i)
2381 {
54dfabe9 2382 expression* ne;
85365d1b
GH
2383 require <expression*> (this, &ne, e->indexes[i]);
2384 n->indexes.push_back(ne);
2385 }
2386 provide <arrayindex*> (this, n);
2387}
2388
2389void
2390deep_copy_visitor::visit_functioncall (functioncall* e)
2391{
54dfabe9 2392 functioncall* n = new functioncall;
67c0a579 2393 n->tok = e->tok;
85365d1b
GH
2394 n->function = e->function;
2395 n->referent = NULL;
2396 for (unsigned i = 0; i < e->args.size(); ++i)
2397 {
54dfabe9 2398 expression* na;
85365d1b
GH
2399 require <expression*> (this, &na, e->args[i]);
2400 n->args.push_back(na);
2401 }
2402 provide <functioncall*> (this, n);
2403}
2404
d02548c0
GH
2405void
2406deep_copy_visitor::visit_print_format (print_format* e)
2407{
2408 print_format* n = new print_format;
2409 n->tok = e->tok;
d02548c0 2410 n->print_to_stream = e->print_to_stream;
3cb17058
JS
2411 n->print_with_format = e->print_with_format;
2412 n->print_with_delim = e->print_with_delim;
2413 n->print_with_newline = e->print_with_newline;
32784362 2414 n->print_char = e->print_char;
1b07c728 2415 n->raw_components = e->raw_components;
d02548c0 2416 n->components = e->components;
3cb17058 2417 n->delimiter = e->delimiter;
d02548c0
GH
2418 for (unsigned i = 0; i < e->args.size(); ++i)
2419 {
2420 expression* na;
2421 require <expression*> (this, &na, e->args[i]);
2422 n->args.push_back(na);
2423 }
a4636912
GH
2424 if (e->hist)
2425 require <hist_op*> (this, &n->hist, e->hist);
d02548c0
GH
2426 provide <print_format*> (this, n);
2427}
2428
2429void
2430deep_copy_visitor::visit_stat_op (stat_op* e)
2431{
2432 stat_op* n = new stat_op;
2433 n->tok = e->tok;
2434 n->ctype = e->ctype;
2435 require <expression*> (this, &(n->stat), e->stat);
2436 provide <stat_op*> (this, n);
2437}
2438
2439void
2440deep_copy_visitor::visit_hist_op (hist_op* e)
2441{
2442 hist_op* n = new hist_op;
2443 n->tok = e->tok;
2444 n->htype = e->htype;
2445 n->params = e->params;
2446 require <expression*> (this, &(n->stat), e->stat);
2447 provide <hist_op*> (this, n);
2448}
2449
dff50e09 2450block*
54dfabe9 2451deep_copy_visitor::deep_copy (block* b)
85365d1b 2452{
54dfabe9 2453 block* n;
85365d1b
GH
2454 deep_copy_visitor v;
2455 require <block*> (&v, &n, b);
2456 return n;
2457}
2458
dff50e09 2459statement*
54dfabe9 2460deep_copy_visitor::deep_copy (statement* s)
85365d1b 2461{
54dfabe9 2462 statement* n;
85365d1b
GH
2463 deep_copy_visitor v;
2464 require <statement*> (&v, &n, s);
2465 return n;
2466}
cbbe8080
MH
2467
2468expression*
2469deep_copy_visitor::deep_copy (expression* s)
2470{
2471 expression* n;
2472 deep_copy_visitor v;
2473 require <expression*> (&v, &n, s);
2474 return n;
2475}
edc22ba9
DB
2476
2477template <> void
2478require <indexable *> (deep_copy_visitor* v, indexable** dst, indexable* src)
2479{
2480 if (src != NULL)
2481 {
2482 symbol *array_src=NULL, *array_dst=NULL;
2483 hist_op *hist_src=NULL, *hist_dst=NULL;
2484
2485 classify_indexable(src, array_src, hist_src);
2486
2487 *dst = NULL;
2488
2489 if (array_src)
2490 {
2491 require <symbol*> (v, &array_dst, array_src);
2492 *dst = array_dst;
2493 }
2494 else
2495 {
2496 require <hist_op*> (v, &hist_dst, hist_src);
2497 *dst = hist_dst;
2498 }
2499 assert (*dst);
2500 }
2501}
2502
This page took 0.325217 seconds and 5 git commands to generate.