LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - parse.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 1880 1953 96.3 %
Date: 2013-03-08 Functions: 97 99 98.0 %
Branches: 3018 4754 63.5 %

           Branch data     Line data    Source code
       1                 :            : // recursive descent parser for systemtap scripts
       2                 :            : // Copyright (C) 2005-2013 Red Hat Inc.
       3                 :            : // Copyright (C) 2006 Intel Corporation.
       4                 :            : // Copyright (C) 2007 Bull S.A.S
       5                 :            : //
       6                 :            : // This file is part of systemtap, and is free software.  You can
       7                 :            : // redistribute it and/or modify it under the terms of the GNU General
       8                 :            : // Public License (GPL); either version 2, or (at your option) any
       9                 :            : // later version.
      10                 :            : 
      11                 :            : #include "config.h"
      12                 :            : #include "staptree.h"
      13                 :            : #include "parse.h"
      14                 :            : #include "session.h"
      15                 :            : #include "util.h"
      16                 :            : 
      17                 :            : #include <iostream>
      18                 :            : 
      19                 :            : #include <fstream>
      20                 :            : #include <cctype>
      21                 :            : #include <cstdlib>
      22                 :            : #include <cassert>
      23                 :            : #include <cerrno>
      24                 :            : #include <climits>
      25                 :            : #include <sstream>
      26                 :            : #include <cstring>
      27                 :            : #include <cctype>
      28                 :            : #include <iterator>
      29                 :            : 
      30                 :            : extern "C" {
      31                 :            : #include <fnmatch.h>
      32                 :            : }
      33                 :            : 
      34                 :            : using namespace std;
      35                 :            : 
      36                 :            : 
      37         [ +  - ]:     191819 : class lexer
      38                 :            : {
      39                 :            : public:
      40                 :            :   bool ate_comment; // current token follows a comment
      41                 :            :   bool ate_whitespace; // the most recent token followed whitespace
      42                 :            :   bool saw_tokens; // the lexer found tokens (before preprocessing occurred)
      43                 :            : 
      44                 :            :   token* scan ();
      45                 :            :   lexer (istream&, const string&, systemtap_session&);
      46                 :            :   void set_current_file (stapfile* f);
      47                 :            : 
      48                 :            :   static set<string> keywords;
      49                 :            :   static set<string> atwords;
      50                 :            : private:
      51                 :            :   inline int input_get ();
      52                 :            :   inline int input_peek (unsigned n=0);
      53                 :            :   void input_put (const string&, const token*);
      54                 :            :   string input_name;
      55                 :            :   string input_contents;
      56                 :            :   const char *input_pointer; // index into input_contents
      57                 :            :   const char *input_end;
      58                 :            :   unsigned cursor_suspend_count;
      59                 :            :   unsigned cursor_suspend_line;
      60                 :            :   unsigned cursor_suspend_column;
      61                 :            :   unsigned cursor_line;
      62                 :            :   unsigned cursor_column;
      63                 :            :   systemtap_session& session;
      64                 :            :   stapfile* current_file;
      65                 :            : };
      66                 :            : 
      67                 :            : 
      68                 :            : class parser
      69                 :            : {
      70                 :            : public:
      71                 :            :   parser (systemtap_session& s, const string& n, istream& i, bool p);
      72                 :            :   ~parser ();
      73                 :            : 
      74                 :            :   stapfile* parse ();
      75                 :            :   stapfile* parse_library_macros ();
      76                 :            : 
      77                 :            : private:
      78                 :            :   typedef enum {
      79                 :            :       PP_NONE,
      80                 :            :       PP_KEEP_THEN,
      81                 :            :       PP_SKIP_THEN,
      82                 :            :       PP_KEEP_ELSE,
      83                 :            :       PP_SKIP_ELSE,
      84                 :            :   } pp_state_t;
      85                 :            : 
      86                 :            :   struct pp1_activation;
      87                 :            : 
      88         [ -  + ]:    1887180 :   struct pp_macrodecl : public macrodecl {
      89                 :            :     pp1_activation* parent_act; // used for param bindings
      90                 :    2779156 :     virtual bool is_closure() { return parent_act != 0; }
      91                 :     943590 :     pp_macrodecl () : macrodecl(), parent_act(0) { }
      92                 :            :   };
      93                 :            : 
      94                 :            :   systemtap_session& session;
      95                 :            :   string input_name;
      96                 :            :   lexer input;
      97                 :            :   bool privileged;
      98                 :            :   parse_context context;
      99                 :            : 
     100                 :            :   // preprocessing subordinate, first pass (macros)
     101                 :            :   struct pp1_activation {
     102                 :            :     const token* tok;
     103                 :            :     unsigned cursor; // position within macro body
     104                 :            :     map<string, pp_macrodecl*> params;
     105                 :            : 
     106                 :            :     macrodecl* curr_macro;
     107                 :            : 
     108                 :    1915243 :     pp1_activation (const token tok, macrodecl* curr_macro)
     109         [ +  - ]:    1915243 :       : tok(new token(tok)), cursor(0), curr_macro(curr_macro) { }
     110                 :            :     ~pp1_activation ();
     111                 :            :   };
     112                 :            : 
     113                 :            :   map<string, macrodecl*> pp1_namespace;
     114                 :            :   vector<pp1_activation*> pp1_state;
     115                 :            :   const token* next_pp1 ();
     116                 :            :   const token* scan_pp1 ();
     117                 :            :   const token* slurp_pp1_param (vector<const token*>& param);
     118                 :            :   const token* slurp_pp1_body (vector<const token*>& body);
     119                 :            : 
     120                 :            :   // preprocessing subordinate, final pass (conditionals)
     121                 :            :   vector<pair<const token*, pp_state_t> > pp_state;
     122                 :            :   const token* scan_pp ();
     123                 :            :   const token* skip_pp ();
     124                 :            : 
     125                 :            :   // scanning state
     126                 :            :   const token* next ();
     127                 :            :   const token* peek ();
     128                 :            : 
     129                 :            :   // Advance past and throw away current token after peek () or next ().
     130                 :            :   void swallow ();
     131                 :            : 
     132                 :            :   const token* systemtap_v_seen;
     133                 :            :   const token* last_t; // the last value returned by peek() or next()
     134                 :            :   const token* next_t; // lookahead token
     135                 :            : 
     136                 :            :   // expectations, these swallow the token
     137                 :            :   void expect_known (token_type tt, string const & expected);
     138                 :            :   void expect_unknown (token_type tt, string & target);
     139                 :            :   void expect_unknown2 (token_type tt1, token_type tt2, string & target);
     140                 :            : 
     141                 :            :   // convenience forms, these also swallow the token
     142                 :            :   void expect_op (string const & expected);
     143                 :            :   void expect_kw (string const & expected);
     144                 :            :   void expect_number (int64_t & expected);
     145                 :            :   void expect_ident_or_keyword (string & target);
     146                 :            : 
     147                 :            :   // convenience forms, which return true or false, these don't swallow token
     148                 :            :   bool peek_op (string const & op);
     149                 :            :   bool peek_kw (string const & kw);
     150                 :            : 
     151                 :            :   // convenience forms, which return the token
     152                 :            :   const token* expect_kw_token (string const & expected);
     153                 :            :   const token* expect_ident_or_atword (string & target);
     154                 :            : 
     155                 :            :   void print_error (const parse_error& pe);
     156                 :            :   unsigned num_errors;
     157                 :            : 
     158                 :            : private: // nonterminals
     159                 :            :   void parse_probe (vector<probe*>&, vector<probe_alias*>&);
     160                 :            :   void parse_global (vector<vardecl*>&, vector<probe*>&);
     161                 :            :   void parse_functiondecl (vector<functiondecl*>&);
     162                 :            :   embeddedcode* parse_embeddedcode ();
     163                 :            :   probe_point* parse_probe_point ();
     164                 :            :   literal_string* consume_string_literals (const token*);
     165                 :            :   literal_string* parse_literal_string ();
     166                 :            :   literal* parse_literal ();
     167                 :            :   block* parse_stmt_block ();
     168                 :            :   try_block* parse_try_block ();
     169                 :            :   statement* parse_statement ();
     170                 :            :   if_statement* parse_if_statement ();
     171                 :            :   for_loop* parse_for_loop ();
     172                 :            :   for_loop* parse_while_loop ();
     173                 :            :   foreach_loop* parse_foreach_loop ();
     174                 :            :   expr_statement* parse_expr_statement ();
     175                 :            :   return_statement* parse_return_statement ();
     176                 :            :   delete_statement* parse_delete_statement ();
     177                 :            :   next_statement* parse_next_statement ();
     178                 :            :   break_statement* parse_break_statement ();
     179                 :            :   continue_statement* parse_continue_statement ();
     180                 :            :   indexable* parse_indexable ();
     181                 :            :   const token *parse_hist_op_or_bare_name (hist_op *&hop, string &name);
     182                 :            :   target_symbol *parse_target_symbol (const token* t);
     183                 :            :   expression* parse_entry_op (const token* t);
     184                 :            :   expression* parse_defined_op (const token* t);
     185                 :            :   expression* parse_perf_op (const token* t);
     186                 :            :   expression* parse_expression ();
     187                 :            :   expression* parse_assignment ();
     188                 :            :   expression* parse_ternary ();
     189                 :            :   expression* parse_logical_or ();
     190                 :            :   expression* parse_logical_and ();
     191                 :            :   expression* parse_boolean_or ();
     192                 :            :   expression* parse_boolean_xor ();
     193                 :            :   expression* parse_boolean_and ();
     194                 :            :   expression* parse_array_in ();
     195                 :            :   expression* parse_comparison_or_regex_query ();
     196                 :            :   expression* parse_shift ();
     197                 :            :   expression* parse_concatenation ();
     198                 :            :   expression* parse_additive ();
     199                 :            :   expression* parse_multiplicative ();
     200                 :            :   expression* parse_unary ();
     201                 :            :   expression* parse_crement ();
     202                 :            :   expression* parse_value ();
     203                 :            :   expression* parse_symbol ();
     204                 :            : 
     205                 :            :   void parse_target_symbol_components (target_symbol* e);
     206                 :            : };
     207                 :            : 
     208                 :            : 
     209                 :            : // ------------------------------------------------------------------------
     210                 :            : 
     211                 :            : stapfile*
     212                 :        540 : parse (systemtap_session& s, istream& i, bool pr)
     213                 :            : {
     214 [ +  - ][ +  - ]:        540 :   parser p (s, "<input>", i, pr);
                 [ +  - ]
     215 [ +  - ][ +  - ]:        540 :   return p.parse ();
     216                 :            : }
     217                 :            : 
     218                 :            : 
     219                 :            : stapfile*
     220                 :     186972 : parse (systemtap_session& s, const string& name, bool pr)
     221                 :            : {
     222 [ +  - ][ +  - ]:     186972 :   ifstream i(name.c_str(), ios::in);
     223 [ +  - ][ +  + ]:     186972 :   if (i.fail())
     224                 :            :     {
     225         [ +  - ]:          1 :       cerr << (file_exists(name)
     226                 :          0 :                ? _F("Input file '%s' can't be opened for reading.", name.c_str())
     227 [ -  + ][ #  # ]:          2 :                : _F("Input file '%s' is missing.", name.c_str()))
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     228         [ +  - ]:          1 :            << endl;
     229                 :          1 :       return 0;
     230                 :            :     }
     231                 :            : 
     232         [ +  - ]:     186971 :   parser p (s, name, i, pr);
     233 [ +  - ][ +  - ]:     186972 :   return p.parse ();
                 [ +  - ]
     234                 :            : }
     235                 :            : 
     236                 :            : stapfile*
     237                 :       4308 : parse_library_macros (systemtap_session& s, const string& name)
     238                 :            : {
     239 [ +  - ][ +  - ]:       4308 :   ifstream i(name.c_str(), ios::in);
     240 [ +  - ][ -  + ]:       4308 :   if (i.fail())
     241                 :            :     {
     242         [ #  # ]:          0 :       cerr << (file_exists(name)
     243                 :          0 :                ? _F("Input file '%s' can't be opened for reading.", name.c_str())
     244 [ #  # ][ #  # ]:          0 :                : _F("Input file '%s' is missing.", name.c_str()))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     245         [ #  # ]:          0 :            << endl;
     246                 :          0 :       return 0;
     247                 :            :     }
     248                 :            : 
     249         [ +  - ]:       4308 :   parser p (s, name, i, false); // TODOXX pr is ...? should path be full??
     250 [ +  - ][ +  - ]:       4308 :   return p.parse_library_macros ();
                 [ +  - ]
     251                 :            : }
     252                 :            : 
     253                 :            : // ------------------------------------------------------------------------
     254                 :            : 
     255                 :            : 
     256                 :     191819 : parser::parser (systemtap_session& s, const string &n, istream& i, bool p):
     257                 :            :   session (s), input_name (n), input (i, input_name, s), privileged (p),
     258 [ +  - ][ +  - ]:     191819 :   context(con_unknown), systemtap_v_seen(0), last_t (0), next_t (0), num_errors (0)
         [ +  - ][ +  - ]
     259                 :            : {
     260                 :     191819 : }
     261                 :            : 
     262                 :     959095 : parser::~parser()
     263                 :            : {
     264 [ +  - ][ +  - ]:     191819 : }
         [ +  - ][ +  - ]
     265                 :            : 
     266                 :            : static string
     267                 :      59564 : tt2str(token_type tt)
     268                 :            : {
     269   [ +  +  +  +  :      59564 :   switch (tt)
             +  +  +  - ]
     270                 :            :     {
     271         [ +  - ]:          6 :     case tok_junk: return "junk";
     272         [ +  - ]:      36344 :     case tok_identifier: return "identifier";
     273         [ +  - ]:       6423 :     case tok_operator: return "operator";
     274         [ +  - ]:         20 :     case tok_string: return "string";
     275         [ +  - ]:         24 :     case tok_number: return "number";
     276         [ +  - ]:          4 :     case tok_embedded: return "embedded-code";
     277         [ +  - ]:      16743 :     case tok_keyword: return "keyword";
     278                 :            :     }
     279         [ #  # ]:      59564 :   return "unknown token";
     280                 :            : }
     281                 :            : 
     282                 :            : ostream&
     283                 :      93286 : operator << (ostream& o, const source_loc& loc)
     284                 :            : {
     285                 :      93286 :   o << loc.file->name << ":"
     286                 :      93286 :     << loc.line << ":"
     287                 :      93286 :     << loc.column;
     288                 :            : 
     289                 :      93286 :   return o;
     290                 :            : }
     291                 :            : 
     292                 :            : ostream&
     293                 :      59561 : operator << (ostream& o, const token& t)
     294                 :            : {
     295         [ +  - ]:      59561 :   o << tt2str(t.type);
     296                 :            : 
     297 [ +  + ][ +  + ]:      59561 :   if (t.type != tok_embedded && t.type != tok_keyword) // XXX: other types?
     298                 :            :     {
     299                 :      42814 :       o << " '";
     300         [ +  + ]:     290845 :       for (unsigned i=0; i<t.content.length(); i++)
     301                 :            :         {
     302                 :     248031 :           char c = t.content[i];
     303         [ +  - ]:     248031 :           o << (isprint (c) ? c : '?');
     304                 :            :         }
     305                 :      42814 :       o << "'";
     306                 :            :     }
     307                 :            : 
     308                 :      59561 :   o << " at "
     309                 :      59561 :     << t.location;
     310                 :            : 
     311                 :      59561 :   return o;
     312                 :            : }
     313                 :            : 
     314                 :            : 
     315                 :            : void
     316                 :        141 : parser::print_error  (const parse_error &pe)
     317                 :            : {
     318         [ +  - ]:        141 :   string align_parse_error ("     ");
     319                 :            : 
     320         [ +  + ]:        141 :   const token *tok = pe.tok ? pe.tok : last_t;
     321                 :            : 
     322                 :            :   // print either pe.what() or a deferred error from the lexer
     323                 :        141 :   bool found_junk = false;
     324 [ +  + ][ +  + ]:        141 :   if (tok && tok->type == tok_junk && tok->msg != "")
         [ +  - ][ +  - ]
                 [ +  + ]
     325                 :            :     {
     326                 :          6 :       found_junk = true;
     327 [ +  - ][ +  - ]:          6 :       cerr << _("parse error: ") << tok->msg << endl;
                 [ +  - ]
     328                 :            :     }
     329                 :            :   else
     330                 :            :     {
     331 [ +  - ][ +  - ]:        135 :       cerr << _("parse error: ") << pe.what() << endl;      
                 [ +  - ]
     332                 :            :     }
     333                 :            : 
     334                 :            :   // NB: It makes sense for lexer errors to always override parser
     335                 :            :   // errors, since the original obvious scheme was for the lexer to
     336                 :            :   // throw an exception before the token reached the parser.
     337                 :            : 
     338 [ +  + ][ +  + ]:        141 :   if (pe.tok || found_junk)
     339                 :            :     {
     340 [ +  - ][ +  - ]:         47 :       cerr << _("\tat: ") << *tok << endl;
                 [ +  - ]
     341         [ +  - ]:         47 :       session.print_error_source (cerr, align_parse_error, tok);
     342                 :            :     }
     343         [ +  + ]:         94 :   else if (tok) // "expected" type error
     344                 :            :     {
     345 [ +  - ][ +  - ]:         88 :       cerr << _("\tsaw: ") << *tok << endl;
                 [ +  - ]
     346         [ +  - ]:         88 :       session.print_error_source (cerr, align_parse_error, tok);
     347                 :            :     }
     348                 :            :   else
     349                 :            :     {
     350 [ +  - ][ +  - ]:          6 :       cerr << _("\tsaw: ") << input_name << " EOF" << endl;
         [ +  - ][ +  - ]
     351                 :            :     }
     352                 :            : 
     353                 :            :   // print chained macro invocations
     354 [ +  + ][ +  + ]:        144 :   while (tok && tok->chain) {
                 [ +  + ]
     355                 :          3 :     tok = tok->chain;
     356 [ +  - ][ +  - ]:          3 :     cerr << _("\tin expansion of macro: ") << *tok << endl;
                 [ +  - ]
     357         [ +  - ]:          3 :     session.print_error_source (cerr, align_parse_error, tok);
     358                 :            :   }
     359                 :            : 
     360         [ +  - ]:        141 :   num_errors ++;
     361                 :        141 : }
     362                 :            : 
     363                 :            : 
     364                 :            : 
     365                 :            : 
     366                 :            : template <typename OPERAND>
     367                 :      82016 : bool eval_comparison (const OPERAND& lhs, const token* op, const OPERAND& rhs)
     368                 :            : {
     369 [ +  - ][ -  + ]:      82016 :   if (op->type == tok_operator && op->content == "<=")
         [ -  + ][ +  - ]
         [ -  + ][ -  + ]
     370                 :          0 :     { return lhs <= rhs; }
     371 [ +  - ][ -  + ]:      82016 :   else if (op->type == tok_operator && op->content == ">=")
         [ -  + ][ +  - ]
         [ +  + ][ +  + ]
     372                 :      79770 :     { return lhs >= rhs; }
     373 [ +  - ][ +  + ]:       2246 :   else if (op->type == tok_operator && op->content == "<")
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
     374                 :         13 :     { return lhs < rhs; }
     375 [ +  - ][ -  + ]:       2233 :   else if (op->type == tok_operator && op->content == ">")
         [ -  + ][ +  - ]
         [ +  + ][ +  + ]
     376                 :         24 :     { return lhs > rhs; }
     377 [ +  - ][ +  + ]:       2209 :   else if (op->type == tok_operator && op->content == "==")
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
     378                 :       2193 :     { return lhs == rhs; }
     379 [ +  - ][ +  - ]:         16 :   else if (op->type == tok_operator && op->content == "!=")
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     380                 :         16 :     { return lhs != rhs; }
     381                 :            :   else
     382 [ #  # ][ #  # ]:      82016 :     throw parse_error (_("expected comparison operator"), op);
         [ #  # ][ #  # ]
     383                 :            : }
     384                 :            : 
     385                 :            : 
     386                 :            : // Here, we perform on-the-fly preprocessing in two passes.
     387                 :            : 
     388                 :            : // First pass - macro declaration and expansion.
     389                 :            : //
     390                 :            : // The basic form of a declaration is @define SIGNATURE %( BODY %)
     391                 :            : // where SIGNATURE is of the form macro_name (a, b, c, ...)
     392                 :            : // and BODY can obtain the parameter contents as @a, @b, @c, ....
     393                 :            : // Note that parameterless macros can also be declared.
     394                 :            : //
     395                 :            : // Macro definitions may not be nested.
     396                 :            : // A macro is available textually after it has been defined.
     397                 :            : //
     398                 :            : // The basic form of a macro invocation
     399                 :            : //   for a parameterless macro is @macro_name,
     400                 :            : //   for a macro with parameters is @macro_name(param_1, param_2, ...).
     401                 :            : //
     402                 :            : // TODOXXX NB: this means that a parameterless macro @foo called as
     403                 :            : // @foo(a, b, c) leaves its 'parameters' alone, rather than consuming
     404                 :            : // them to result in a "too many parameters error".
     405                 :            : //
     406                 :            : // Invocations of unknown macros are left unexpanded, to allow
     407                 :            : // the continued use of constructs such as @cast, @var, etc.
     408                 :            : 
     409                 :    3774360 : macrodecl::~macrodecl ()
     410                 :            : {
     411 [ +  - ][ +  - ]:     943590 :   delete tok;
     412 [ +  - ][ +  - ]:    8677100 :   for (vector<const token*>::iterator it = body.begin();
         [ +  - ][ +  + ]
     413         [ +  - ]:    4338550 :        it != body.end(); it++)
     414 [ +  - ][ +  - ]:    3394960 :     delete *it;
     415 [ +  - ][ +  - ]:     943590 : }
                 [ -  + ]
     416                 :            : 
     417                 :    3830486 : parser::pp1_activation::~pp1_activation ()
     418                 :            : {
     419 [ +  - ][ +  - ]:    1915243 :   delete tok;
     420 [ +  - ][ +  + ]:    1915243 :   if (curr_macro->is_closure()) return; // body is shared with an earlier declaration
     421 [ +  - ][ +  + ]:    5433334 :   for (map<string, pp_macrodecl*>::iterator it = params.begin();
     422         [ +  - ]:    2716667 :        it != params.end(); it++)
     423 [ +  - ][ +  - ]:     943590 :     delete it->second;
                 [ +  - ]
     424                 :    1915243 : }
     425                 :            : 
     426                 :            : // Grab a token from the current input source (main file or macro body):
     427                 :            : const token*
     428                 :  275820886 : parser::next_pp1 ()
     429                 :            : {
     430         [ +  + ]:  275820886 :   if (pp1_state.empty())
     431                 :  254414512 :     return input.scan ();
     432                 :            : 
     433                 :            :   // otherwise, we're inside a macro
     434                 :   21406374 :   pp1_activation* act = pp1_state.back();
     435                 :   21406374 :   unsigned& cursor = act->cursor;
     436         [ +  + ]:   21406374 :   if (cursor < act->curr_macro->body.size())
     437                 :            :     {
     438         [ +  - ]:   19491134 :       token* t = new token(*act->curr_macro->body[cursor]);
     439                 :   19491134 :       t->chain = act->tok; // mark chained token
     440                 :   19491134 :       cursor++;
     441                 :   19491134 :       return t;
     442                 :            :     }
     443                 :            :   else
     444                 :  275820886 :     return 0; // reached end of macro body
     445                 :            : }
     446                 :            : 
     447                 :            : const token*
     448                 :  269748149 : parser::scan_pp1 ()
     449                 :            : {
     450                 :  269748140 :   while (true)
     451                 :            :     {
     452                 :  269748149 :       const token* t = next_pp1 ();
     453         [ +  + ]:  269748149 :       if (t == 0) // EOF or end of macro body
     454                 :            :         {
     455         [ +  + ]:    2111502 :           if (pp1_state.empty()) // actual EOF
     456                 :     196263 :             return 0;
     457                 :            : 
     458                 :            :           // Exit macro and loop around to look for the next token.
     459                 :    1915239 :           pp1_activation* act = pp1_state.back();
     460         [ +  - ]:    1915239 :           pp1_state.pop_back(); delete act;
     461                 :    1915239 :           continue;
     462                 :            :         }
     463                 :            : 
     464                 :            :       // macro definition
     465 [ +  + ][ +  + ]:  267636647 :       if (t->type == tok_operator && t->content == "@define")
                 [ +  + ]
     466                 :            :         {
     467 [ +  - ][ -  + ]:      12955 :           if (!pp1_state.empty())
     468 [ #  # ][ #  # ]:          0 :             throw parse_error (_("'@define' forbidden inside macro body"), t);
     469 [ +  - ][ +  - ]:      12955 :           delete t;
     470                 :            : 
     471                 :            :           // handle macro definition
     472                 :            :           // (1) consume macro signature
     473         [ +  - ]:      12955 :           t = input.scan();
     474 [ +  + ][ -  + ]:      12955 :           if (! (t && t->type == tok_identifier))
     475 [ +  - ][ +  - ]:          1 :             throw parse_error (_("expected identifier"), t);
     476         [ +  - ]:      12954 :           string name = t->content;
     477                 :            : 
     478                 :            :           // check for redefinition of existing macro
     479 [ +  - ][ +  - ]:      12954 :           if (pp1_namespace.find(name) != pp1_namespace.end())
                 [ -  + ]
     480                 :            :             // TODOXXX use a slightly different chaining hack to also point to
     481                 :            :             // pp1_namespace[name]->tok, the site of the original definition?
     482 [ #  # ][ #  # ]:          0 :             throw parse_error (_F("attempt to redefine macro '@%s' in the same file", name.c_str ()), t);
                 [ #  # ]
     483                 :            :           // TODOXXX this is only really necessary if we want to leave open the possibility of statically-scoped semantics in the future...?
     484                 :            : 
     485                 :            :           // XXX this cascades into further parse errors as the
     486                 :            :           // parser tries to parse the remaining definition...
     487 [ +  - ][ +  + ]:      12954 :           if (name == "define")
     488 [ +  - ][ +  - ]:          1 :             throw parse_error (_("attempt to redefine '@define'"), t);
     489 [ +  - ][ +  - ]:      12953 :           if (input.atwords.count("@" + name))
         [ +  - ][ +  + ]
     490 [ +  - ][ +  - ]:          2 :             session.print_warning (_F("macro redefines built-in operator '@%s'", name.c_str()), t);
         [ +  - ][ +  - ]
     491                 :            : 
     492 [ +  - ][ +  - ]:      12953 :           macrodecl* decl = (pp1_namespace[name] = new macrodecl);
                 [ +  - ]
     493                 :      12953 :           decl->tok = t;
     494                 :            : 
     495                 :            :           // determine if the macro takes parameters
     496                 :      12953 :           bool saw_params = false;
     497         [ +  - ]:      12953 :           t = input.scan();
     498 [ +  + ][ +  - ]:      12953 :           if (t && t->type == tok_operator && t->content == "(")
         [ +  - ][ +  + ]
                 [ +  + ]
     499                 :            :             {
     500                 :       6479 :               saw_params = true;
     501                 :       2154 :               do
     502                 :            :                 {
     503 [ +  - ][ +  - ]:       8633 :                   delete t;
     504                 :            :                   
     505         [ +  - ]:       8633 :                   t = input.scan ();
     506 [ +  - ][ -  + ]:       8633 :                   if (! (t && t->type == tok_identifier))
     507 [ #  # ][ #  # ]:          0 :                     throw parse_error(_("expected identifier"), t);
     508         [ +  - ]:       8633 :                   decl->formal_args.push_back(t->content);
     509 [ +  - ][ +  - ]:       8633 :                   delete t;
     510                 :            :                   
     511         [ +  - ]:       8633 :                   t = input.scan ();
     512 [ +  - ][ +  - ]:       8633 :                   if (t && t->type == tok_operator && t->content == ",")
         [ +  - ][ +  + ]
                 [ +  + ]
     513                 :            :                     {
     514                 :       2154 :                       continue;
     515                 :            :                     }
     516 [ +  - ][ +  - ]:       6479 :                   else if (t && t->type == tok_operator && t->content == ")")
         [ +  - ][ +  - ]
                 [ +  - ]
     517                 :            :                     {
     518 [ +  - ][ +  - ]:       6479 :                       delete t;
     519         [ +  - ]:       6479 :                       t = input.scan();
     520                 :       6479 :                       break;
     521                 :            :                     }
     522                 :            :                   else
     523                 :            :                     {
     524 [ #  # ][ #  # ]:       6479 :                       throw parse_error (_("expected ',' or ')'"), t);
     525                 :            :                     }
     526                 :            :                 }
     527                 :            :               while (true);
     528                 :            :             }
     529                 :            : 
     530                 :            :           // (2) identify & consume macro body
     531 [ +  + ][ +  - ]:      12953 :           if (! (t && t->type == tok_operator && t->content == "%("))
         [ +  - ][ -  + ]
                 [ +  + ]
     532                 :            :             {
     533         [ -  + ]:          1 :               if (saw_params)
     534 [ #  # ][ #  # ]:          0 :                 throw parse_error (_("expected '%('"), t);
     535                 :            :               else
     536 [ +  - ][ +  - ]:          1 :                 throw parse_error (_("expected '%(' or '('"), t);
     537                 :            :             }
     538 [ +  - ][ +  - ]:      12952 :           delete t;
     539                 :            : 
     540         [ +  - ]:      12952 :           t = slurp_pp1_body (decl->body);
     541         [ +  + ]:      12952 :           if (!t)
     542 [ +  - ][ +  - ]:          2 :             throw parse_error (_("incomplete macro definition - missing '%)'"), decl->tok);
     543 [ +  - ][ +  - ]:      12950 :           delete t;
     544                 :            : 
     545                 :            :           // Now loop around to look for a real token.
     546         [ +  - ]:      12955 :           continue;
     547                 :            :         }
     548                 :            : 
     549                 :            :       // (potential) macro invocation
     550 [ +  + ][ +  + ]:  267623692 :       if (t->type == tok_operator && t->content[0] == '@')
                 [ +  + ]
     551                 :            :         {
     552         [ +  - ]:    3601015 :           string name = t->content.substr(1); // strip initial '@'
     553                 :            : 
     554                 :            :           // check if name refers to a real parameter or macro
     555                 :            :           macrodecl* decl;
     556 [ +  - ][ +  + ]:    3601015 :           pp1_activation* act = pp1_state.empty() ? 0 : pp1_state.back();
                 [ +  - ]
     557 [ +  + ][ +  - ]:    3601015 :           if (act && act->params.find(name) != act->params.end())
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
           [ +  +  #  #  
                   #  # ]
     558         [ +  - ]:    1389578 :             decl = act->params[name];
     559         [ +  + ]:    6188377 :           else if (!(act && act->curr_macro->context == ctx_library)
           [ +  +  +  + ]
                 [ +  + ]
     560 [ +  - ][ +  - ]:    3976940 :                    && pp1_namespace.find(name) != pp1_namespace.end())
         [ +  + ][ +  + ]
           [ #  #  #  # ]
     561         [ +  - ]:      66807 :             decl = pp1_namespace[name];
     562         [ +  + ]:    2144630 :           else if (session.library_macros.find(name)
     563 [ +  - ][ +  - ]:    2144630 :                    != session.library_macros.end())
     564         [ +  - ]:     458858 :             decl = session.library_macros[name];
     565                 :            :           else // this is an ordinary @operator
     566                 :    1685772 :             return t;
     567                 :            : 
     568                 :            :           // handle macro invocation
     569 [ +  - ][ +  - ]:    1915243 :           pp1_activation *new_act = new pp1_activation(*t, decl);
         [ +  - ][ +  - ]
     570                 :    1915243 :           unsigned num_params = decl->formal_args.size();
     571                 :            : 
     572                 :            :           // (1a) restore parameter invocation closure
     573 [ +  + ][ +  - ]:    1915243 :           if (num_params == 0 && decl->is_closure())
         [ +  + ][ +  + ]
     574                 :            :             {
     575                 :            :               // NB: decl->parent_act is always safe since the
     576                 :            :               // parameter decl (if any) comes from an activation
     577                 :            :               // record which deeper in the stack than new_act.
     578                 :            : 
     579                 :            :               // decl is a macro parameter which must be evaluated in
     580                 :            :               // the context of the original point of invocation:
     581         [ +  - ]:     142166 :               new_act->params = ((pp_macrodecl*)decl)->parent_act->params;
     582                 :     142166 :               goto expand;
     583                 :            :             }
     584                 :            : 
     585                 :            :           // (1b) consume macro parameters (if any)
     586         [ +  + ]:    1773077 :           if (num_params == 0)
     587                 :    1275420 :             goto expand;
     588                 :            : 
     589                 :            :           // for simplicity, we do not allow macro constructs here
     590                 :            :           // -- if we did, we'd have to recursively call scan_pp1()
     591         [ +  - ]:     497657 :           t = next_pp1 ();
     592 [ +  - ][ +  - ]:     497657 :           if (! (t && t->type == tok_operator && t->content == "("))
         [ +  - ][ +  + ]
                 [ +  + ]
     593                 :            :             {
     594 [ +  - ][ +  - ]:          1 :               delete new_act;
     595                 :          1 :               throw parse_error (_F(ngettext
     596                 :            :                                     ("expected '(' in invocation of macro '@%s'"
     597                 :            :                                      " taking %d parameter",
     598                 :            :                                      "expected '(' in invocation of macro '@%s'"
     599                 :            :                                      " taking %d parameters",
     600 [ +  - ][ +  - ]:          2 :                                      num_params), name.c_str(), num_params), t);
                 [ +  - ]
     601                 :            :             }
     602                 :            : 
     603                 :            :           // XXX perhaps parse/count the full number of params,
     604                 :            :           // so we can say "expected x, found y params" on error?
     605         [ +  + ]:    1441243 :           for (unsigned i = 0; i < num_params; i++)
     606                 :            :             {
     607 [ +  - ][ +  - ]:     943590 :               delete t;
     608                 :            : 
     609                 :            :               // create parameter closure
     610         [ +  - ]:     943590 :               string param_name = decl->formal_args[i];
     611         [ +  - ]:     943590 :               pp_macrodecl* p = (new_act->params[param_name]
     612 [ +  - ][ +  - ]:     943590 :                                  = new pp_macrodecl);
     613 [ +  - ][ +  - ]:     943590 :               p->tok = new token(*new_act->tok);
     614                 :     943590 :               p->parent_act = act;
     615                 :            :               // NB: *new_act->tok points to invocation, act is NULL at top level
     616                 :            : 
     617         [ +  - ]:     943590 :               t = slurp_pp1_param (p->body);
     618                 :            : 
     619                 :            :               // check correct usage of ',' or ')'
     620         [ +  + ]:     943590 :               if (t == 0) // hit unexpected EOF or end of macro
     621                 :            :                 {
     622                 :            :                   // XXX could we pop the stack and continue parsing
     623                 :            :                   // the invocation, allowing macros to construct new
     624                 :            :                   // invocations in piecemeal fashion??
     625 [ +  - ][ +  - ]:          2 :                   const token* orig_t = new token(*new_act->tok);
     626 [ +  - ][ +  - ]:          2 :                   delete new_act;
     627 [ +  - ][ +  - ]:          2 :                   throw parse_error (_("could not find end of macro invocation"), orig_t);
     628                 :            :                 }
     629 [ +  - ][ +  - ]:     943588 :               if (t->type == tok_operator && t->content == ",")
         [ +  + ][ +  + ]
     630                 :            :                 {
     631         [ +  + ]:     445935 :                   if (i + 1 == num_params)
     632                 :            :                     {
     633 [ +  - ][ +  - ]:          1 :                       delete new_act;
     634 [ +  - ][ +  - ]:          1 :                       throw parse_error (_F("too many parameters for macro '@%s' (expected %d)", name.c_str(), num_params), t);
                 [ +  - ]
     635                 :            :                     }
     636                 :            :                 }
     637 [ +  - ][ +  - ]:     497653 :               else if (t->type == tok_operator && t->content == ")")
         [ +  - ][ +  - ]
     638                 :            :                 {
     639         [ -  + ]:     497653 :                   if (i + 1 != num_params)
     640                 :            :                     {
     641 [ #  # ][ #  # ]:          0 :                       delete new_act;
     642 [ #  # ][ #  # ]:          0 :                       throw parse_error (_F("too few parameters for macro '@%s' (expected %d)", name.c_str(), num_params), t);
                 [ #  # ]
     643                 :            :                     }
     644                 :            :                 }
     645                 :            :               else
     646                 :            :                 {
     647                 :            :                   // XXX this is, incidentally, impossible
     648 [ #  # ][ #  # ]:          0 :                   delete new_act;
     649 [ #  # ][ #  # ]:          0 :                   throw parse_error(_("expected ',' or ')' after macro parameter"), t);
     650                 :            :                 }
     651         [ +  - ]:     943590 :             }
     652                 :            : 
     653 [ +  - ][ +  - ]:     497653 :           delete t;
     654                 :            : 
     655                 :            :           // (2) set up macro expansion
     656                 :            :         expand:
     657         [ +  - ]:    1915239 :           pp1_state.push_back (new_act);
     658                 :            : 
     659                 :            :           // Now loop around to look for a real token.
     660 [ +  - ][ +  + ]:    3601015 :           continue;
     661                 :            :         }
     662                 :            : 
     663                 :            :       // Otherwise, we have an ordinary token.
     664                 :  264022677 :       return t;
     665                 :            :     }
     666                 :            : }
     667                 :            : 
     668                 :            : // Consume a single macro invocation's parameters, heeding nested ( )
     669                 :            : // brackets and stopping on an unbalanced ')' or an unbracketed ','
     670                 :            : // (and returning the final separator token).
     671                 :            : const token*
     672                 :     943590 : parser::slurp_pp1_param (vector<const token*>& param)
     673                 :            : {
     674                 :     943590 :   const token* t = 0;
     675                 :     943590 :   unsigned nesting = 0;
     676                 :    3394960 :   do
     677                 :            :     {
     678         [ +  - ]:    4338550 :       t = next_pp1 ();
     679                 :            : 
     680         [ +  + ]:    4338550 :       if (!t)
     681                 :          2 :         break;
     682 [ +  + ][ +  - ]:    4338548 :       if (t->type == tok_operator && t->content == "(")
         [ +  + ][ +  + ]
     683                 :     217555 :         ++nesting;
     684 [ +  + ][ +  + ]:    4120993 :       else if (nesting && t->type == tok_operator && t->content == ")")
         [ +  - ][ +  + ]
                 [ +  + ]
     685                 :     217555 :         --nesting;
     686 [ +  + ][ +  + ]:    6503633 :       else if (!nesting && t->type == tok_operator
         [ +  + ][ +  + ]
                 [ +  + ]
     687 [ +  - ][ +  - ]:    2600195 :                && (t->content == ")" || t->content == ","))
     688                 :     943588 :         break;
     689         [ +  - ]:    3394960 :       param.push_back(t);
     690                 :            :     }
     691                 :            :   while (true);
     692                 :     943590 :   return t; // report ")" or "," or NULL
     693                 :            : }
     694                 :            : 
     695                 :            : 
     696                 :            : // Consume a macro declaration's body, heeding nested %( %) brackets.
     697                 :            : const token*
     698                 :      12952 : parser::slurp_pp1_body (vector<const token*>& body)
     699                 :            : {
     700                 :      12952 :   const token* t = 0;
     701                 :      12952 :   unsigned nesting = 0;
     702                 :    1223578 :   do
     703                 :            :     {
     704         [ +  - ]:    1236530 :       t = next_pp1 ();
     705                 :            : 
     706         [ +  + ]:    1236530 :       if (!t)
     707                 :          2 :         break;
     708 [ +  + ][ +  - ]:    1236528 :       if (t->type == tok_operator && t->content == "%(")
         [ +  + ][ +  + ]
     709                 :          2 :         ++nesting;
     710 [ +  + ][ +  + ]:    1236526 :       else if (nesting && t->type == tok_operator && t->content == "%)")
         [ +  - ][ +  + ]
                 [ +  + ]
     711                 :          2 :         --nesting;
     712 [ +  + ][ +  + ]:    1236524 :       else if (!nesting && t->type == tok_operator && t->content == "%)")
         [ +  - ][ +  + ]
                 [ +  + ]
     713                 :      12950 :         break;
     714         [ +  - ]:    1223578 :       body.push_back(t);
     715                 :            :     }
     716                 :            :   while (true);
     717                 :      12952 :   return t; // report final "%)" or NULL
     718                 :            : }
     719                 :            : 
     720                 :            : // Used for parsing .stpm files.
     721                 :            : stapfile*
     722                 :       4308 : parser::parse_library_macros ()
     723                 :            : {
     724         [ +  - ]:       4308 :   stapfile* f = new stapfile;
     725                 :       4308 :   input.set_current_file (f);
     726                 :            : 
     727                 :            :   try
     728                 :            :     {
     729         [ +  - ]:       4308 :       const token* t = scan_pp1 ();
     730                 :            : 
     731                 :            :       // Currently we only take objection to macro invocations if they
     732                 :            :       // produce a non-whitespace token after being expanded.
     733                 :            : 
     734                 :            :       // XXX should we prevent macro invocations even if they expand to empty??
     735                 :            : 
     736         [ -  + ]:       4308 :       if (t != 0)
     737 [ #  # ][ #  # ]:          0 :         throw parse_error (_F("library macro file '%s' contains non-@define construct", input_name.c_str()), t);
                 [ #  # ]
     738                 :            : 
     739                 :            :       // We need to first check whether *any* of the macros are duplicates,
     740                 :            :       // then commit to including the entire file in the global namespace
     741                 :            :       // (or not). Yuck.
     742 [ +  - ][ +  + ]:      17232 :       for (map<string, macrodecl*>::iterator it = pp1_namespace.begin();
     743         [ +  - ]:       8616 :            it != pp1_namespace.end(); it++)
     744                 :            :         {
     745 [ +  - ][ +  - ]:       4308 :           string name = it->first;
     746                 :            : 
     747 [ +  - ][ +  - ]:       4308 :           if (session.library_macros.find(name) != session.library_macros.end())
                 [ -  + ]
     748                 :            :             {
     749                 :            :               // XXX ugly hack simulates chaining
     750 [ #  # ][ #  # ]:          0 :               parse_error* er1 = new parse_error (_F("duplicate definition of library macro '%s'", name.c_str()), it->second->tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     751 [ #  # ][ #  # ]:          0 :               parse_error* er2 = new parse_error (_("location of original definition was"), session.library_macros[name]->tok);
         [ #  # ][ #  # ]
                 [ #  # ]
     752         [ #  # ]:          0 :               print_error (*er1);
     753         [ #  # ]:          0 :               print_error (*er2);
     754 [ #  # ][ #  # ]:          0 :               delete er1; delete er2;
     755                 :            : 
     756 [ #  # ][ #  # ]:          0 :               delete f;
     757                 :       4308 :               return 0;
     758                 :            :             }
     759 [ +  - ][ +  - ]:       4308 :         }
     760                 :            : 
     761                 :            :     }
     762         [ #  # ]:            :   catch (const parse_error& pe)
     763                 :            :     {
     764         [ #  # ]:            :       print_error (pe);
     765   [ #  #  #  # ]:            :       delete f;
     766                 :            :       return 0;
     767                 :            :     }
     768                 :            : 
     769                 :            :   // If no errors, include the entire file.  Note how this is outside
     770                 :            :   // of the try-catch block -- no errors possible.
     771 [ +  - ][ +  + ]:      17232 :   for (map<string, macrodecl*>::iterator it = pp1_namespace.begin();
     772         [ +  - ]:       8616 :        it != pp1_namespace.end(); it++)
     773                 :            :     {
     774 [ +  - ][ +  - ]:       4308 :       string name = it->first;
     775                 :            :       
     776 [ +  - ][ +  - ]:       4308 :       session.library_macros[name] = it->second;
     777         [ +  - ]:       4308 :       session.library_macros[name]->context = ctx_library;
     778                 :            :       // TODOXXX be sure declaration is retained and not deleted
     779         [ +  - ]:       4308 :     }
     780                 :            : 
     781                 :       4308 :   return f;
     782                 :            : }
     783                 :            : 
     784                 :            : // Second pass - preprocessor conditional expansion.
     785                 :            : //
     786                 :            : // The basic form is %( CONDITION %? THEN-TOKENS %: ELSE-TOKENS %)
     787                 :            : // where CONDITION is: kernel_v[r] COMPARISON-OP "version-string"
     788                 :            : //                 or: arch COMPARISON-OP "arch-string"
     789                 :            : //                 or: systemtap_v COMPARISON-OP "version-string"
     790                 :            : //                 or: systemtap_privilege COMPARISON-OP "privilege-string"
     791                 :            : //                 or: CONFIG_foo COMPARISON-OP "config-string"
     792                 :            : //                 or: CONFIG_foo COMPARISON-OP number
     793                 :            : //                 or: CONFIG_foo COMPARISON-OP CONFIG_bar
     794                 :            : //                 or: "string1" COMPARISON-OP "string2"
     795                 :            : //                 or: number1 COMPARISON-OP number2
     796                 :            : // The %: ELSE-TOKENS part is optional.
     797                 :            : //
     798                 :            : // e.g. %( kernel_v > "2.5" %? "foo" %: "baz" %)
     799                 :            : // e.g. %( arch != "i?86" %? "foo" %: "baz" %)
     800                 :            : // e.g. %( CONFIG_foo %? "foo" %: "baz" %)
     801                 :            : //
     802                 :            : // Up to an entire %( ... %) expression is processed by a single call
     803                 :            : // to this function.  Tokens included by any nested conditions are
     804                 :            : // enqueued in a private vector.
     805                 :            : 
     806                 :     295568 : bool eval_pp_conditional (systemtap_session& s,
     807                 :            :                           const token* l, const token* op, const token* r)
     808                 :            : {
     809 [ +  + ][ +  +  :     634094 :   if (l->type == tok_identifier && (l->content == "kernel_v" ||
             +  +  +  + ]
                 [ +  + ]
     810                 :     170349 :                                     l->content == "kernel_vr" || 
     811                 :     168177 :                                     l->content == "systemtap_v"))
     812                 :            :     {
     813         [ +  + ]:     153107 :       if (! (r->type == tok_string))
     814 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected string literal"), r);
     815                 :            : 
     816         [ +  - ]:     153106 :       string target_kernel_vr = s.kernel_release;
     817         [ +  - ]:     153106 :       string target_kernel_v = s.kernel_base_release;
     818         [ +  - ]:     153106 :       string target;
     819                 :            : 
     820 [ +  - ][ +  + ]:     153106 :       if (l->content == "kernel_v") target = target_kernel_v;
                 [ +  - ]
     821 [ +  - ][ +  + ]:     103428 :       else if (l->content == "kernel_vr") target = target_kernel_vr;
                 [ +  - ]
     822 [ +  - ][ +  - ]:     101256 :       else if (l->content == "systemtap_v") target = s.compatible;
                 [ +  - ]
     823                 :          0 :       else assert (0);
     824                 :            : 
     825         [ +  - ]:     153106 :       string query = r->content;
     826         [ +  - ]:     153106 :       bool rhs_wildcard = (strpbrk (query.c_str(), "*?[") != 0);
     827                 :            : 
     828                 :            :       // collect acceptable strverscmp results.
     829                 :            :       int rvc_ok1, rvc_ok2;
     830                 :     153106 :       bool wc_ok = false;
     831 [ +  - ][ +  - ]:     153106 :       if (op->type == tok_operator && op->content == "<=")
         [ +  + ][ +  + ]
     832                 :      96950 :         { rvc_ok1 = -1; rvc_ok2 = 0; }
     833 [ +  - ][ +  - ]:      56156 :       else if (op->type == tok_operator && op->content == ">=")
         [ +  + ][ +  + ]
     834                 :      36640 :         { rvc_ok1 = 1; rvc_ok2 = 0; }
     835 [ +  - ][ +  - ]:      19516 :       else if (op->type == tok_operator && op->content == "<")
         [ +  + ][ +  + ]
     836                 :      15146 :         { rvc_ok1 = -1; rvc_ok2 = -1; }
     837 [ +  - ][ +  - ]:       4370 :       else if (op->type == tok_operator && op->content == ">")
         [ +  + ][ +  + ]
     838                 :       2195 :         { rvc_ok1 = 1; rvc_ok2 = 1; }
     839 [ +  - ][ +  - ]:       2175 :       else if (op->type == tok_operator && op->content == "==")
         [ +  + ][ +  + ]
     840                 :       2164 :         { rvc_ok1 = 0; rvc_ok2 = 0; wc_ok = true; }
     841 [ +  - ][ +  - ]:         11 :       else if (op->type == tok_operator && op->content == "!=")
         [ +  + ][ +  + ]
     842                 :         10 :         { rvc_ok1 = -1; rvc_ok2 = 1; wc_ok = true; }
     843                 :            :       else
     844 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected comparison operator"), op);
     845                 :            : 
     846 [ +  + ][ -  + ]:     153105 :       if ((!wc_ok) && rhs_wildcard)
     847 [ #  # ][ #  # ]:          0 :         throw parse_error (_("wildcard not allowed with order comparison operators"), op);
     848                 :            : 
     849         [ +  + ]:     153105 :       if (rhs_wildcard)
     850                 :            :         {
     851                 :            :           int rvc_result = fnmatch (query.c_str(), target.c_str(),
     852 [ +  - ][ +  - ]:          8 :                                     FNM_NOESCAPE); // spooky
                 [ +  - ]
     853         [ +  - ]:          8 :           bool badness = (rvc_result == 0) ^ (op->content == "==");
     854                 :          8 :           return !badness;
     855                 :            :         }
     856                 :            :       else
     857                 :            :         {
     858 [ +  - ][ +  - ]:     153097 :           int rvc_result = strverscmp (target.c_str(), query.c_str());
     859                 :            :           // normalize rvc_result
     860         [ +  + ]:     153097 :           if (rvc_result < 0) rvc_result = -1;
     861         [ +  + ]:     153097 :           if (rvc_result > 0) rvc_result = 1;
     862 [ +  + ][ +  + ]:     153097 :           return (rvc_result == rvc_ok1 || rvc_result == rvc_ok2);
     863 [ +  - ][ +  - ]:     153107 :         }
         [ +  - ][ +  - ]
     864                 :            :     }
     865 [ +  + ][ +  + ]:     142461 :   else if (l->type == tok_identifier && l->content == "systemtap_privilege")
                 [ +  + ]
     866                 :            :     {
     867                 :            :       string target_privilege =
     868                 :            :         /* XXX perhaps include a "guru" state */
     869         [ +  - ]:       2145 :         pr_contains(s.privilege, pr_stapdev) ? "stapdev"
     870         [ +  - ]:        151 :         : pr_contains(s.privilege, pr_stapsys) ? "stapsys"
     871         [ +  - ]:         93 :         : pr_contains(s.privilege, pr_stapusr) ? "stapusr"
     872 [ +  + ][ +  + ]:       2389 :         : "none"; /* should be impossible -- s.privilege always one of above */
         [ +  - ][ +  - ]
     873 [ +  - ][ -  + ]:       2145 :       assert(target_privilege != "none");
     874                 :            : 
     875         [ -  + ]:       2145 :       if (! (r->type == tok_string))
     876 [ #  # ][ #  # ]:          0 :         throw parse_error (_("expected string literal"), r);
     877         [ +  - ]:       2145 :       string query_privilege = r->content;
     878                 :            : 
     879         [ +  - ]:       2145 :       bool nomatch = (target_privilege != query_privilege);
     880                 :            : 
     881                 :            :       bool result;
     882 [ +  - ][ +  - ]:       2145 :       if (op->type == tok_operator && op->content == "==")
         [ +  + ][ +  + ]
     883                 :          1 :         result = !nomatch;
     884 [ +  - ][ +  - ]:       2144 :       else if (op->type == tok_operator && op->content == "!=")
         [ +  - ][ +  - ]
     885                 :       2144 :         result = nomatch;
     886                 :            :       else
     887 [ #  # ][ #  # ]:          0 :         throw parse_error (_("expected '==' or '!='"), op);
     888                 :            :       /* XXX perhaps allow <= >= and similar comparisons */
     889                 :            : 
     890 [ +  - ][ +  - ]:       2145 :       return result;
     891                 :            :     }
     892 [ +  + ][ +  + ]:     140316 :   else if (l->type == tok_identifier && l->content == "arch")
                 [ +  + ]
     893                 :            :     {
     894         [ +  - ]:      34507 :       string target_architecture = s.architecture;
     895         [ +  + ]:      34507 :       if (! (r->type == tok_string))
     896 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected string literal"), r);
     897         [ +  - ]:      34506 :       string query_architecture = r->content;
     898                 :            : 
     899                 :            :       int nomatch = fnmatch (query_architecture.c_str(),
     900                 :            :                              target_architecture.c_str(),
     901 [ +  - ][ +  - ]:      34506 :                              FNM_NOESCAPE); // still spooky
                 [ +  - ]
     902                 :            : 
     903                 :            :       bool result;
     904 [ +  - ][ +  - ]:      34506 :       if (op->type == tok_operator && op->content == "==")
         [ +  + ][ +  + ]
     905                 :       8650 :         result = !nomatch;
     906 [ +  - ][ +  - ]:      25856 :       else if (op->type == tok_operator && op->content == "!=")
         [ +  + ][ +  + ]
     907                 :      25855 :         result = nomatch;
     908                 :            :       else
     909 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected '==' or '!='"), op);
     910                 :            : 
     911 [ +  - ][ +  - ]:      34507 :       return result;
     912                 :            :     }
     913 [ +  + ][ +  + ]:     105809 :   else if (l->type == tok_identifier && startswith(l->content, "CONFIG_"))
                 [ +  + ]
     914                 :            :     {
     915         [ +  + ]:      30267 :       if (r->type == tok_string)
     916                 :            :         {
     917 [ +  - ][ +  - ]:      23787 :           string lhs = s.kernel_config[l->content]; // may be empty
     918         [ +  - ]:      23787 :           string rhs = r->content;
     919                 :            : 
     920 [ +  - ][ +  - ]:      23787 :           int nomatch = fnmatch (rhs.c_str(), lhs.c_str(), FNM_NOESCAPE); // still spooky
                 [ +  - ]
     921                 :            : 
     922                 :            :           bool result;
     923 [ +  - ][ +  - ]:      23787 :           if (op->type == tok_operator && op->content == "==")
         [ +  + ][ +  + ]
     924                 :      23779 :             result = !nomatch;
     925 [ +  - ][ +  - ]:          8 :           else if (op->type == tok_operator && op->content == "!=")
         [ +  - ][ +  - ]
     926                 :          8 :             result = nomatch;
     927                 :            :           else
     928 [ #  # ][ #  # ]:          0 :             throw parse_error (_("expected '==' or '!='"), op);
     929                 :            : 
     930 [ +  - ][ +  - ]:      23787 :           return result;
     931                 :            :         }
     932         [ +  + ]:       6480 :       else if (r->type == tok_number)
     933                 :            :         {
     934 [ +  - ][ +  - ]:          8 :           const char* startp = s.kernel_config[l->content].c_str ();
     935                 :          8 :           char* endp = (char*) startp;
     936                 :          8 :           errno = 0;
     937                 :          8 :           int64_t lhs = (int64_t) strtoll (startp, & endp, 0);
     938 [ +  - ][ +  - ]:          8 :           if (errno == ERANGE || errno == EINVAL || *endp != '\0')
                 [ -  + ]
     939 [ #  # ][ #  # ]:          0 :             throw parse_error ("Config option value not a number", l);
     940                 :            : 
     941         [ +  - ]:          8 :           int64_t rhs = lex_cast<int64_t>(r->content);
     942         [ +  - ]:          8 :           return eval_comparison (lhs, op, rhs);
     943                 :            :         }
     944   [ +  -  +  - ]:      12944 :       else if (r->type == tok_identifier
                 [ +  - ]
     945                 :       6472 :                && startswith(r->content, "CONFIG_"))
     946                 :            :         {
     947                 :            :           // First try to convert both to numbers,
     948                 :            :           // otherwise threat both as strings.
     949 [ +  - ][ +  - ]:       6472 :           const char* startp = s.kernel_config[l->content].c_str ();
     950                 :       6472 :           char* endp = (char*) startp;
     951                 :       6472 :           errno = 0;
     952                 :       6472 :           int64_t val = (int64_t) strtoll (startp, & endp, 0);
     953 [ +  - ][ +  - ]:       6472 :           if (errno != ERANGE && errno != EINVAL && *endp == '\0')
                 [ +  + ]
     954                 :            :             {
     955                 :       6470 :               int64_t lhs = val;
     956 [ +  - ][ +  - ]:       6470 :               startp = s.kernel_config[r->content].c_str ();
     957                 :       6470 :               endp = (char*) startp;
     958                 :       6470 :               errno = 0;
     959                 :       6470 :               int64_t rhs = (int64_t) strtoll (startp, & endp, 0);
     960 [ +  - ][ +  - ]:       6470 :               if (errno != ERANGE && errno != EINVAL && *endp == '\0')
                 [ +  + ]
     961         [ +  - ]:       6470 :                 return eval_comparison (lhs, op, rhs);
     962                 :            :             }
     963                 :            : 
     964 [ +  - ][ +  - ]:          4 :           string lhs = s.kernel_config[l->content];
     965 [ +  - ][ +  - ]:          4 :           string rhs = s.kernel_config[r->content];
     966 [ +  - ][ +  - ]:       6472 :           return eval_comparison (lhs, op, rhs);
                 [ +  - ]
     967                 :            :         }
     968                 :            :       else
     969 [ #  # ][ #  # ]:          0 :         throw parse_error (_("expected string, number literal or other CONFIG_... as right side operand"), r);
     970                 :            :     }
     971 [ +  + ][ +  + ]:      75542 :   else if (l->type == tok_string && r->type == tok_string)
     972                 :            :     {
     973         [ +  - ]:          8 :       string lhs = l->content;
     974         [ +  - ]:          8 :       string rhs = r->content;
     975 [ +  - ][ +  - ]:          8 :       return eval_comparison (lhs, op, rhs);
                 [ +  - ]
     976                 :            :       // NB: no wildcarding option here
     977                 :            :     }
     978 [ +  + ][ +  + ]:      75534 :   else if (l->type == tok_number && r->type == tok_number)
     979                 :            :     {
     980         [ +  - ]:      75528 :       int64_t lhs = lex_cast<int64_t>(l->content);
     981         [ +  - ]:      75528 :       int64_t rhs = lex_cast<int64_t>(r->content);
     982         [ +  - ]:      75528 :       return eval_comparison (lhs, op, rhs);
     983                 :            :       // NB: no wildcarding option here
     984                 :            :     }
     985 [ +  + ][ +  - ]:          6 :   else if (l->type == tok_string && r->type == tok_number
                 [ +  - ]
     986                 :            :             && op->type == tok_operator)
     987 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected string literal as right value"), r);
     988 [ +  + ][ +  - ]:          5 :   else if (l->type == tok_number && r->type == tok_string
                 [ +  - ]
     989                 :            :             && op->type == tok_operator)
     990 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected number literal as right value"), r);
     991                 :            : 
     992                 :            :   else
     993                 :          4 :     throw parse_error (_("expected 'arch' or 'kernel_v' or 'kernel_vr' or 'CONFIG_...'\n"
     994 [ +  - ][ +  - ]:     295562 :                        "             or comparison between strings or integers"), l);
     995                 :            : }
     996                 :            : 
     997                 :            : 
     998                 :            : // Only tokens corresponding to the TRUE statement must be expanded
     999                 :            : const token*
    1000                 :  260812752 : parser::scan_pp ()
    1001                 :            : {
    1002                 :  260812710 :   while (true)
    1003                 :            :     {
    1004                 :  260812752 :       pp_state_t pp = PP_NONE;
    1005         [ +  + ]:  260812752 :       if (!pp_state.empty())
    1006                 :    2094058 :         pp = pp_state.back().second;
    1007                 :            : 
    1008                 :  260812752 :       const token* t = 0;
    1009 [ +  + ][ +  + ]:  260812752 :       if (pp == PP_SKIP_THEN || pp == PP_SKIP_ELSE)
    1010                 :     221870 :         t = skip_pp ();
    1011                 :            :       else
    1012                 :  260590882 :         t = scan_pp1 ();
    1013                 :            : 
    1014         [ +  + ]:  260812743 :       if (t == 0) // EOF
    1015                 :            :         {
    1016         [ +  + ]:     191954 :           if (pp != PP_NONE)
    1017                 :            :             {
    1018                 :          3 :               t = pp_state.back().first;
    1019                 :          3 :               pp_state.pop_back(); // so skip_some doesn't keep trying to close this
    1020                 :            :               //TRANSLATORS: 'conditional' meaning 'conditional preprocessing'
    1021 [ +  - ][ +  - ]:          3 :               throw parse_error (_("incomplete conditional at end of file"), t);
    1022                 :            :             }
    1023                 :     191951 :           return t;
    1024                 :            :         }
    1025                 :            : 
    1026                 :            :       // misplaced preprocessor "then"
    1027 [ +  + ][ +  + ]:  260620789 :       if (t->type == tok_operator && t->content == "%?")
                 [ +  + ]
    1028 [ +  - ][ +  - ]:          9 :         throw parse_error (_("incomplete conditional - missing '%('"), t);
    1029                 :            : 
    1030                 :            :       // preprocessor "else"
    1031 [ +  + ][ +  + ]:  260620780 :       if (t->type == tok_operator && t->content == "%:")
                 [ +  + ]
    1032                 :            :         {
    1033         [ -  + ]:      64814 :           if (pp == PP_NONE)
    1034 [ #  # ][ #  # ]:          0 :             throw parse_error (_("incomplete conditional - missing '%('"), t);
    1035 [ +  - ][ -  + ]:      64814 :           if (pp == PP_KEEP_ELSE || pp == PP_SKIP_ELSE)
    1036 [ #  # ][ #  # ]:          0 :             throw parse_error (_("invalid conditional - duplicate '%:'"), t);
    1037                 :            :           // XXX: here and elsewhere, error cascades might be avoided
    1038                 :            :           // by dropping tokens until we reach the closing %)
    1039                 :            : 
    1040                 :      64814 :           pp_state.back().second = (pp == PP_KEEP_THEN) ?
    1041         [ +  + ]:      64814 :                                    PP_SKIP_ELSE : PP_KEEP_ELSE;
    1042         [ +  - ]:      64814 :           delete t;
    1043                 :      64814 :           continue;
    1044                 :            :         }
    1045                 :            : 
    1046                 :            :       // preprocessor close
    1047 [ +  + ][ +  + ]:  260555966 :       if (t->type == tok_operator && t->content == "%)")
                 [ +  + ]
    1048                 :            :         {
    1049         [ +  + ]:     280436 :           if (pp == PP_NONE)
    1050 [ +  - ][ +  - ]:          9 :             throw parse_error (_("incomplete conditional - missing '%('"), t);
    1051         [ +  - ]:     280427 :           delete pp_state.back().first;
    1052         [ +  - ]:     280427 :           delete t; //this is the closing bracket
    1053                 :     280427 :           pp_state.pop_back();
    1054                 :     280427 :           continue;
    1055                 :            :         }
    1056                 :            : 
    1057 [ +  + ][ +  + ]:  260275530 :       if (! (t->type == tok_operator && t->content == "%(")) // ordinary token
                 [ +  + ]
    1058                 :  259995088 :         return t;
    1059                 :            : 
    1060                 :            :       // We have a %( - it's time to throw a preprocessing party!
    1061                 :            : 
    1062                 :     280442 :       bool result = false;
    1063                 :     280442 :       bool and_result = true;
    1064                 :     280442 :       const token *n = NULL;
    1065                 :      15127 :       do {
    1066                 :            :         const token *l, *op, *r;
    1067                 :     295569 :         l = scan_pp1 ();
    1068                 :     295569 :         op = scan_pp1 ();
    1069                 :     295569 :         r = scan_pp1 ();
    1070 [ +  - ][ +  - ]:     295569 :         if (l == 0 || op == 0 || r == 0)
                 [ +  + ]
    1071 [ +  - ][ +  - ]:          1 :           throw parse_error (_("incomplete condition after '%('"), t);
    1072                 :            :         // NB: consider generalizing to consume all tokens until %?, and
    1073                 :            :         // passing that as a vector to an evaluator.
    1074                 :            : 
    1075                 :            :         // Do not evaluate the condition if we haven't expanded everything.
    1076                 :            :         // This may occur when having several recursive conditionals.
    1077                 :     295568 :         and_result &= eval_pp_conditional (session, l, op, r);
    1078         [ +  + ]:     295558 :         if(l->content=="systemtap_v")
    1079                 :     101256 :           systemtap_v_seen=r;
    1080                 :            : 
    1081                 :            :         else
    1082         [ +  - ]:     194302 :           delete r;
    1083                 :            : 
    1084         [ +  - ]:     295558 :         delete l;
    1085         [ +  - ]:     295558 :         delete op;
    1086         [ +  + ]:     295558 :         delete n;
    1087                 :            : 
    1088                 :     295558 :         n = scan_pp1 ();
    1089 [ +  - ][ +  - ]:     295558 :         if (n && n->type == tok_operator && n->content == "&&")
         [ +  + ][ +  + ]
    1090                 :      12957 :           continue;
    1091                 :     282601 :         result |= and_result;
    1092                 :     282601 :         and_result = true;
    1093 [ +  - ][ +  - ]:     282601 :         if (! (n && n->type == tok_operator && n->content == "||"))
         [ +  + ][ +  + ]
    1094                 :     280431 :           break;
    1095                 :            :       } while (true);
    1096                 :            : 
    1097                 :            :       /*
    1098                 :            :       clog << "PP eval (" << *t << ") == " << result << endl;
    1099                 :            :       */
    1100                 :            : 
    1101                 :     280431 :       const token *m = n;
    1102 [ +  - ][ +  - ]:     280431 :       if (! (m && m->type == tok_operator && m->content == "%?"))
         [ +  + ][ +  + ]
    1103 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected '%?' marker for conditional"), t);
    1104         [ +  - ]:     280430 :       delete m; // "%?"
    1105                 :            : 
    1106         [ +  + ]:     280430 :       pp = result ? PP_KEEP_THEN : PP_SKIP_THEN;
    1107         [ +  - ]:     280430 :       pp_state.push_back (make_pair (t, pp));
    1108                 :            : 
    1109                 :            :       // Now loop around to look for a real token.
    1110                 :            :     }
    1111                 :            : }
    1112                 :            : 
    1113                 :            : 
    1114                 :            : // Skip over tokens and any errors, heeding
    1115                 :            : // only nested preprocessor starts and ends.
    1116                 :            : const token*
    1117                 :     221870 : parser::skip_pp ()
    1118                 :            : {
    1119                 :     221870 :   const token* t = 0;
    1120                 :     221870 :   unsigned nesting = 0;
    1121                 :    3905396 :   do
    1122                 :            :     {
    1123                 :            :       try
    1124                 :            :         {
    1125         [ +  - ]:    4127266 :           t = scan_pp1 ();
    1126                 :            :         }
    1127                 :            :       catch (const parse_error &e)
    1128                 :            :         {
    1129                 :            :           continue;
    1130                 :            :         }
    1131         [ -  + ]:    4127266 :       if (!t)
    1132                 :          0 :         break;
    1133 [ +  + ][ +  + ]:    4127266 :       if (t->type == tok_operator && t->content == "%(")
                 [ +  + ]
    1134                 :       4523 :         ++nesting;
    1135 [ +  + ][ +  + ]:    4122743 :       else if (nesting && t->type == tok_operator && t->content == "%)")
         [ +  + ][ +  + ]
    1136                 :       4523 :         --nesting;
    1137 [ +  + ][ +  +  :   10548888 :       else if (!nesting && t->type == tok_operator &&
          +  +  +  +  +  
              + ][ +  + ]
    1138                 :    6430668 :                (t->content == "%:" || t->content == "%?" || t->content == "%)"))
    1139                 :     221870 :         break;
    1140         [ +  - ]:    3905396 :       delete t;
    1141                 :            :     }
    1142                 :            :   while (true);
    1143         [ #  # ]:     221870 :   return t;
    1144                 :            : }
    1145                 :            : 
    1146                 :            : 
    1147                 :            : const token*
    1148                 :  190421513 : parser::next ()
    1149                 :            : {
    1150         [ +  + ]:  190421513 :   if (! next_t)
    1151                 :   61024859 :     next_t = scan_pp ();
    1152         [ -  + ]:  190421511 :   if (! next_t)
    1153 [ #  # ][ #  # ]:          0 :     throw parse_error (_("unexpected end-of-file"));
    1154                 :            : 
    1155                 :  190421511 :   last_t = next_t;
    1156                 :            :   // advance by zeroing next_t
    1157                 :  190421511 :   next_t = 0;
    1158                 :  190421511 :   return last_t;
    1159                 :            : }
    1160                 :            : 
    1161                 :            : 
    1162                 :            : const token*
    1163                 : 1521915152 : parser::peek ()
    1164                 :            : {
    1165         [ +  + ]: 1521915152 :   if (! next_t)
    1166                 :  199162222 :     next_t = scan_pp ();
    1167                 :            : 
    1168                 :            :   // don't advance by zeroing next_t
    1169                 : 1521915112 :   last_t = next_t;
    1170                 : 1521915112 :   return next_t;
    1171                 :            : }
    1172                 :            : 
    1173                 :            : 
    1174                 :            : void
    1175                 :  112553105 : parser::swallow ()
    1176                 :            : {
    1177                 :            :   // can only swallow something last peeked or nexted token.
    1178         [ -  + ]:  112553105 :   assert (last_t != 0);
    1179         [ +  - ]:  112553105 :   delete last_t;
    1180                 :            :   // advance by zeroing next_t
    1181                 :  112553105 :   last_t = next_t = 0;
    1182                 :  112553105 : }
    1183                 :            : 
    1184                 :            : 
    1185                 :            : static inline bool
    1186                 :  123380100 : tok_is(token const * t, token_type tt, string const & expected)
    1187                 :            : {
    1188 [ +  - ][ +  + ]:  123380100 :   return t && t->type == tt && t->content == expected;
                 [ +  + ]
    1189                 :            : }
    1190                 :            : 
    1191                 :            : 
    1192                 :            : void
    1193                 :   13934579 : parser::expect_known (token_type tt, string const & expected)
    1194                 :            : {
    1195                 :   13934579 :   const token *t = next();
    1196 [ +  - ][ +  + ]:   13934579 :   if (! (t && t->type == tt && t->content == expected))
         [ +  + ][ +  + ]
    1197 [ +  - ][ +  - ]:          3 :     throw parse_error (_F("expected '%s'", expected.c_str()));
                 [ +  - ]
    1198                 :   13934576 :   swallow (); // We are done with it, content was copied.
    1199                 :   13934576 : }
    1200                 :            : 
    1201                 :            : 
    1202                 :            : void
    1203                 :    3495070 : parser::expect_unknown (token_type tt, string & target)
    1204                 :            : {
    1205                 :    3495070 :   const token *t = next();
    1206 [ +  - ][ +  + ]:    3495070 :   if (!(t && t->type == tt))
    1207 [ +  - ][ +  - ]:          2 :     throw parse_error (_("expected ") + tt2str(tt));
                 [ +  - ]
    1208                 :    3495068 :   target = t->content;
    1209                 :    3495068 :   swallow (); // We are done with it, content was copied.
    1210                 :    3495068 : }
    1211                 :            : 
    1212                 :            : 
    1213                 :            : void
    1214                 :    3701179 : parser::expect_unknown2 (token_type tt1, token_type tt2, string & target)
    1215                 :            : {
    1216                 :    3701179 :   const token *t = next();
    1217 [ +  - ][ +  + ]:    3701179 :   if (!(t && (t->type == tt1 || t->type == tt2)))
                 [ -  + ]
    1218 [ #  # ][ #  # ]:          0 :     throw parse_error (_F("expected %s or %s", tt2str(tt1).c_str(), tt2str(tt2).c_str()));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1219                 :    3701179 :   target = t->content;
    1220                 :    3701179 :   swallow (); // We are done with it, content was copied.
    1221                 :    3701179 : }
    1222                 :            : 
    1223                 :            : 
    1224                 :            : void
    1225                 :   13895658 : parser::expect_op (std::string const & expected)
    1226                 :            : {
    1227                 :   13895658 :   expect_known (tok_operator, expected);
    1228                 :   13895655 : }
    1229                 :            : 
    1230                 :            : 
    1231                 :            : void
    1232                 :      15133 : parser::expect_kw (std::string const & expected)
    1233                 :            : {
    1234                 :      15133 :   expect_known (tok_keyword, expected);
    1235                 :      15133 : }
    1236                 :            : 
    1237                 :            : const token*
    1238                 :      15133 : parser::expect_kw_token (std::string const & expected)
    1239                 :            : {
    1240                 :      15133 :   const token *t = next();
    1241 [ +  - ][ +  - ]:      15133 :   if (! (t && t->type == tok_keyword && t->content == expected))
         [ -  + ][ -  + ]
    1242 [ #  # ][ #  # ]:          0 :     throw parse_error (_F("expected '%s'", expected.c_str()));
                 [ #  # ]
    1243                 :      15133 :   return t;
    1244                 :            : }
    1245                 :            : 
    1246                 :            : void
    1247                 :      23958 : parser::expect_number (int64_t & value)
    1248                 :            : {
    1249                 :      23958 :   bool neg = false;
    1250         [ +  - ]:      23958 :   const token *t = next();
    1251 [ +  + ][ +  - ]:      23958 :   if (t->type == tok_operator && t->content == "-")
         [ +  - ][ +  + ]
    1252                 :            :     {
    1253                 :         12 :       neg = true;
    1254         [ +  - ]:         12 :       swallow ();
    1255         [ +  - ]:         12 :       t = next ();
    1256                 :            :     }
    1257 [ +  - ][ -  + ]:      23958 :   if (!(t && t->type == tok_number))
    1258 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected number"));
    1259                 :            : 
    1260         [ +  - ]:      23958 :   const char* startp = t->content.c_str ();
    1261                 :      23958 :   char* endp = (char*) startp;
    1262                 :            : 
    1263                 :            :   // NB: we allow controlled overflow from LLONG_MIN .. ULLONG_MAX
    1264                 :            :   // Actually, this allows all the way from -ULLONG_MAX to ULLONG_MAX,
    1265                 :            :   // since the lexer only gives us positive digit strings, but we'll
    1266                 :            :   // limit it to LLONG_MIN when a '-' operator is fed into the literal.
    1267                 :      23958 :   errno = 0;
    1268                 :      23958 :   value = (int64_t) strtoull (startp, & endp, 0);
    1269 [ +  - ][ +  - ]:      23958 :   if (errno == ERANGE || errno == EINVAL || *endp != '\0'
         [ +  - ][ +  + ]
                 [ -  + ]
    1270                 :            :       || (neg && (unsigned long long) value > 9223372036854775808ULL)
    1271                 :            :       || (unsigned long long) value > 18446744073709551615ULL
    1272                 :            :       || value < -9223372036854775807LL-1)
    1273 [ #  # ][ #  # ]:          0 :     throw parse_error (_("number invalid or out of range"));
    1274                 :            : 
    1275         [ +  + ]:      23958 :   if (neg)
    1276                 :         12 :     value = -value;
    1277                 :            : 
    1278         [ +  - ]:      23958 :   swallow (); // We are done with it, content was parsed and copied into value.
    1279                 :      23958 : }
    1280                 :            : 
    1281                 :            : 
    1282                 :            : const token*
    1283                 :   50626767 : parser::expect_ident_or_atword (std::string & target)
    1284                 :            : {
    1285                 :   50626767 :   const token *t = next();
    1286                 :            : 
    1287                 :            :   // accept identifiers and operators beginning in '@':
    1288 [ +  - ][ +  + ]:   52066761 :   if (!t || (t->type != tok_identifier
           [ +  -  +  + ]
                 [ +  + ]
    1289                 :    1439994 :              && (t->type != tok_operator || t->content[0] != '@')))
    1290                 :            :     // XXX currently this is only called from parse_hist_op_or_bare_name(),
    1291                 :            :     // so the message is accurate, but keep an eye out in the future:
    1292 [ +  - ][ +  - ]:          1 :     throw parse_error (_F("expected %s or statistical operation", tt2str(tok_identifier).c_str()));
         [ +  - ][ +  - ]
    1293                 :            : 
    1294                 :   50626766 :   target = t->content;
    1295                 :   50626766 :   return t;
    1296                 :            : }
    1297                 :            : 
    1298                 :            : 
    1299                 :            : void
    1300                 :    3701179 : parser::expect_ident_or_keyword (std::string & target)
    1301                 :            : {
    1302                 :    3701179 :   expect_unknown2 (tok_identifier, tok_keyword, target);
    1303                 :    3701179 : }
    1304                 :            : 
    1305                 :            : 
    1306                 :            : bool
    1307                 :  123362535 : parser::peek_op (std::string const & op)
    1308                 :            : {
    1309                 :  123362535 :   return tok_is (peek(), tok_operator, op);
    1310                 :            : }
    1311                 :            : 
    1312                 :            : 
    1313                 :            : bool
    1314                 :          0 : parser::peek_kw (std::string const & kw)
    1315                 :            : {
    1316                 :          0 :   return tok_is (peek(), tok_identifier, kw);
    1317                 :            : }
    1318                 :            : 
    1319                 :            : 
    1320                 :            : 
    1321                 :     191819 : lexer::lexer (istream& input, const string& in, systemtap_session& s):
    1322                 :            :   ate_comment(false), ate_whitespace(false), saw_tokens(false),
    1323                 :            :   input_name (in), input_pointer (0), input_end (0), cursor_suspend_count(0),
    1324                 :            :   cursor_suspend_line (1), cursor_suspend_column (1), cursor_line (1),
    1325         [ +  - ]:     191819 :   cursor_column (1), session(s), current_file (0)
    1326                 :            : {
    1327         [ +  - ]:     191819 :   getline(input, input_contents, '\0');
    1328                 :            : 
    1329         [ +  - ]:     191819 :   input_pointer = input_contents.data();
    1330 [ +  - ][ +  - ]:     191819 :   input_end = input_contents.data() + input_contents.size();
    1331                 :            : 
    1332 [ +  - ][ +  + ]:     191819 :   if (keywords.empty())
    1333                 :            :     {
    1334                 :            :       // NB: adding new keywords is highly disruptive to the language,
    1335                 :            :       // in particular to existing scripts that could be suddenly
    1336                 :            :       // broken.  If done at all, it has to be s.compatible-sensitive,
    1337                 :            :       // and broadly advertised.
    1338 [ +  - ][ +  - ]:       2154 :       keywords.insert("probe");
                 [ +  - ]
    1339 [ +  - ][ +  - ]:       2154 :       keywords.insert("global");
                 [ +  - ]
    1340 [ +  - ][ +  - ]:       2154 :       keywords.insert("function");
                 [ +  - ]
    1341 [ +  - ][ +  - ]:       2154 :       keywords.insert("if");
                 [ +  - ]
    1342 [ +  - ][ +  - ]:       2154 :       keywords.insert("else");
                 [ +  - ]
    1343 [ +  - ][ +  - ]:       2154 :       keywords.insert("for");
                 [ +  - ]
    1344 [ +  - ][ +  - ]:       2154 :       keywords.insert("foreach");
                 [ +  - ]
    1345 [ +  - ][ +  - ]:       2154 :       keywords.insert("in");
                 [ +  - ]
    1346 [ +  - ][ +  - ]:       2154 :       keywords.insert("limit");
                 [ +  - ]
    1347 [ +  - ][ +  - ]:       2154 :       keywords.insert("return");
                 [ +  - ]
    1348 [ +  - ][ +  - ]:       2154 :       keywords.insert("delete");
                 [ +  - ]
    1349 [ +  - ][ +  - ]:       2154 :       keywords.insert("while");
                 [ +  - ]
    1350 [ +  - ][ +  - ]:       2154 :       keywords.insert("break");
                 [ +  - ]
    1351 [ +  - ][ +  - ]:       2154 :       keywords.insert("continue");
                 [ +  - ]
    1352 [ +  - ][ +  - ]:       2154 :       keywords.insert("next");
                 [ +  - ]
    1353 [ +  - ][ +  - ]:       2154 :       keywords.insert("string");
                 [ +  - ]
    1354 [ +  - ][ +  - ]:       2154 :       keywords.insert("long");
                 [ +  - ]
    1355 [ +  - ][ +  - ]:       2154 :       keywords.insert("try");
                 [ +  - ]
    1356 [ +  - ][ +  - ]:       2154 :       keywords.insert("catch");
                 [ +  - ]
    1357                 :            :     }
    1358                 :            : 
    1359 [ +  - ][ +  + ]:     191819 :   if (atwords.empty())
    1360                 :            :     {
    1361                 :            :       // NB: adding new @words is mildly disruptive to existing
    1362                 :            :       // scripts that define macros with the same name, but not
    1363                 :            :       // really. The user will merely receive a warning that they are
    1364                 :            :       // redefining an existing operator.
    1365 [ +  - ][ +  - ]:       2154 :       atwords.insert("@cast");
                 [ +  - ]
    1366 [ +  - ][ +  - ]:       2154 :       atwords.insert("@defined");
                 [ +  - ]
    1367 [ +  - ][ +  - ]:       2154 :       atwords.insert("@entry");
                 [ +  - ]
    1368 [ +  - ][ +  - ]:       2154 :       atwords.insert("@var");
                 [ +  - ]
    1369 [ +  - ][ +  - ]:       2154 :       atwords.insert("@avg");
                 [ +  - ]
    1370 [ +  - ][ +  - ]:       2154 :       atwords.insert("@count");
                 [ +  - ]
    1371 [ +  - ][ +  - ]:       2154 :       atwords.insert("@sum");
                 [ +  - ]
    1372 [ +  - ][ +  - ]:       2154 :       atwords.insert("@min");
                 [ +  - ]
    1373 [ +  - ][ +  - ]:       2154 :       atwords.insert("@max");
                 [ +  - ]
    1374 [ +  - ][ +  - ]:       2154 :       atwords.insert("@hist_linear");
                 [ +  - ]
    1375 [ +  - ][ +  - ]:       2154 :       atwords.insert("@hist_log");
                 [ +  - ]
    1376                 :            :     }
    1377                 :     191819 : }
    1378                 :            : 
    1379                 :       2414 : set<string> lexer::keywords;
    1380                 :       2414 : set<string> lexer::atwords;
    1381                 :            : 
    1382                 :            : void
    1383                 :     379330 : lexer::set_current_file (stapfile* f)
    1384                 :            : {
    1385                 :     379330 :   current_file = f;
    1386         [ +  + ]:     379330 :   if (f)
    1387                 :            :     {
    1388                 :     191819 :       f->file_contents = input_contents;
    1389                 :     191819 :       f->name = input_name;
    1390                 :            :     }
    1391                 :     379330 : }
    1392                 :            : 
    1393                 :            : int
    1394                 : 3485294005 : lexer::input_peek (unsigned n)
    1395                 :            : {
    1396         [ +  + ]: 3485294005 :   if (input_pointer + n >= input_end)
    1397                 :     308101 :     return -1; // EOF
    1398                 : 3485294005 :   return (unsigned char)*(input_pointer + n);
    1399                 :            : }
    1400                 :            : 
    1401                 :            : 
    1402                 :            : int
    1403                 : 2504841823 : lexer::input_get ()
    1404                 :            : {
    1405                 : 2504841823 :   int c = input_peek();
    1406         [ +  + ]: 2504841823 :   if (c < 0) return c; // EOF
    1407                 :            : 
    1408                 : 2504645552 :   ++input_pointer;
    1409                 :            : 
    1410         [ +  + ]: 2504645552 :   if (cursor_suspend_count)
    1411                 :            :     {
    1412                 :            :       // Track effect of input_put: preserve previous cursor/line_column
    1413                 :            :       // until all of its characters are consumed.
    1414         [ +  + ]:      89972 :       if (--cursor_suspend_count == 0)
    1415                 :            :         {
    1416                 :      80830 :           cursor_line = cursor_suspend_line;
    1417                 :      80830 :           cursor_column = cursor_suspend_column;
    1418                 :            :         }
    1419                 :            :     }
    1420                 :            :   else
    1421                 :            :     {
    1422                 :            :       // update source cursor
    1423         [ +  + ]: 2504555580 :       if (c == '\n')
    1424                 :            :         {
    1425                 :   84036061 :           cursor_line ++;
    1426                 :   84036061 :           cursor_column = 1;
    1427                 :            :         }
    1428                 :            :       else
    1429                 : 2420519519 :         cursor_column ++;
    1430                 :            :     }
    1431                 :            : 
    1432                 :            :   // clog << "[" << (char)c << "]";
    1433                 : 2504841823 :   return c;
    1434                 :            : }
    1435                 :            : 
    1436                 :            : 
    1437                 :            : void
    1438                 :      80830 : lexer::input_put (const string& chars, const token* t)
    1439                 :            : {
    1440                 :      80830 :   size_t pos = input_pointer - input_contents.data();
    1441                 :            :   // clog << "[put:" << chars << " @" << pos << "]";
    1442                 :      80830 :   input_contents.insert (pos, chars);
    1443                 :      80830 :   cursor_suspend_count += chars.size();
    1444                 :      80830 :   cursor_suspend_line = cursor_line;
    1445                 :      80830 :   cursor_suspend_column = cursor_column;
    1446                 :      80830 :   cursor_line = t->location.line;
    1447                 :      80830 :   cursor_column = t->location.column;
    1448                 :      80830 :   input_pointer = input_contents.data() + pos;
    1449                 :      80830 :   input_end = input_contents.data() + input_contents.size();
    1450                 :      80830 : }
    1451                 :            : 
    1452                 :            : 
    1453                 :            : token*
    1454                 :  254464165 : lexer::scan ()
    1455                 :            : {
    1456                 :  254464165 :   ate_comment = false; // reset for each new token
    1457                 :  254464165 :   ate_whitespace = false; // reset for each new token
    1458                 :            : 
    1459                 :            :   // XXX be very sure to restore old_saw_tokens if we return without a token:
    1460                 :  254464165 :   bool old_saw_tokens = saw_tokens;
    1461                 :  254464165 :   saw_tokens = true;
    1462                 :            : 
    1463         [ +  - ]:  254464165 :   token* n = new token;
    1464                 :  254464165 :   n->location.file = current_file;
    1465                 :  254464165 :   n->chain = NULL; // important safety dance
    1466                 :            : 
    1467                 :            : skip:
    1468                 :  503504655 :   bool suspended = (cursor_suspend_count > 0);
    1469                 :  503504655 :   n->location.line = cursor_line;
    1470                 :  503504655 :   n->location.column = cursor_column;
    1471                 :            : 
    1472                 :  503504655 :   int c = input_get();
    1473                 :            :   // clog << "{" << (char)c << (char)c2 << "}";
    1474         [ +  + ]:  503504655 :   if (c < 0)
    1475                 :            :     {
    1476         [ +  - ]:     196268 :       delete n;
    1477                 :     196268 :       saw_tokens = old_saw_tokens;
    1478                 :     196268 :       return 0;
    1479                 :            :     }
    1480                 :            : 
    1481         [ +  + ]:  503308387 :   if (isspace (c))
    1482                 :            :     {
    1483                 :  235328902 :       ate_whitespace = true;
    1484                 :  235328902 :       goto skip;
    1485                 :            :     }
    1486                 :            : 
    1487                 :  267979485 :   int c2 = input_peek ();
    1488                 :            : 
    1489                 :            :   // Paste command line arguments as character streams into
    1490                 :            :   // the beginning of a token.  $1..$999 go through as raw
    1491                 :            :   // characters; @1..@999 are quoted/escaped as strings.
    1492                 :            :   // $# and @# expand to the number of arguments, similarly
    1493                 :            :   // raw or quoted.
    1494 [ +  + ][ +  + ]:  267979485 :   if ((c == '$' || c == '@') && (c2 == '#'))
                 [ +  + ]
    1495                 :            :     {
    1496         [ +  - ]:      79821 :       n->content.push_back (c);
    1497         [ +  - ]:      79821 :       n->content.push_back (c2);
    1498                 :      79821 :       input_get(); // swallow '#'
    1499         [ -  + ]:      79821 :       if (suspended)
    1500                 :            :         {
    1501 [ #  # ][ #  # ]:          0 :           n->make_junk(_("invalid nested substitution of command line arguments"));
                 [ #  # ]
    1502                 :          0 :           return n;
    1503                 :            :         }
    1504                 :      79821 :       size_t num_args = session.args.size ();
    1505 [ +  + ][ +  - ]:      79821 :       input_put ((c == '$') ? lex_cast (num_args) : lex_cast_qstring (num_args), n);
         [ +  - ][ +  - ]
                 [ +  - ]
    1506         [ +  - ]:      79821 :       n->content.clear();
    1507                 :            :       goto skip;
    1508                 :            :     }
    1509 [ +  + ][ +  + ]:  267899664 :   else if ((c == '$' || c == '@') && (isdigit (c2)))
                 [ +  + ]
    1510                 :            :     {
    1511                 :      69824 :       n->content.push_back (c);
    1512                 :      69824 :       unsigned idx = 0;
    1513         [ +  + ]:     121403 :       do
           [ +  +  +  + ]
                 [ +  + ]
    1514                 :            :         {
    1515                 :      71814 :           input_get ();
    1516                 :      71814 :           idx = (idx * 10) + (c2 - '0');
    1517                 :      71814 :           n->content.push_back (c2);
    1518                 :      71814 :           c2 = input_peek ();
    1519                 :            :         } while (c2 > 0 &&
    1520                 :      71811 :                  isdigit (c2) &&
    1521                 :      49589 :                  idx <= session.args.size()); // prevent overflow
    1522         [ +  + ]:      69824 :       if (suspended) 
    1523                 :            :         {
    1524 [ +  - ][ +  - ]:          2 :           n->make_junk(_("invalid nested substitution of command line arguments"));
                 [ +  - ]
    1525                 :          2 :           return n;
    1526                 :            :         }
    1527   [ +  +  +  + ]:     139643 :       if (idx == 0 ||
                 [ +  + ]
    1528                 :      69821 :           idx-1 >= session.args.size())
    1529                 :            :         {
    1530                 :      68813 :           n->make_junk(_F("command line argument index %lu out of range [1-%lu]",
    1531         [ +  - ]:      68813 :                           (unsigned long) idx, (unsigned long) session.args.size()));
    1532                 :      68813 :           return n;
    1533                 :            :         }
    1534                 :       1009 :       const string& arg = session.args[idx-1];
    1535 [ +  + ][ +  - ]:       1009 :       input_put ((c == '$') ? arg : lex_cast_qstring (arg), n);
    1536                 :       1009 :       n->content.clear();
    1537                 :       1009 :       goto skip;
    1538                 :            :     }
    1539                 :            : 
    1540 [ +  + ][ +  + ]:  267829840 :   else if (isalpha (c) || c == '$' || c == '@' || c == '_')
         [ +  + ][ +  + ]
    1541                 :            :     {
    1542                 :   98065200 :       n->type = tok_identifier;
    1543                 :   98065200 :       n->content = (char) c;
    1544 [ +  + ][ +  + ]:  661469831 :       while (isalnum (c2) || c2 == '_' || c2 == '$')
         [ +  + ][ +  + ]
    1545                 :            :         {
    1546                 :  563404631 :           input_get ();
    1547                 :  563404631 :           n->content.push_back (c2);
    1548                 :  563404631 :           c2 = input_peek ();
    1549                 :            :         }
    1550                 :            : 
    1551         [ +  + ]:   98065200 :       if (keywords.count(n->content))
    1552                 :   23140781 :         n->type = tok_keyword;
    1553         [ +  + ]:   74924419 :       else if (n->content[0] == '@')
    1554                 :            :         // makes it easier to detect illegal use of @words:
    1555                 :    1487635 :         n->type = tok_operator;
    1556                 :            : 
    1557                 :   98065200 :       return n;
    1558                 :            :     }
    1559                 :            : 
    1560         [ +  + ]:  169764640 :   else if (isdigit (c)) // positive literal
    1561                 :            :     {
    1562                 :    8394350 :       n->type = tok_number;
    1563                 :    8394350 :       n->content = (char) c;
    1564                 :            : 
    1565         [ +  + ]:   12347428 :       while (isalnum (c2))
    1566                 :            :         {
    1567                 :            :           // NB: isalnum is very permissive.  We rely on strtol, called in
    1568                 :            :           // parser::parse_literal below, to confirm that the number string
    1569                 :            :           // is correctly formatted and in range.
    1570                 :            : 
    1571                 :    3953078 :           input_get ();
    1572                 :    3953078 :           n->content.push_back (c2);
    1573                 :    3953078 :           c2 = input_peek ();
    1574                 :            :         }
    1575                 :    8394350 :       return n;
    1576                 :            :     }
    1577                 :            : 
    1578         [ +  + ]:  161370290 :   else if (c == '\"')
    1579                 :            :     {
    1580                 :   16327116 :       n->type = tok_string;
    1581                 :  180372462 :       while (1)
    1582                 :            :         {
    1583                 :  196699578 :           c = input_get ();
    1584                 :            : 
    1585 [ +  - ][ -  + ]:  196699578 :           if (c < 0 || c == '\n')
    1586                 :            :             {
    1587 [ #  # ][ #  # ]:          0 :               n->make_junk(_("Could not find matching closing quote"));
                 [ #  # ]
    1588                 :          0 :               return n;
    1589                 :            :             }
    1590         [ +  + ]:  196699578 :           if (c == '\"') // closing double-quotes
    1591                 :   16327116 :             break;
    1592         [ +  + ]:  180372462 :           else if (c == '\\') // see also input_put
    1593                 :            :             {
    1594                 :      48859 :               c = input_get ();
    1595         [ +  + ]:      48859 :               switch (c)
    1596                 :            :                 {
    1597                 :            :                 case 'a':
    1598                 :            :                 case 'b':
    1599                 :            :                 case 't':
    1600                 :            :                 case 'n':
    1601                 :            :                 case 'v':
    1602                 :            :                 case 'f':
    1603                 :            :                 case 'r':
    1604                 :            :                 case '0' ... '7': // NB: need only match the first digit
    1605                 :            :                 case '\\':
    1606                 :            :                   // Pass these escapes through to the string value
    1607                 :            :                   // being parsed; it will be emitted into a C literal.
    1608                 :            : 
    1609                 :      44386 :                   n->content.push_back('\\');
    1610                 :            : 
    1611                 :            :                   // fall through
    1612                 :            :                 default:
    1613                 :      48859 :                   n->content.push_back(c);
    1614                 :      48859 :                   break;
    1615                 :            :                 }
    1616                 :            :             }
    1617                 :            :           else
    1618                 :  180323603 :             n->content.push_back(c);
    1619                 :            :         }
    1620                 :   16327116 :       return n;
    1621                 :            :     }
    1622                 :            : 
    1623         [ +  - ]:  145043174 :   else if (ispunct (c))
    1624                 :            :     {
    1625                 :  145043174 :       int c3 = input_peek (1);
    1626                 :            : 
    1627                 :            :       // NB: if we were to recognize negative numeric literals here,
    1628                 :            :       // we'd introduce another grammar ambiguity:
    1629                 :            :       // 1-1 would be parsed as tok_number(1) and tok_number(-1)
    1630                 :            :       // instead of tok_number(1) tok_operator('-') tok_number(1)
    1631                 :            : 
    1632         [ +  + ]:  145043174 :       if (c == '#') // shell comment
    1633                 :            :         {
    1634                 :    7240245 :           unsigned this_line = cursor_line;
    1635 [ +  + ][ +  + ]:  263168478 :           do { c = input_get (); }
                 [ +  + ]
    1636                 :            :           while (c >= 0 && cursor_line == this_line);
    1637                 :    7240245 :           ate_comment = true;
    1638                 :    7240245 :           ate_whitespace = true;
    1639                 :    7240245 :           goto skip;
    1640                 :            :         }
    1641 [ +  + ][ +  + ]:  137802929 :       else if ((c == '/' && c2 == '/')) // C++ comment
    1642                 :            :         {
    1643                 :    4627867 :           unsigned this_line = cursor_line;
    1644 [ +  - ][ +  + ]:  164867590 :           do { c = input_get (); }
                 [ +  + ]
    1645                 :            :           while (c >= 0 && cursor_line == this_line);
    1646                 :    4627867 :           ate_comment = true;
    1647                 :    4627867 :           ate_whitespace = true;
    1648                 :    4627867 :           goto skip;
    1649                 :            :         }
    1650 [ +  + ][ +  + ]:  133175062 :       else if (c == '/' && c2 == '*') // C comment
    1651                 :            :         {
    1652                 :    1762646 :           (void) input_get (); // swallow '*' already in c2
    1653                 :    1762646 :           c = input_get ();
    1654                 :    1762646 :           c2 = input_get ();
    1655         [ +  + ]:  521626561 :           while (c2 >= 0)
    1656                 :            :             {
    1657 [ +  + ][ +  + ]:  521626560 :               if (c == '*' && c2 == '/')
    1658                 :    1762645 :                 break;
    1659                 :  519863915 :               c = c2;
    1660                 :  519863915 :               c2 = input_get ();
    1661                 :            :             }
    1662                 :    1762646 :           ate_comment = true;
    1663                 :    1762646 :           ate_whitespace = true;
    1664                 :    1762646 :           goto skip;
    1665                 :            :         }
    1666 [ +  + ][ +  + ]:  131412416 :       else if (c == '%' && c2 == '{') // embedded code
    1667                 :            :         {
    1668                 :    1195845 :           n->type = tok_embedded;
    1669                 :    1195845 :           (void) input_get (); // swallow '{' already in c2
    1670                 :    1195845 :           c = input_get ();
    1671                 :    1195845 :           c2 = input_get ();
    1672         [ +  + ]:  275189825 :           while (c2 >= 0)
    1673                 :            :             {
    1674 [ +  + ][ +  + ]:  275189824 :               if (c == '%' && c2 == '}')
    1675                 :    1195844 :                 return n;
    1676                 :  273993980 :               n->content += c;
    1677                 :  273993980 :               c = c2;
    1678                 :  273993980 :               c2 = input_get ();
    1679                 :            :             }
    1680                 :            : 
    1681 [ +  - ][ +  - ]:          1 :           n->make_junk(_("Could not find matching '%}' to close embedded function block"));
                 [ +  - ]
    1682                 :          1 :           return n;
    1683                 :            :         }
    1684                 :            : 
    1685                 :            :       // We're committed to recognizing at least the first character
    1686                 :            :       // as an operator.
    1687                 :  130216571 :       n->type = tok_operator;
    1688                 :  130216571 :       n->content = c;
    1689                 :            : 
    1690                 :            :       // match all valid operators, in decreasing size order
    1691 [ +  + ][ +  + ]:  130216571 :       if ((c == '<' && c2 == '<' && c3 == '<') ||
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
    1692                 :            :           (c == '<' && c2 == '<' && c3 == '=') ||
    1693                 :            :           (c == '>' && c2 == '>' && c3 == '='))
    1694                 :            :         {
    1695                 :       6733 :           n->content += c2;
    1696                 :       6733 :           n->content += c3;
    1697                 :       6733 :           input_get (); input_get (); // swallow other two characters
    1698                 :            :         }
    1699 [ +  + ][ +  + ]:  130209838 :       else if ((c == '=' && c2 == '=') ||
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    1700                 :            :                (c == '!' && c2 == '=') ||
    1701                 :            :                (c == '<' && c2 == '=') ||
    1702                 :            :                (c == '>' && c2 == '=') ||
    1703                 :            :                (c == '=' && c2 == '~') ||
    1704                 :            :                (c == '!' && c2 == '~') ||
    1705                 :            :                (c == '+' && c2 == '=') ||
    1706                 :            :                (c == '-' && c2 == '=') ||
    1707                 :            :                (c == '*' && c2 == '=') ||
    1708                 :            :                (c == '/' && c2 == '=') ||
    1709                 :            :                (c == '%' && c2 == '=') ||
    1710                 :            :                (c == '&' && c2 == '=') ||
    1711                 :            :                (c == '^' && c2 == '=') ||
    1712                 :            :                (c == '|' && c2 == '=') ||
    1713                 :            :                (c == '.' && c2 == '=') ||
    1714                 :            :                (c == '&' && c2 == '&') ||
    1715                 :            :                (c == '|' && c2 == '|') ||
    1716                 :            :                (c == '+' && c2 == '+') ||
    1717                 :            :                (c == '-' && c2 == '-') ||
    1718                 :            :                (c == '-' && c2 == '>') ||
    1719                 :            :                (c == '<' && c2 == '<') ||
    1720                 :            :                (c == '>' && c2 == '>') ||
    1721                 :            :                // preprocessor tokens
    1722                 :            :                (c == '%' && c2 == '(') ||
    1723                 :            :                (c == '%' && c2 == '?') ||
    1724                 :            :                (c == '%' && c2 == ':') ||
    1725                 :            :                (c == '%' && c2 == ')'))
    1726                 :            :         {
    1727                 :    6296485 :           n->content += c2;
    1728                 :    6296485 :           input_get (); // swallow other character
    1729                 :            :         }
    1730                 :            : 
    1731                 :  130216571 :       return n;
    1732                 :            :     }
    1733                 :            : 
    1734                 :            :   else
    1735                 :            :     {
    1736                 :          0 :       n->type = tok_junk;
    1737         [ #  # ]:          0 :       ostringstream s;
    1738 [ #  # ][ #  # ]:          0 :       s << "\\x" << hex << setw(2) << setfill('0') << c;
         [ #  # ][ #  # ]
                 [ #  # ]
    1739 [ #  # ][ #  # ]:          0 :       n->content = s.str();
                 [ #  # ]
    1740         [ #  # ]:          0 :       n->msg = ""; // signal parser to emit "expected X, found junk" type error
    1741         [ #  # ]:  254464165 :       return n;
    1742                 :            :     }
    1743                 :            : }
    1744                 :            : 
    1745                 :            : // ------------------------------------------------------------------------
    1746                 :            : 
    1747                 :            : void
    1748                 :      68816 : token::make_junk (const string new_msg)
    1749                 :            : {
    1750                 :      68816 :   type = tok_junk;
    1751                 :      68816 :   msg = new_msg;
    1752                 :      68816 : }
    1753                 :            : 
    1754                 :            : // ------------------------------------------------------------------------
    1755                 :            : 
    1756                 :            : stapfile*
    1757                 :     187511 : parser::parse ()
    1758                 :            : {
    1759         [ +  - ]:     187511 :   stapfile* f = new stapfile;
    1760                 :     187511 :   input.set_current_file (f);
    1761                 :            : 
    1762                 :     187511 :   bool empty = true;
    1763                 :            : 
    1764                 :    5859359 :   while (1)
    1765                 :            :     {
    1766                 :            :       try
    1767                 :            :         {
    1768                 :    6046870 :           systemtap_v_seen = 0;
    1769         [ +  + ]:    6046870 :           const token* t = peek ();
    1770         [ +  + ]:    6046842 :           if (! t) // nice clean EOF, modulo any preprocessing that occurred
    1771                 :     187511 :             break;
    1772                 :            : 
    1773                 :    5859331 :           empty = false;
    1774 [ +  + ][ +  - ]:    5859331 :           if (t->type == tok_keyword && t->content == "probe")
         [ +  + ][ +  + ]
    1775                 :            :             {
    1776                 :    4360206 :               context = con_probe;
    1777         [ +  + ]:    4360206 :               parse_probe (f->probes, f->aliases);
    1778                 :            :             }
    1779 [ +  + ][ +  - ]:    1499125 :           else if (t->type == tok_keyword && t->content == "global")
         [ +  + ][ +  + ]
    1780                 :            :             {
    1781                 :     115360 :               context = con_global;
    1782         [ +  + ]:     115360 :               parse_global (f->globals, f->probes);
    1783                 :            :             }
    1784 [ +  + ][ +  - ]:    1383765 :           else if (t->type == tok_keyword && t->content == "function")
         [ +  - ][ +  + ]
    1785                 :            :             {
    1786                 :    1273818 :               context = con_function;
    1787         [ +  + ]:    1273818 :               parse_functiondecl (f->functions);
    1788                 :            :             }
    1789         [ +  + ]:     109947 :           else if (t->type == tok_embedded)
    1790                 :            :             {
    1791                 :     109940 :               context = con_embedded;
    1792 [ +  + ][ +  - ]:     109940 :               f->embeds.push_back (parse_embeddedcode ());
    1793                 :            :             }
    1794                 :            :           else
    1795                 :            :             {
    1796                 :          7 :               context = con_unknown;
    1797 [ +  - ][ +  - ]:          7 :               throw parse_error (_("expected 'probe', 'global', 'function', or '%{'"));
    1798                 :            :             }
    1799                 :            :         }
    1800         [ -  + ]:        260 :       catch (parse_error& pe)
    1801                 :            :         {
    1802         [ -  + ]:        130 :           print_error (pe);
    1803                 :            : 
    1804                 :            :           // XXX: do we want tok_junk to be able to force skip_some behaviour?
    1805         [ +  + ]:        130 :           if (pe.skip_some) // for recovery
    1806                 :            :             // Quietly swallow all tokens until the next keyword we can start parsing from.
    1807                 :        670 :             while (1)
    1808                 :            :               try
    1809                 :            :                 {
    1810                 :            :                   {
    1811         [ +  + ]:        670 :                     const token* t = peek ();
    1812         [ +  + ]:        659 :                     if (! t)
    1813                 :        115 :                       break;
    1814 [ +  + ][ -  + ]:        544 :                     if (t->type == tok_keyword && t->content == "probe") break;
         [ +  + ][ +  + ]
    1815 [ +  + ][ -  + ]:        531 :                     else if (t->type == tok_keyword && t->content == "global") break;
         [ -  + ][ -  + ]
    1816 [ +  + ][ -  + ]:        531 :                     else if (t->type == tok_keyword && t->content == "function") break;
         [ -  + ][ -  + ]
    1817         [ -  + ]:        531 :                     else if (t->type == tok_embedded) break;
    1818         [ -  + ]:        531 :                     swallow (); // swallow it
    1819                 :            :                   }
    1820                 :            :                 }
    1821 [ -  + ][ -  + ]:         22 :               catch (parse_error& pe2)
    1822                 :            :                 {
    1823                 :            :                   // parse error during recovery ... ugh
    1824         [ -  + ]:         11 :                   print_error (pe2);
    1825                 :            :                 }
    1826                 :            :         }
    1827                 :            :     }
    1828                 :            : 
    1829         [ +  + ]:     187511 :   if (empty)
    1830                 :            :     {
    1831                 :            :       // vary message depending on whether file was *actually* empty:
    1832                 :            :       cerr << (input.saw_tokens
    1833                 :         14 :                ? _F("Input file '%s' is empty after preprocessing.", input_name.c_str())
    1834 [ +  + ][ +  - ]:         30 :                : _F("Input file '%s' is empty.", input_name.c_str()))
    1835         [ +  - ]:         15 :            << endl;
    1836         [ +  - ]:         15 :       delete f;
    1837                 :         15 :       f = 0;
    1838                 :            :     }
    1839         [ +  + ]:     187496 :   else if (num_errors > 0)
    1840                 :            :     {
    1841 [ +  - ][ +  - ]:        104 :       cerr << _F(ngettext("%d parse error.", "%d parse errors.", num_errors), num_errors) << endl;
    1842         [ +  - ]:        104 :       delete f;
    1843                 :        104 :       f = 0;
    1844                 :            :     }
    1845                 :            : 
    1846                 :     187511 :   input.set_current_file(0);
    1847                 :     187511 :   return f;
    1848                 :            : }
    1849                 :            : 
    1850                 :            : 
    1851                 :            : void
    1852                 :    4360206 : parser::parse_probe (std::vector<probe *> & probe_ret,
    1853                 :            :                      std::vector<probe_alias *> & alias_ret)
    1854                 :            : {
    1855         [ +  - ]:    4360206 :   const token* t0 = next ();
    1856 [ +  - ][ +  - ]:    4360206 :   if (! (t0->type == tok_keyword && t0->content == "probe"))
         [ -  + ][ -  + ]
    1857 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'probe'"));
    1858                 :            : 
    1859         [ +  - ]:    4360206 :   vector<probe_point *> aliases;
    1860         [ +  - ]:    4360206 :   vector<probe_point *> locations;
    1861                 :            : 
    1862                 :    4360206 :   bool equals_ok = true;
    1863                 :            : 
    1864                 :    4360206 :   int epilogue_alias = 0;
    1865                 :            : 
    1866                 :    6644967 :   while (1)
    1867                 :            :     {
    1868         [ +  + ]:   11005173 :       probe_point * pp = parse_probe_point ();
    1869                 :            : 
    1870         [ +  - ]:   11005141 :       const token* t = peek ();
    1871 [ +  + ][ +  - ]:   19704700 :       if (equals_ok && t
         [ +  - ][ +  + ]
                 [ +  + ]
    1872         [ +  - ]:    8699559 :           && t->type == tok_operator && t->content == "=")
    1873                 :            :         {
    1874 [ +  + ][ -  + ]:    4339380 :           if (pp->optional || pp->sufficient)
    1875 [ +  - ][ +  - ]:          1 :             throw parse_error (_("probe point alias name cannot be optional nor sufficient"), pp->components.front()->tok);
                 [ +  - ]
    1876         [ +  - ]:    4339379 :           aliases.push_back(pp);
    1877         [ +  - ]:    4339379 :           swallow ();
    1878                 :    4339379 :           continue;
    1879                 :            :         }
    1880 [ +  + ][ +  - ]:   11025940 :       else if (equals_ok && t
         [ +  - ][ +  + ]
                 [ +  + ]
    1881         [ +  - ]:    4360179 :           && t->type == tok_operator && t->content == "+=")
    1882                 :            :         {
    1883 [ +  - ][ -  + ]:          4 :           if (pp->optional || pp->sufficient)
    1884 [ #  # ][ #  # ]:          0 :             throw parse_error (_("probe point alias name cannot be optional nor sufficient"), pp->components.front()->tok);
                 [ #  # ]
    1885         [ +  - ]:          4 :           aliases.push_back(pp);
    1886                 :          4 :           epilogue_alias = 1;
    1887         [ +  - ]:          4 :           swallow ();
    1888                 :          4 :           continue;
    1889                 :            :         }
    1890 [ +  - ][ +  - ]:    6665757 :       else if (t && t->type == tok_operator && t->content == ",")
         [ +  - ][ +  + ]
                 [ +  + ]
    1891                 :            :         {
    1892         [ +  - ]:    2305584 :           locations.push_back(pp);
    1893                 :    2305584 :           equals_ok = false;
    1894         [ +  - ]:    2305584 :           swallow ();
    1895                 :    2305584 :           continue;
    1896                 :            :         }
    1897 [ +  - ][ +  - ]:    4360173 :       else if (t && t->type == tok_operator && t->content == "{")
         [ +  - ][ +  - ]
                 [ +  - ]
    1898                 :            :         {
    1899         [ +  - ]:    4360173 :           locations.push_back(pp);
    1900                 :            :           break;
    1901                 :            :         }
    1902                 :            :       else
    1903 [ #  # ][ #  # ]:         33 :         throw parse_error (_("expected probe point specifier"));
    1904                 :            :     }
    1905                 :            : 
    1906 [ +  - ][ +  + ]:    4360173 :   if (aliases.empty())
    1907                 :            :     {
    1908 [ +  - ][ +  - ]:      20817 :       probe* p = new probe;
    1909                 :      20792 :       p->tok = t0;
    1910         [ +  - ]:      20792 :       p->locations = locations;
    1911         [ +  + ]:      20792 :       p->body = parse_stmt_block ();
    1912                 :      20767 :       p->privileged = privileged;
    1913                 :      20767 :       p->systemtap_v_conditional = systemtap_v_seen;
    1914         [ +  - ]:      20767 :       probe_ret.push_back (p);
    1915                 :            :     }
    1916                 :            :   else
    1917                 :            :     {
    1918 [ +  - ][ +  - ]:    4339381 :       probe_alias* p = new probe_alias (aliases);
    1919         [ +  + ]:    4339381 :       if(epilogue_alias)
    1920                 :          4 :         p->epilogue_style = true;
    1921                 :            :       else
    1922                 :    4339377 :         p->epilogue_style = false;
    1923                 :    4339381 :       p->tok = t0;
    1924         [ +  - ]:    4339381 :       p->locations = locations;
    1925         [ +  - ]:    4339381 :       p->body = parse_stmt_block ();
    1926                 :    4339381 :       p->privileged = privileged;
    1927                 :    4339381 :       p->systemtap_v_conditional = systemtap_v_seen;
    1928         [ +  - ]:    4339381 :       alias_ret.push_back (p);
    1929 [ +  - ][ +  - ]:    4360206 :     }
    1930                 :    4360148 : }
    1931                 :            : 
    1932                 :            : 
    1933                 :            : embeddedcode*
    1934                 :     689615 : parser::parse_embeddedcode ()
    1935                 :            : {
    1936         [ +  - ]:     689615 :   embeddedcode* e = new embeddedcode;
    1937                 :     689615 :   const token* t = next ();
    1938         [ -  + ]:     689615 :   if (t->type != tok_embedded)
    1939 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected '%{'"));
    1940                 :            : 
    1941         [ +  + ]:     689615 :   if (! privileged)
    1942                 :          2 :     throw parse_error (_("embedded code in unprivileged script; need stap -g"),
    1943 [ +  - ][ +  - ]:          2 :                        false /* don't skip tokens for parse resumption */);
    1944                 :            : 
    1945                 :     689613 :   e->tok = t;
    1946                 :     689613 :   e->code = t->content;
    1947                 :     689613 :   return e;
    1948                 :            : }
    1949                 :            : 
    1950                 :            : 
    1951                 :            : block*
    1952                 :    5846599 : parser::parse_stmt_block ()
    1953                 :            : {
    1954         [ +  - ]:    5846599 :   block* pb = new block;
    1955                 :            : 
    1956                 :    5846599 :   const token* t = next ();
    1957 [ +  - ][ -  + ]:    5846599 :   if (! (t->type == tok_operator && t->content == "{"))
                 [ -  + ]
    1958 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected '{'"));
    1959                 :            : 
    1960                 :    5846599 :   pb->tok = t;
    1961                 :            : 
    1962                 :   22314068 :   while (1)
    1963                 :            :     {
    1964                 :   28160667 :       t = peek ();
    1965 [ +  + ][ +  + ]:   28160666 :       if (t && t->type == tok_operator && t->content == "}")
         [ +  + ][ +  + ]
    1966                 :            :         {
    1967                 :    5846555 :           swallow ();
    1968                 :    5846555 :           break;
    1969                 :            :         }
    1970         [ +  - ]:   22314111 :       pb->statements.push_back (parse_statement ());
    1971                 :            :     }
    1972                 :            : 
    1973                 :    5846555 :   return pb;
    1974                 :            : }
    1975                 :            : 
    1976                 :            : 
    1977                 :            : try_block*
    1978                 :      15133 : parser::parse_try_block ()
    1979                 :            : {
    1980         [ +  - ]:      15133 :   try_block* pb = new try_block;
    1981                 :            : 
    1982 [ +  - ][ +  - ]:      15133 :   pb->tok = expect_kw_token ("try");
                 [ +  - ]
    1983                 :      15133 :   pb->try_block = parse_stmt_block();
    1984 [ +  - ][ +  - ]:      15133 :   expect_kw ("catch");
                 [ +  - ]
    1985                 :            : 
    1986                 :      15133 :   const token* t = peek ();
    1987 [ +  - ][ +  + ]:      15133 :   if (t->type == tok_operator && t->content == "(")
                 [ +  + ]
    1988                 :            :     {
    1989                 :          7 :       swallow (); // swallow the '('
    1990                 :            : 
    1991                 :          7 :       t = next();
    1992         [ -  + ]:          7 :       if (! (t->type == tok_identifier))
    1993 [ #  # ][ #  # ]:          0 :         throw parse_error (_("expected identifier"));
    1994         [ +  - ]:          7 :       symbol* sym = new symbol;
    1995                 :          7 :       sym->tok = t;
    1996                 :          7 :       sym->name = t->content;
    1997                 :          7 :       pb->catch_error_var = sym;
    1998                 :            : 
    1999 [ +  - ][ +  - ]:          7 :       expect_op (")");
                 [ +  - ]
    2000                 :            :     }
    2001                 :            :   else
    2002                 :      15126 :     pb->catch_error_var = 0;
    2003                 :            : 
    2004                 :      15133 :   pb->catch_block = parse_stmt_block();
    2005                 :            : 
    2006                 :      15133 :   return pb;
    2007                 :            : }
    2008                 :            : 
    2009                 :            : 
    2010                 :            : 
    2011                 :            : statement*
    2012                 :   24835682 : parser::parse_statement ()
    2013                 :            : {
    2014                 :            :   statement *ret;
    2015                 :   24835682 :   const token* t = peek ();
    2016 [ +  + ][ +  + ]:   24835682 :   if (t && t->type == tok_operator && t->content == ";")
         [ +  + ][ +  + ]
    2017         [ +  - ]:        174 :     return new null_statement (next ());
    2018 [ +  + ][ +  + ]:   24835508 :   else if (t && t->type == tok_operator && t->content == "{")
         [ +  + ][ +  + ]
    2019                 :     762025 :     return parse_stmt_block (); // Don't squash semicolons.
    2020 [ +  + ][ +  + ]:   24073483 :   else if (t && t->type == tok_keyword && t->content == "try")
         [ +  + ][ +  + ]
    2021                 :      15133 :     return parse_try_block (); // Don't squash semicolons.
    2022 [ +  + ][ +  + ]:   24058350 :   else if (t && t->type == tok_keyword && t->content == "if")
         [ +  + ][ +  + ]
    2023                 :    2102453 :     return parse_if_statement (); // Don't squash semicolons.
    2024 [ +  + ][ +  + ]:   21955897 :   else if (t && t->type == tok_keyword && t->content == "for")
         [ +  + ][ +  + ]
    2025                 :       6823 :     return parse_for_loop (); // Don't squash semicolons.
    2026 [ +  + ][ +  + ]:   21949074 :   else if (t && t->type == tok_keyword && t->content == "foreach")
         [ +  + ][ +  + ]
    2027                 :      17574 :     return parse_foreach_loop (); // Don't squash semicolons.
    2028 [ +  + ][ +  + ]:   21931500 :   else if (t && t->type == tok_keyword && t->content == "while")
         [ +  + ][ +  + ]
    2029                 :      25920 :     return parse_while_loop (); // Don't squash semicolons.
    2030 [ +  + ][ +  + ]:   21905580 :   else if (t && t->type == tok_keyword && t->content == "return")
         [ +  + ][ +  + ]
    2031                 :    1753741 :     ret = parse_return_statement ();
    2032 [ +  + ][ +  + ]:   20151839 :   else if (t && t->type == tok_keyword && t->content == "delete")
         [ +  + ][ +  + ]
    2033                 :      28254 :     ret = parse_delete_statement ();
    2034 [ +  + ][ +  + ]:   20123585 :   else if (t && t->type == tok_keyword && t->content == "break")
         [ +  + ][ +  + ]
    2035                 :      19431 :     ret = parse_break_statement ();
    2036 [ +  + ][ +  + ]:   20104154 :   else if (t && t->type == tok_keyword && t->content == "continue")
         [ +  + ][ +  + ]
    2037                 :       2223 :     ret = parse_continue_statement ();
    2038 [ +  + ][ +  + ]:   20101931 :   else if (t && t->type == tok_keyword && t->content == "next")
         [ +  - ][ +  + ]
    2039                 :      62712 :     ret = parse_next_statement ();
    2040 [ +  + ][ +  + ]:   20039219 :   else if (t && (t->type == tok_operator || // expressions are flexible
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    2041                 :            :                  t->type == tok_identifier ||
    2042                 :            :                  t->type == tok_number ||
    2043                 :            :                  t->type == tok_string ||
    2044                 :            :                  t->type == tok_embedded ))
    2045                 :   20039217 :     ret = parse_expr_statement ();
    2046                 :            :   // XXX: consider generally accepting tok_embedded here too
    2047                 :            :   else
    2048 [ +  - ][ +  - ]:          2 :     throw parse_error (_("expected statement"));
    2049                 :            : 
    2050                 :            :   // Squash "empty" trailing colons after any "non-block-like" statement.
    2051                 :   21905558 :   t = peek ();
    2052 [ +  - ][ +  + ]:   21905558 :   if (t && t->type == tok_operator && t->content == ";")
         [ +  + ][ +  + ]
    2053                 :            :     {
    2054                 :     842063 :       swallow (); // Silently eat trailing ; after statement
    2055                 :            :     }
    2056                 :            : 
    2057                 :   24835639 :   return ret;
    2058                 :            : }
    2059                 :            : 
    2060                 :            : 
    2061                 :            : void
    2062                 :     115360 : parser::parse_global (vector <vardecl*>& globals, vector<probe*>&)
    2063                 :            : {
    2064                 :     115360 :   const token* t0 = next ();
    2065 [ +  - ][ -  + ]:     115360 :   if (! (t0->type == tok_keyword && t0->content == "global"))
                 [ -  + ]
    2066 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'global'"));
    2067                 :     115360 :   swallow ();
    2068                 :            : 
    2069                 :      48040 :   while (1)
    2070                 :            :     {
    2071         [ +  - ]:     163400 :       const token* t = next ();
    2072         [ +  + ]:     163400 :       if (! (t->type == tok_identifier))
    2073 [ +  - ][ +  - ]:          3 :         throw parse_error (_("expected identifier"));
    2074                 :            : 
    2075         [ +  + ]:     640866 :       for (unsigned i=0; i<globals.size(); i++)
    2076 [ +  - ][ +  + ]:     477470 :         if (globals[i]->name == t->content)
    2077 [ +  - ][ +  - ]:          1 :           throw parse_error (_("duplicate global name"));
    2078                 :            : 
    2079 [ +  - ][ +  - ]:     163396 :       vardecl* d = new vardecl;
    2080         [ +  - ]:     163396 :       d->name = t->content;
    2081                 :     163396 :       d->tok = t;
    2082                 :     163396 :       d->systemtap_v_conditional = systemtap_v_seen;
    2083         [ +  - ]:     163396 :       globals.push_back (d);
    2084                 :            : 
    2085         [ +  - ]:     163396 :       t = peek ();
    2086                 :            : 
    2087 [ +  + ][ +  + ]:     163396 :       if(t && t->type == tok_operator && t->content == "%") //wrapping
         [ +  - ][ +  + ]
                 [ +  + ]
    2088                 :            :         {
    2089                 :         18 :           d->wrap = true;
    2090         [ +  - ]:         18 :           swallow ();
    2091         [ +  - ]:         18 :           t = peek();
    2092                 :            :         }
    2093                 :            : 
    2094 [ +  + ][ +  + ]:     163396 :       if (t && t->type == tok_operator && t->content == "[") // array size
         [ +  - ][ +  + ]
                 [ +  + ]
    2095                 :            :         {
    2096                 :            :           int64_t size;
    2097         [ +  - ]:      23790 :           swallow ();
    2098         [ +  - ]:      23790 :           expect_number(size);
    2099 [ +  + ][ +  + ]:      23790 :           if (size <= 0 || size > 1000000) // arbitrary max
    2100 [ +  - ][ +  - ]:          2 :             throw parse_error(_("array size out of range"));
    2101                 :      23788 :           d->maxsize = (int)size;
    2102 [ +  - ][ +  - ]:      23790 :           expect_known(tok_operator, "]");
                 [ +  - ]
    2103         [ +  - ]:      23788 :           t = peek ();
    2104                 :            :         }
    2105                 :            : 
    2106 [ +  + ][ +  + ]:     163394 :       if (t && t->type == tok_operator && t->content == "=") // initialization
         [ +  - ][ +  + ]
                 [ +  + ]
    2107                 :            :         {
    2108 [ +  - ][ +  + ]:      28220 :           if (!d->compatible_arity(0))
    2109 [ +  - ][ +  - ]:          8 :             throw parse_error(_("only scalar globals can be initialized"));
    2110         [ +  - ]:      28218 :           d->set_arity(0, t);
    2111         [ +  - ]:      28218 :           next (); // Don't swallow, set_arity() used the peeked token.
    2112         [ +  - ]:      28218 :           d->init = parse_literal ();
    2113                 :      28218 :           d->type = d->init->type;
    2114         [ +  - ]:      28218 :           t = peek ();
    2115                 :            :         }
    2116                 :            : 
    2117 [ +  + ][ +  + ]:     163392 :       if (t && t->type == tok_operator && t->content == ";") // termination
         [ +  - ][ +  + ]
                 [ +  + ]
    2118                 :            :         {
    2119         [ +  - ]:        118 :           swallow ();
    2120                 :            :           break;
    2121                 :            :         }
    2122                 :            : 
    2123 [ +  + ][ +  + ]:     163274 :       if (t && t->type == tok_operator && t->content == ",") // next global
         [ +  - ][ +  - ]
                 [ +  + ]
    2124                 :            :         {
    2125         [ +  - ]:      48040 :           swallow ();
    2126                 :      48040 :           continue;
    2127                 :            :         }
    2128                 :            :       else
    2129                 :            :         break;
    2130                 :            :     }
    2131                 :     115352 : }
    2132                 :            : 
    2133                 :            : 
    2134                 :            : void
    2135                 :    1273818 : parser::parse_functiondecl (std::vector<functiondecl*>& functions)
    2136                 :            : {
    2137         [ +  - ]:    1273818 :   const token* t = next ();
    2138 [ +  - ][ +  - ]:    1273818 :   if (! (t->type == tok_keyword && t->content == "function"))
         [ -  + ][ -  + ]
    2139 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'function'"));
    2140         [ +  - ]:    1273818 :   swallow ();
    2141                 :            : 
    2142         [ +  - ]:    1273818 :   t = next ();
    2143 [ +  + ][ +  + ]:    1273819 :   if (! (t->type == tok_identifier)
                 [ +  + ]
    2144                 :            :       && ! (t->type == tok_keyword
    2145 [ +  - ][ +  - ]:          1 :             && (t->content == "string" || t->content == "long")))
         [ +  - ][ +  - ]
    2146 [ +  - ][ +  - ]:          2 :     throw parse_error (_("expected identifier"));
    2147                 :            : 
    2148         [ +  + ]:   18589757 :   for (unsigned i=0; i<functions.size(); i++)
    2149 [ +  - ][ +  + ]:   17315942 :     if (functions[i]->name == t->content)
    2150 [ +  - ][ +  - ]:          1 :       throw parse_error (_("duplicate function name"));
    2151                 :            : 
    2152 [ +  - ][ +  - ]:    1273815 :   functiondecl *fd = new functiondecl ();
    2153         [ +  - ]:    1273815 :   fd->name = t->content;
    2154                 :    1273815 :   fd->tok = t;
    2155                 :            : 
    2156         [ +  - ]:    1273815 :   t = next ();
    2157 [ +  - ][ +  - ]:    1273815 :   if (t->type == tok_operator && t->content == ":")
         [ +  + ][ +  + ]
    2158                 :            :     {
    2159         [ +  - ]:    1012715 :       swallow ();
    2160         [ +  - ]:    1012715 :       t = next ();
    2161 [ +  + ][ +  - ]:    1012715 :       if (t->type == tok_keyword && t->content == "string")
         [ +  + ][ +  + ]
    2162                 :     325332 :         fd->type = pe_string;
    2163 [ +  + ][ +  - ]:     687383 :       else if (t->type == tok_keyword && t->content == "long")
         [ +  - ][ +  + ]
    2164                 :     687382 :         fd->type = pe_long;
    2165 [ +  - ][ +  - ]:          1 :       else throw parse_error (_("expected 'string' or 'long'"));
    2166         [ +  - ]:    1012714 :       swallow ();
    2167                 :            : 
    2168         [ +  - ]:    1012714 :       t = next ();
    2169                 :            :     }
    2170                 :            : 
    2171 [ +  - ][ +  - ]:    1273814 :   if (! (t->type == tok_operator && t->content == "("))
         [ +  + ][ +  + ]
    2172 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected '('"));
    2173         [ +  - ]:    1273813 :   swallow ();
    2174                 :            : 
    2175                 :     222088 :   while (1)
    2176                 :            :     {
    2177         [ +  - ]:    1495901 :       t = next ();
    2178                 :            : 
    2179                 :            :       // permit zero-argument functions
    2180 [ +  + ][ +  - ]:    1495901 :       if (t->type == tok_operator && t->content == ")")
         [ +  + ][ +  + ]
    2181                 :            :         {
    2182         [ +  - ]:     222245 :           swallow ();
    2183                 :            :           break;
    2184                 :            :         }
    2185         [ +  + ]:    1273656 :       else if (! (t->type == tok_identifier))
    2186 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected identifier"));
    2187 [ +  - ][ +  - ]:    1273655 :       vardecl* vd = new vardecl;
    2188         [ +  - ]:    1273655 :       vd->name = t->content;
    2189                 :    1273655 :       vd->tok = t;
    2190         [ +  - ]:    1273655 :       fd->formal_args.push_back (vd);
    2191                 :    1273655 :       fd->systemtap_v_conditional = systemtap_v_seen;
    2192                 :            : 
    2193         [ +  - ]:    1273655 :       t = next ();
    2194 [ +  + ][ +  - ]:    1273655 :       if (t->type == tok_operator && t->content == ":")
         [ +  + ][ +  + ]
    2195                 :            :         {
    2196         [ +  - ]:    1122669 :           swallow ();
    2197         [ +  - ]:    1122669 :           t = next ();
    2198 [ +  + ][ +  - ]:    1122669 :           if (t->type == tok_keyword && t->content == "string")
         [ +  + ][ +  + ]
    2199                 :     146521 :             vd->type = pe_string;
    2200 [ +  + ][ +  - ]:     976148 :           else if (t->type == tok_keyword && t->content == "long")
         [ +  - ][ +  + ]
    2201                 :     976147 :             vd->type = pe_long;
    2202 [ +  - ][ +  - ]:          1 :           else throw parse_error (_("expected 'string' or 'long'"));
    2203         [ +  - ]:    1122668 :           swallow ();
    2204         [ +  - ]:    1122668 :           t = next ();
    2205                 :            :         }
    2206 [ +  + ][ +  - ]:    1273654 :       if (t->type == tok_operator && t->content == ")")
         [ +  + ][ +  + ]
    2207                 :            :         {
    2208         [ +  - ]:    1051565 :           swallow ();
    2209                 :            :           break;
    2210                 :            :         }
    2211 [ +  + ][ +  - ]:     222089 :       if (t->type == tok_operator && t->content == ",")
         [ +  - ][ +  + ]
    2212                 :            :         {
    2213         [ +  - ]:     222088 :           swallow ();
    2214                 :     222088 :           continue;
    2215                 :            :         }
    2216                 :            :       else
    2217 [ +  - ][ +  - ]:         28 :         throw parse_error (_("expected ',' or ')'"));
    2218                 :            :     }
    2219                 :            : 
    2220         [ +  - ]:    1273810 :   t = peek ();
    2221 [ +  - ][ +  + ]:    1273810 :   if (t && t->type == tok_embedded)
    2222         [ +  + ]:     579675 :     fd->body = parse_embeddedcode ();
    2223                 :            :   else
    2224         [ +  + ]:     694135 :     fd->body = parse_stmt_block ();
    2225                 :            : 
    2226         [ +  - ]:    1273790 :   functions.push_back (fd);
    2227                 :    1273790 : }
    2228                 :            : 
    2229                 :            : 
    2230                 :            : probe_point*
    2231                 :   11005173 : parser::parse_probe_point ()
    2232                 :            : {
    2233         [ +  - ]:   11005173 :   probe_point* pl = new probe_point;
    2234                 :            : 
    2235                 :   18777247 :   while (1)
    2236                 :            :     {
    2237         [ +  + ]:   29782420 :       const token* t = next ();
    2238         [ +  + ]:   29782418 :       if (! (t->type == tok_identifier
    2239                 :            :              // we must allow ".return" and ".function", which are keywords
    2240                 :            :              || t->type == tok_keyword
    2241                 :            :              // we must allow "*", due to being an operator
    2242 [ +  + ][ +  + ]:   29782418 :              || (t->type == tok_operator && t->content == "*")))
         [ +  - ][ +  - ]
                 [ +  + ]
    2243 [ +  - ][ +  - ]:          8 :         throw parse_error (_("expected identifier or '*'"));
    2244                 :            : 
    2245                 :            :       // loop which reconstitutes an identifier with wildcards
    2246         [ +  - ]:   29782410 :       string content = t->content;
    2247                 :        301 :       while (1)
    2248                 :            :         {
    2249         [ +  - ]:   29782711 :           const token* u = peek();
    2250                 :            :           // ensure pieces of the identifier are adjacent:
    2251         [ +  + ]:   29782711 :           if (input.ate_whitespace)
    2252                 :    8424063 :             break;
    2253                 :            :           // ensure pieces of the identifier are valid:
    2254         [ +  + ]:   21358648 :           if (! (u->type == tok_identifier
    2255                 :            :                  // we must allow arbitrary keywords with a wildcard
    2256                 :            :                  || u->type == tok_keyword
    2257                 :            :                  // we must allow "*", due to being an operator
    2258 [ +  + ][ +  - ]:   21358648 :                  || (u->type == tok_operator && u->content == "*")))
         [ +  - ][ +  - ]
                 [ +  + ]
    2259                 :   21358347 :             break;
    2260                 :            : 
    2261                 :            :           // append u to t
    2262 [ +  - ][ +  - ]:        301 :           content = content + u->content;
                 [ +  - ]
    2263                 :            :           
    2264                 :            :           // consume u
    2265         [ +  - ]:        301 :           swallow ();
    2266                 :            :         }
    2267                 :            :       // get around const-ness of t:
    2268 [ +  - ][ +  - ]:   29782410 :       token* new_t = new token(*t);
    2269         [ +  - ]:   29782410 :       new_t->content = content;
    2270 [ +  - ][ +  - ]:   29782410 :       delete t; t = new_t;
    2271                 :            : 
    2272 [ +  - ][ +  - ]:   29782410 :       probe_point::component* c = new probe_point::component;
    2273         [ +  - ]:   29782410 :       c->functor = t->content;
    2274                 :   29782410 :       c->tok = t;
    2275         [ +  - ]:   29782410 :       pl->components.push_back (c);
    2276                 :            :       // NB we may add c->arg soon
    2277                 :            : 
    2278         [ +  - ]:   29782410 :       t = peek ();
    2279                 :            : 
    2280                 :            :       // consume optional parameter
    2281 [ +  - ][ +  + ]:   29782410 :       if (t && t->type == tok_operator && t->content == "(")
         [ +  - ][ +  + ]
                 [ +  + ]
    2282                 :            :         {
    2283         [ +  - ]:    6704177 :           swallow (); // consume "("
    2284         [ +  + ]:    6704177 :           c->arg = parse_literal ();
    2285                 :            : 
    2286         [ +  - ]:    6704167 :           t = next ();
    2287 [ +  + ][ +  - ]:    6704167 :           if (! (t->type == tok_operator && t->content == ")"))
         [ +  + ][ +  + ]
    2288 [ +  - ][ +  - ]:          3 :             throw parse_error (_("expected ')'"));
    2289         [ +  - ]:    6704164 :           swallow ();
    2290                 :            : 
    2291         [ +  - ]:    6704164 :           t = peek ();
    2292                 :            :         }
    2293                 :            : 
    2294 [ +  - ][ +  + ]:   29782397 :       if (t && t->type == tok_operator && t->content == ".")
         [ +  - ][ +  + ]
                 [ +  + ]
    2295                 :            :         {
    2296         [ +  - ]:   18777247 :           swallow ();
    2297                 :   18777247 :           continue;
    2298                 :            :         }
    2299                 :            : 
    2300                 :            :       // We only fall through here at the end of        a probe point (past
    2301                 :            :       // all the dotted/parametrized components).
    2302                 :            : 
    2303 [ +  - ][ +  + ]:   29132414 :       if (t && t->type == tok_operator &&
         [ +  + ][ +  + ]
                 [ +  + ]
    2304 [ +  - ][ +  - ]:   18127264 :           (t->content == "?" || t->content == "!"))
    2305                 :            :         {
    2306                 :    4598142 :           pl->optional = true;
    2307 [ +  - ][ +  + ]:    4598142 :           if (t->content == "!") pl->sufficient = true;
    2308                 :            :           // NB: sufficient implies optional
    2309         [ +  - ]:    4598142 :           swallow ();
    2310         [ +  - ]:    4598142 :           t = peek ();
    2311                 :            :           // fall through
    2312                 :            :         }
    2313                 :            : 
    2314 [ +  - ][ +  + ]:   11005150 :       if (t && t->type == tok_keyword && t->content == "if")
         [ +  - ][ +  - ]
                 [ +  + ]
    2315                 :            :         {
    2316         [ +  - ]:         59 :           swallow ();
    2317         [ +  - ]:         59 :           t = peek ();
    2318 [ +  + ][ +  - ]:         59 :           if (!(t && t->type == tok_operator && t->content == "("))
         [ +  - ][ -  + ]
                 [ +  + ]
    2319 [ +  - ][ +  - ]:          1 :             throw parse_error (_("expected '('"));
    2320         [ +  - ]:         58 :           swallow ();
    2321                 :            : 
    2322         [ +  - ]:         58 :           pl->condition = parse_expression ();
    2323                 :            : 
    2324         [ +  - ]:         58 :           t = peek ();
    2325 [ +  - ][ +  - ]:         58 :           if (!(t && t->type == tok_operator && t->content == ")"))
         [ +  - ][ +  + ]
                 [ +  + ]
    2326 [ +  - ][ +  - ]:          1 :             throw parse_error (_("expected ')'"));
    2327         [ +  - ]:         57 :           swallow ();
    2328         [ +  - ]:         57 :           t = peek ();
    2329                 :            :           // fall through
    2330                 :            :         }
    2331                 :            : 
    2332 [ +  - ][ +  + ]:   32994661 :       if (t && t->type == tok_operator
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
    2333 [ +  - ][ +  - ]:   17650117 :           && (t->content == "{" || t->content == "," ||
    2334 [ +  - ][ +  - ]:    4339396 :               t->content == "=" || t->content == "+=" ))
    2335                 :            :         break;
    2336                 :            : 
    2337 [ +  - ][ +  - ]:          7 :       throw parse_error (_("expected one of '. , ( ? ! { = +='"));
    2338 [ +  - ][ +  + ]:   29782420 :     }
    2339                 :            : 
    2340                 :   11005141 :   return pl;
    2341                 :            : }
    2342                 :            : 
    2343                 :            : 
    2344                 :            : literal_string*
    2345                 :   12858457 : parser::consume_string_literals(const token *t)
    2346                 :            : {
    2347         [ +  - ]:   12858457 :   literal_string *ls = new literal_string (t->content);
    2348                 :            : 
    2349                 :            :   // PR11208: check if the next token is also a string literal;
    2350                 :            :   // auto-concatenate it.  This is complicated to the extent that we
    2351                 :            :   // need to skip intermediate whitespace.
    2352                 :            :   //
    2353                 :            :   // NB for versions prior to 2.0: but don't skip over intervening comments
    2354                 :   12858457 :   const token *n = peek();
    2355         [ +  + ]:   12858529 :   while (n != NULL && n->type == tok_string
           [ +  +  +  + ]
                 [ +  + ]
    2356                 :         36 :          && ! (strverscmp(session.compatible.c_str(), "2.0") < 0
    2357         [ -  + ]:          1 :                && input.ate_comment))
    2358                 :            :     {
    2359                 :         35 :       ls->value.append(next()->content); // consume and append the token
    2360                 :         35 :       n = peek();
    2361                 :            :     }
    2362                 :   12858457 :   return ls;
    2363                 :            : }
    2364                 :            : 
    2365                 :            : 
    2366                 :            : // Parse a string literal and perform backslash escaping on the contents:
    2367                 :            : literal_string*
    2368                 :         60 : parser::parse_literal_string ()
    2369                 :            : {
    2370                 :         60 :   const token* t = next ();
    2371                 :            :   literal_string* l;
    2372         [ +  + ]:         60 :   if (t->type == tok_string)
    2373                 :         55 :     l = consume_string_literals (t);
    2374                 :            :   else
    2375 [ +  - ][ +  - ]:          5 :     throw parse_error (_("expected literal string"));
    2376                 :            : 
    2377                 :         55 :   l->tok = t;
    2378                 :         55 :   return l;
    2379                 :            : }
    2380                 :            : 
    2381                 :            : 
    2382                 :            : literal*
    2383                 :   21064469 : parser::parse_literal ()
    2384                 :            : {
    2385                 :   21064469 :   const token* t = next ();
    2386                 :            :   literal* l;
    2387         [ +  + ]:   21064469 :   if (t->type == tok_string)
    2388                 :            :     {
    2389                 :   12858402 :       l = consume_string_literals (t);
    2390                 :            :     }
    2391                 :            :   else
    2392                 :            :     {
    2393                 :    8206067 :       bool neg = false;
    2394 [ +  + ][ +  + ]:    8206067 :       if (t->type == tok_operator && t->content == "-")
                 [ +  + ]
    2395                 :            :         {
    2396                 :       4378 :           neg = true;
    2397                 :       4378 :           swallow ();
    2398                 :       4378 :           t = next ();
    2399                 :            :         }
    2400                 :            : 
    2401         [ +  + ]:    8206067 :       if (t->type == tok_number)
    2402                 :            :         {
    2403         [ +  - ]:    8206055 :           const char* startp = t->content.c_str ();
    2404                 :    8206055 :           char* endp = (char*) startp;
    2405                 :            : 
    2406                 :            :           // NB: we allow controlled overflow from LLONG_MIN .. ULLONG_MAX
    2407                 :            :           // Actually, this allows all the way from -ULLONG_MAX to ULLONG_MAX,
    2408                 :            :           // since the lexer only gives us positive digit strings, but we'll
    2409                 :            :           // limit it to LLONG_MIN when a '-' operator is fed into the literal.
    2410                 :    8206055 :           errno = 0;
    2411                 :    8206055 :           long long value = (long long) strtoull (startp, & endp, 0);
    2412 [ +  + ][ +  - ]:    8206055 :           if (errno == ERANGE || errno == EINVAL || *endp != '\0'
         [ +  + ][ +  + ]
                 [ -  + ]
    2413                 :            :               || (neg && (unsigned long long) value > 9223372036854775808ULL)
    2414                 :            :               || (unsigned long long) value > 18446744073709551615ULL
    2415                 :            :               || value < -9223372036854775807LL-1)
    2416 [ +  - ][ +  - ]:          5 :             throw parse_error (_("number invalid or out of range"));
    2417                 :            : 
    2418         [ +  + ]:    8206050 :           if (neg)
    2419                 :       4378 :             value = -value;
    2420                 :            : 
    2421 [ +  - ][ +  - ]:    8206055 :           l = new literal_number (value);
    2422                 :            :         }
    2423                 :            :       else
    2424 [ +  - ][ +  - ]:         12 :         throw parse_error (_("expected literal string or number"));
    2425                 :            :     }
    2426                 :            : 
    2427                 :   21064452 :   l->tok = t;
    2428                 :   21064452 :   return l;
    2429                 :            : }
    2430                 :            : 
    2431                 :            : 
    2432                 :            : if_statement*
    2433                 :    2102453 : parser::parse_if_statement ()
    2434                 :            : {
    2435                 :    2102453 :   const token* t = next ();
    2436 [ +  - ][ -  + ]:    2102453 :   if (! (t->type == tok_keyword && t->content == "if"))
                 [ -  + ]
    2437 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'if'"));
    2438         [ +  - ]:    2102453 :   if_statement* s = new if_statement;
    2439                 :    2102453 :   s->tok = t;
    2440                 :            : 
    2441                 :    2102453 :   t = next ();
    2442 [ +  + ][ -  + ]:    2102453 :   if (! (t->type == tok_operator && t->content == "("))
                 [ +  + ]
    2443 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected '('"));
    2444                 :    2102452 :   swallow ();
    2445                 :            : 
    2446                 :    2102452 :   s->condition = parse_expression ();
    2447                 :            : 
    2448                 :    2102451 :   t = next ();
    2449 [ +  + ][ -  + ]:    2102451 :   if (! (t->type == tok_operator && t->content == ")"))
                 [ +  + ]
    2450 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected ')'"));
    2451                 :    2102450 :   swallow ();
    2452                 :            : 
    2453                 :    2102450 :   s->thenblock = parse_statement ();
    2454                 :            : 
    2455                 :    2102450 :   t = peek ();
    2456 [ +  - ][ +  + ]:    2102450 :   if (t && t->type == tok_keyword && t->content == "else")
         [ +  + ][ +  + ]
    2457                 :            :     {
    2458                 :     368822 :       swallow ();
    2459                 :     368822 :       s->elseblock = parse_statement ();
    2460                 :            :     }
    2461                 :            :   else
    2462                 :    1733628 :     s->elseblock = 0; // in case not otherwise initialized
    2463                 :            : 
    2464                 :    2102450 :   return s;
    2465                 :            : }
    2466                 :            : 
    2467                 :            : 
    2468                 :            : expr_statement*
    2469                 :   20052787 : parser::parse_expr_statement ()
    2470                 :            : {
    2471         [ +  - ]:   20052787 :   expr_statement *es = new expr_statement;
    2472                 :   20052787 :   const token* t = peek ();
    2473                 :            :   // Copy, we only peeked, parse_expression might swallow.
    2474         [ +  - ]:   20052787 :   es->tok = new token (*t);
    2475                 :   20052787 :   es->value = parse_expression ();
    2476                 :   20052769 :   return es;
    2477                 :            : }
    2478                 :            : 
    2479                 :            : 
    2480                 :            : return_statement*
    2481                 :    1753741 : parser::parse_return_statement ()
    2482                 :            : {
    2483                 :    1753741 :   const token* t = next ();
    2484 [ +  - ][ -  + ]:    1753741 :   if (! (t->type == tok_keyword && t->content == "return"))
                 [ -  + ]
    2485 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'return'"));
    2486         [ +  + ]:    1753741 :   if (context != con_function)
    2487 [ +  - ][ +  - ]:          1 :     throw parse_error (_("found 'return' not in function context"));
    2488         [ +  - ]:    1753740 :   return_statement* s = new return_statement;
    2489                 :    1753740 :   s->tok = t;
    2490                 :    1753740 :   s->value = parse_expression ();
    2491                 :    1753740 :   return s;
    2492                 :            : }
    2493                 :            : 
    2494                 :            : 
    2495                 :            : delete_statement*
    2496                 :      28254 : parser::parse_delete_statement ()
    2497                 :            : {
    2498                 :      28254 :   const token* t = next ();
    2499 [ +  - ][ -  + ]:      28254 :   if (! (t->type == tok_keyword && t->content == "delete"))
                 [ -  + ]
    2500 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'delete'"));
    2501         [ +  - ]:      28254 :   delete_statement* s = new delete_statement;
    2502                 :      28254 :   s->tok = t;
    2503                 :      28254 :   s->value = parse_expression ();
    2504                 :      28254 :   return s;
    2505                 :            : }
    2506                 :            : 
    2507                 :            : 
    2508                 :            : next_statement*
    2509                 :      62712 : parser::parse_next_statement ()
    2510                 :            : {
    2511                 :      62712 :   const token* t = next ();
    2512 [ +  - ][ -  + ]:      62712 :   if (! (t->type == tok_keyword && t->content == "next"))
                 [ -  + ]
    2513 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'next'"));
    2514         [ +  + ]:      62712 :   if (context != con_probe)
    2515 [ +  - ][ +  - ]:          1 :     throw parse_error (_("found 'next' not in probe context"));
    2516         [ +  - ]:      62711 :   next_statement* s = new next_statement;
    2517                 :      62711 :   s->tok = t;
    2518                 :      62711 :   return s;
    2519                 :            : }
    2520                 :            : 
    2521                 :            : 
    2522                 :            : break_statement*
    2523                 :      19431 : parser::parse_break_statement ()
    2524                 :            : {
    2525                 :      19431 :   const token* t = next ();
    2526 [ +  - ][ -  + ]:      19431 :   if (! (t->type == tok_keyword && t->content == "break"))
                 [ -  + ]
    2527 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'break'"));
    2528         [ +  - ]:      19431 :   break_statement* s = new break_statement;
    2529                 :      19431 :   s->tok = t;
    2530                 :      19431 :   return s;
    2531                 :            : }
    2532                 :            : 
    2533                 :            : 
    2534                 :            : continue_statement*
    2535                 :       2223 : parser::parse_continue_statement ()
    2536                 :            : {
    2537                 :       2223 :   const token* t = next ();
    2538 [ +  - ][ -  + ]:       2223 :   if (! (t->type == tok_keyword && t->content == "continue"))
                 [ -  + ]
    2539 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'continue'"));
    2540         [ +  - ]:       2223 :   continue_statement* s = new continue_statement;
    2541                 :       2223 :   s->tok = t;
    2542                 :       2223 :   return s;
    2543                 :            : }
    2544                 :            : 
    2545                 :            : 
    2546                 :            : for_loop*
    2547                 :       6823 : parser::parse_for_loop ()
    2548                 :            : {
    2549                 :       6823 :   const token* t = next ();
    2550 [ +  - ][ -  + ]:       6823 :   if (! (t->type == tok_keyword && t->content == "for"))
                 [ -  + ]
    2551 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'for'"));
    2552         [ +  - ]:       6823 :   for_loop* s = new for_loop;
    2553                 :       6823 :   s->tok = t;
    2554                 :            : 
    2555                 :       6823 :   t = next ();
    2556 [ +  + ][ -  + ]:       6823 :   if (! (t->type == tok_operator && t->content == "("))
                 [ +  + ]
    2557 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected '('"));
    2558                 :       6822 :   swallow ();
    2559                 :            : 
    2560                 :            :   // initializer + ";"
    2561                 :       6822 :   t = peek ();
    2562 [ +  - ][ +  + ]:       6822 :   if (t && t->type == tok_operator && t->content == ";")
         [ +  + ][ +  + ]
    2563                 :            :     {
    2564                 :         34 :       s->init = 0;
    2565                 :         34 :       swallow ();
    2566                 :            :     }
    2567                 :            :   else
    2568                 :            :     {
    2569                 :       6788 :       s->init = parse_expr_statement ();
    2570                 :       6788 :       t = next ();
    2571 [ +  - ][ +  + ]:       6788 :       if (! (t->type == tok_operator && t->content == ";"))
                 [ +  + ]
    2572 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected ';'"));
    2573                 :       6787 :       swallow ();
    2574                 :            :     }
    2575                 :            : 
    2576                 :            :   // condition + ";"
    2577                 :       6821 :   t = peek ();
    2578 [ +  - ][ +  + ]:       6821 :   if (t && t->type == tok_operator && t->content == ";")
         [ +  + ][ +  + ]
    2579                 :            :     {
    2580         [ +  - ]:         16 :       literal_number* l = new literal_number(1);
    2581                 :         16 :       s->cond = l;
    2582                 :         16 :       s->cond->tok = next ();
    2583                 :            :     }
    2584                 :            :   else
    2585                 :            :     {
    2586                 :       6805 :       s->cond = parse_expression ();
    2587                 :       6805 :       t = next ();
    2588 [ +  - ][ +  + ]:       6805 :       if (! (t->type == tok_operator && t->content == ";"))
                 [ +  + ]
    2589 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected ';'"));
    2590                 :       6804 :       swallow ();
    2591                 :            :     }
    2592                 :            : 
    2593                 :            :   // increment + ")"
    2594                 :       6820 :   t = peek ();
    2595 [ +  - ][ +  + ]:       6820 :   if (t && t->type == tok_operator && t->content == ")")
         [ +  + ][ +  + ]
    2596                 :            :     {
    2597                 :         38 :       s->incr = 0;
    2598                 :         38 :       swallow ();
    2599                 :            :     }
    2600                 :            :   else
    2601                 :            :     {
    2602                 :       6782 :       s->incr = parse_expr_statement ();
    2603                 :       6782 :       t = next ();
    2604 [ +  + ][ -  + ]:       6782 :       if (! (t->type == tok_operator && t->content == ")"))
                 [ +  + ]
    2605 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected ')'"));
    2606                 :       6781 :       swallow ();
    2607                 :            :     }
    2608                 :            : 
    2609                 :            :   // block
    2610                 :       6819 :   s->block = parse_statement ();
    2611                 :            : 
    2612                 :       6819 :   return s;
    2613                 :            : }
    2614                 :            : 
    2615                 :            : 
    2616                 :            : for_loop*
    2617                 :      25920 : parser::parse_while_loop ()
    2618                 :            : {
    2619                 :      25920 :   const token* t = next ();
    2620 [ +  - ][ -  + ]:      25920 :   if (! (t->type == tok_keyword && t->content == "while"))
                 [ -  + ]
    2621 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'while'"));
    2622         [ +  - ]:      25920 :   for_loop* s = new for_loop;
    2623                 :      25920 :   s->tok = t;
    2624                 :            : 
    2625                 :      25920 :   t = next ();
    2626 [ +  + ][ -  + ]:      25920 :   if (! (t->type == tok_operator && t->content == "("))
                 [ +  + ]
    2627 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected '('"));
    2628                 :      25919 :   swallow ();
    2629                 :            : 
    2630                 :            :   // dummy init and incr fields
    2631                 :      25919 :   s->init = 0;
    2632                 :      25919 :   s->incr = 0;
    2633                 :            : 
    2634                 :            :   // condition
    2635                 :      25919 :   s->cond = parse_expression ();
    2636                 :            : 
    2637                 :      25919 :   t = next ();
    2638 [ +  + ][ -  + ]:      25919 :   if (! (t->type == tok_operator && t->content == ")"))
                 [ +  + ]
    2639 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected ')'"));
    2640                 :      25918 :   swallow ();
    2641                 :            : 
    2642                 :            :   // block
    2643                 :      25918 :   s->block = parse_statement ();
    2644                 :            : 
    2645                 :      25918 :   return s;
    2646                 :            : }
    2647                 :            : 
    2648                 :            : 
    2649                 :            : foreach_loop*
    2650                 :      17574 : parser::parse_foreach_loop ()
    2651                 :            : {
    2652         [ +  - ]:      17574 :   const token* t = next ();
    2653 [ +  - ][ +  - ]:      17574 :   if (! (t->type == tok_keyword && t->content == "foreach"))
         [ -  + ][ -  + ]
    2654 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected 'foreach'"));
    2655 [ +  - ][ +  - ]:      17574 :   foreach_loop* s = new foreach_loop;
    2656                 :      17574 :   s->tok = t;
    2657                 :      17574 :   s->sort_direction = 0;
    2658                 :      17574 :   s->sort_aggr = sc_none;
    2659                 :      17574 :   s->value = NULL;
    2660                 :      17574 :   s->limit = NULL;
    2661                 :            : 
    2662         [ +  - ]:      17574 :   t = next ();
    2663 [ +  + ][ +  - ]:      17574 :   if (! (t->type == tok_operator && t->content == "("))
         [ -  + ][ +  + ]
    2664 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected '('"));
    2665         [ +  - ]:      17573 :   swallow ();
    2666                 :            : 
    2667                 :      17573 :   symbol* lookahead_sym = NULL;
    2668                 :      17573 :   int lookahead_sort = 0;
    2669                 :            : 
    2670         [ +  - ]:      17573 :   t = peek ();
    2671 [ +  - ][ +  + ]:      17573 :   if (t && t->type == tok_identifier)
    2672                 :            :     {
    2673         [ +  - ]:      10984 :       next ();
    2674 [ +  - ][ +  - ]:      10984 :       lookahead_sym = new symbol;
    2675                 :      10984 :       lookahead_sym->tok = t;
    2676         [ +  - ]:      10984 :       lookahead_sym->name = t->content;
    2677                 :            : 
    2678         [ +  - ]:      10984 :       t = peek ();
    2679 [ +  - ][ +  + ]:      11029 :       if (t && t->type == tok_operator &&
         [ +  + ][ +  + ]
                 [ +  + ]
    2680 [ +  - ][ +  - ]:         45 :           (t->content == "+" || t->content == "-"))
    2681                 :            :         {
    2682 [ +  - ][ +  + ]:         23 :           lookahead_sort = (t->content == "+") ? 1 : -1;
    2683         [ +  - ]:         23 :           swallow ();
    2684                 :            :         }
    2685                 :            : 
    2686         [ +  - ]:      10984 :       t = peek ();
    2687 [ +  - ][ +  + ]:      10984 :       if (t && t->type == tok_operator && t->content == "=")
         [ +  - ][ +  + ]
                 [ +  + ]
    2688                 :            :         {
    2689         [ +  - ]:         10 :           swallow ();
    2690                 :         10 :           s->value = lookahead_sym;
    2691         [ +  + ]:         10 :           if (lookahead_sort)
    2692                 :            :             {
    2693                 :          2 :               s->sort_direction = lookahead_sort;
    2694                 :          2 :               s->sort_column = 0;
    2695                 :            :             }
    2696                 :         10 :           lookahead_sym = NULL;
    2697                 :            :         }
    2698                 :            :     }
    2699                 :            : 
    2700                 :            :   // see also parse_array_in
    2701                 :            : 
    2702                 :      17573 :   bool parenthesized = false;
    2703         [ +  - ]:      17573 :   t = peek ();
    2704 [ +  + ][ +  - ]:      17573 :   if (!lookahead_sym && t && t->type == tok_operator && t->content == "[")
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
    2705                 :            :     {
    2706         [ +  - ]:       6589 :       swallow ();
    2707                 :       6589 :       parenthesized = true;
    2708                 :            :     }
    2709                 :            : 
    2710         [ +  + ]:      17573 :   if (lookahead_sym)
    2711                 :            :     {
    2712         [ +  - ]:      10974 :       s->indexes.push_back (lookahead_sym);
    2713         [ +  + ]:      10974 :       if (lookahead_sort)
    2714                 :            :         {
    2715                 :         21 :           s->sort_direction = lookahead_sort;
    2716                 :         21 :           s->sort_column = 1;
    2717                 :            :         }
    2718                 :      10974 :       lookahead_sym = NULL;
    2719                 :            :     }
    2720                 :       6627 :   else while (1)
    2721                 :            :     {
    2722         [ +  - ]:      13226 :       t = next ();
    2723         [ +  + ]:      13226 :       if (! (t->type == tok_identifier))
    2724 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected identifier"));
    2725 [ +  - ][ +  - ]:      13225 :       symbol* sym = new symbol;
    2726                 :      13225 :       sym->tok = t;
    2727         [ +  - ]:      13225 :       sym->name = t->content;
    2728         [ +  - ]:      13225 :       s->indexes.push_back (sym);
    2729                 :            : 
    2730         [ +  - ]:      13225 :       t = peek ();
    2731 [ +  - ][ +  + ]:      37484 :       if (t && t->type == tok_operator &&
         [ +  + ][ +  + ]
                 [ +  + ]
    2732 [ +  - ][ +  - ]:      24259 :           (t->content == "+" || t->content == "-"))
    2733                 :            :         {
    2734         [ +  + ]:       2181 :           if (s->sort_direction)
    2735 [ +  - ][ +  - ]:          1 :             throw parse_error (_("multiple sort directives"));
    2736 [ +  - ][ +  + ]:       2180 :           s->sort_direction = (t->content == "+") ? 1 : -1;
    2737                 :       2180 :           s->sort_column = s->indexes.size();
    2738         [ +  - ]:       2180 :           swallow ();
    2739                 :            :         }
    2740                 :            : 
    2741         [ +  + ]:      13224 :       if (parenthesized)
    2742                 :            :         {
    2743         [ +  - ]:      13215 :           t = peek ();
    2744 [ +  - ][ +  + ]:      13215 :           if (t && t->type == tok_operator && t->content == ",")
         [ +  - ][ +  + ]
                 [ +  + ]
    2745                 :            :             {
    2746         [ +  - ]:       6627 :               swallow ();
    2747                 :       6627 :               continue;
    2748                 :            :             }
    2749 [ +  - ][ +  + ]:       6588 :           else if (t && t->type == tok_operator && t->content == "]")
         [ +  - ][ +  - ]
                 [ +  + ]
    2750                 :            :             {
    2751         [ +  - ]:       6587 :               swallow ();
    2752                 :            :               break;
    2753                 :            :             }
    2754                 :            :           else
    2755 [ +  - ][ +  - ]:       6599 :             throw parse_error (_("expected ',' or ']'"));
    2756                 :            :         }
    2757                 :            :       else
    2758                 :            :         break; // expecting only one expression
    2759                 :            :     }
    2760                 :            : 
    2761         [ +  - ]:      17570 :   t = next ();
    2762 [ +  + ][ +  - ]:      17570 :   if (! (t->type == tok_keyword && t->content == "in"))
         [ -  + ][ +  + ]
    2763 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected 'in'"));
    2764         [ +  - ]:      17569 :   swallow ();
    2765                 :            : 
    2766         [ +  + ]:      17569 :   s->base = parse_indexable();
    2767                 :            : 
    2768                 :            :   // check for atword, see also expect_ident_or_atword,
    2769         [ +  - ]:      17568 :   t = peek ();
    2770 [ +  - ][ +  + ]:      17568 :   if (t && t->type == tok_operator && t->content[0] == '@')
         [ +  - ][ +  + ]
                 [ +  + ]
    2771                 :            :     {
    2772 [ +  - ][ +  + ]:         16 :       if (t->content == "@avg") s->sort_aggr = sc_average;
    2773 [ +  - ][ +  + ]:         14 :       else if (t->content == "@min") s->sort_aggr = sc_min;
    2774 [ +  - ][ +  + ]:         12 :       else if (t->content == "@max") s->sort_aggr = sc_max;
    2775 [ +  - ][ +  + ]:         10 :       else if (t->content == "@count") s->sort_aggr = sc_count;
    2776 [ +  - ][ +  + ]:          8 :       else if (t->content == "@sum") s->sort_aggr = sc_sum;
    2777 [ +  - ][ +  - ]:          1 :       else throw parse_error(_("expected statistical operation"));
    2778         [ +  - ]:         15 :       swallow();
    2779                 :            : 
    2780         [ +  - ]:         15 :       t = peek ();
    2781 [ +  - ][ +  - ]:         15 :       if (! (t && t->type == tok_operator && (t->content == "+" || t->content == "-")))
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
                 [ +  + ]
    2782 [ +  - ][ +  - ]:          1 :         throw parse_error(_("expected sort directive"));
    2783                 :            :     } 
    2784                 :            : 
    2785         [ +  - ]:      17566 :   t = peek ();
    2786 [ +  - ][ +  + ]:      50467 :   if (t && t->type == tok_operator &&
         [ +  + ][ +  + ]
                 [ +  + ]
    2787 [ +  - ][ +  - ]:      32901 :       (t->content == "+" || t->content == "-"))
    2788                 :            :     {
    2789         [ +  + ]:       2273 :       if (s->sort_direction)
    2790 [ +  - ][ +  - ]:          1 :         throw parse_error (_("multiple sort directives"));
    2791 [ +  - ][ +  + ]:       2272 :       s->sort_direction = (t->content == "+") ? 1 : -1;
    2792                 :       2272 :       s->sort_column = 0;
    2793         [ +  - ]:       2272 :       swallow ();
    2794                 :            :     }
    2795                 :            : 
    2796         [ +  - ]:      17565 :   t = peek ();
    2797 [ +  - ][ +  - ]:      17565 :   if (tok_is(t, tok_keyword, "limit"))
         [ +  - ][ +  + ]
    2798                 :            :     {
    2799         [ +  - ]:         77 :       swallow ();                       // get past the "limit"
    2800         [ +  + ]:         77 :       s->limit = parse_expression ();
    2801                 :            :     }
    2802                 :            : 
    2803         [ +  - ]:      17564 :   t = next ();
    2804 [ +  + ][ +  - ]:      17564 :   if (! (t->type == tok_operator && t->content == ")"))
         [ -  + ][ +  + ]
    2805 [ +  - ][ +  - ]:         12 :     throw parse_error ("expected ')'");
    2806         [ +  - ]:      17562 :   swallow ();
    2807                 :            : 
    2808         [ +  - ]:      17562 :   s->block = parse_statement ();
    2809                 :      17562 :   return s;
    2810                 :            : }
    2811                 :            : 
    2812                 :            : 
    2813                 :            : expression*
    2814                 :   64679728 : parser::parse_expression ()
    2815                 :            : {
    2816                 :   64679728 :   return parse_assignment ();
    2817                 :            : }
    2818                 :            : 
    2819                 :            : 
    2820                 :            : expression*
    2821                 :   64679728 : parser::parse_assignment ()
    2822                 :            : {
    2823                 :   64679728 :   expression* op1 = parse_ternary ();
    2824                 :            : 
    2825                 :   64679707 :   const token* t = peek ();
    2826                 :            :   // right-associative operators
    2827 [ +  - ][ +  +  :  466436601 :   if (t && t->type == tok_operator
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
              + ][ +  + ]
    2828                 :   48631486 :       && (t->content == "=" ||
    2829                 :   29520189 :           t->content == "<<<" ||
    2830                 :   29513476 :           t->content == "+=" ||
    2831                 :   29422827 :           t->content == "-=" ||
    2832                 :   29418492 :           t->content == "*=" ||
    2833                 :   29418467 :           t->content == "/=" ||
    2834                 :   29418446 :           t->content == "%=" ||
    2835                 :   29418431 :           t->content == "<<=" ||
    2836                 :   29418420 :           t->content == ">>=" ||
    2837                 :   29418411 :           t->content == "&=" ||
    2838                 :   29386092 :           t->content == "^=" ||
    2839                 :   29386083 :           t->content == "|=" ||
    2840                 :   29386074 :           t->content == ".=" ||
    2841                 :            :           false))
    2842                 :            :     {
    2843                 :            :       // NB: lvalueness is checked during elaboration / translation
    2844         [ +  - ]:   19273449 :       assignment* e = new assignment;
    2845                 :   19273449 :       e->left = op1;
    2846                 :   19273449 :       e->op = t->content;
    2847                 :   19273449 :       e->tok = t;
    2848                 :   19273449 :       next ();
    2849                 :   19273449 :       e->right = parse_expression ();
    2850                 :   19273441 :       op1 = e;
    2851                 :            :     }
    2852                 :            : 
    2853                 :   64679699 :   return op1;
    2854                 :            : }
    2855                 :            : 
    2856                 :            : 
    2857                 :            : expression*
    2858                 :   64679728 : parser::parse_ternary ()
    2859                 :            : {
    2860                 :   64679728 :   expression* op1 = parse_logical_or ();
    2861                 :            : 
    2862                 :   64679708 :   const token* t = peek ();
    2863 [ +  - ][ +  + ]:   64679708 :   if (t && t->type == tok_operator && t->content == "?")
         [ +  + ][ +  + ]
    2864                 :            :     {
    2865         [ +  - ]:     743414 :       ternary_expression* e = new ternary_expression;
    2866                 :     743414 :       e->tok = t;
    2867                 :     743414 :       e->cond = op1;
    2868                 :     743414 :       next ();
    2869                 :     743414 :       e->truevalue = parse_expression (); // XXX
    2870                 :            : 
    2871                 :     743414 :       t = next ();
    2872 [ +  - ][ +  + ]:     743414 :       if (! (t->type == tok_operator && t->content == ":"))
                 [ +  + ]
    2873 [ +  - ][ +  - ]:          1 :         throw parse_error (_("expected ':'"));
    2874                 :     743413 :       swallow ();
    2875                 :            : 
    2876                 :     743413 :       e->falsevalue = parse_expression (); // XXX
    2877                 :     743413 :       return e;
    2878                 :            :     }
    2879                 :            :   else
    2880                 :   64679707 :     return op1;
    2881                 :            : }
    2882                 :            : 
    2883                 :            : 
    2884                 :            : expression*
    2885                 :   64679728 : parser::parse_logical_or ()
    2886                 :            : {
    2887                 :   64679728 :   expression* op1 = parse_logical_and ();
    2888                 :            : 
    2889                 :   64679708 :   const token* t = peek ();
    2890 [ +  - ][ +  + ]:   64707869 :   while (t && t->type == tok_operator && t->content == "||")
         [ +  + ][ +  + ]
    2891                 :            :     {
    2892         [ +  - ]:      28161 :       logical_or_expr* e = new logical_or_expr;
    2893                 :      28161 :       e->tok = t;
    2894                 :      28161 :       e->op = t->content;
    2895                 :      28161 :       e->left = op1;
    2896                 :      28161 :       next ();
    2897                 :      28161 :       e->right = parse_logical_and ();
    2898                 :      28161 :       op1 = e;
    2899                 :      28161 :       t = peek ();
    2900                 :            :     }
    2901                 :            : 
    2902                 :   64679708 :   return op1;
    2903                 :            : }
    2904                 :            : 
    2905                 :            : 
    2906                 :            : expression*
    2907                 :   64707889 : parser::parse_logical_and ()
    2908                 :            : {
    2909                 :   64707889 :   expression* op1 = parse_boolean_or ();
    2910                 :            : 
    2911                 :   64707869 :   const token* t = peek ();
    2912 [ +  - ][ +  + ]:   64764094 :   while (t && t->type == tok_operator && t->content == "&&")
         [ +  + ][ +  + ]
    2913                 :            :     {
    2914         [ +  - ]:      56225 :       logical_and_expr *e = new logical_and_expr;
    2915                 :      56225 :       e->left = op1;
    2916                 :      56225 :       e->op = t->content;
    2917                 :      56225 :       e->tok = t;
    2918                 :      56225 :       next ();
    2919                 :      56225 :       e->right = parse_boolean_or ();
    2920                 :      56225 :       op1 = e;
    2921                 :      56225 :       t = peek ();
    2922                 :            :     }
    2923                 :            : 
    2924                 :   64707869 :   return op1;
    2925                 :            : }
    2926                 :            : 
    2927                 :            : 
    2928                 :            : expression*
    2929                 :   64764114 : parser::parse_boolean_or ()
    2930                 :            : {
    2931                 :   64764114 :   expression* op1 = parse_boolean_xor ();
    2932                 :            : 
    2933                 :   64764094 :   const token* t = peek ();
    2934 [ +  - ][ +  + ]:   64766267 :   while (t && t->type == tok_operator && t->content == "|")
         [ +  + ][ +  + ]
    2935                 :            :     {
    2936         [ +  - ]:       2173 :       binary_expression* e = new binary_expression;
    2937                 :       2173 :       e->left = op1;
    2938                 :       2173 :       e->op = t->content;
    2939                 :       2173 :       e->tok = t;
    2940                 :       2173 :       next ();
    2941                 :       2173 :       e->right = parse_boolean_xor ();
    2942                 :       2173 :       op1 = e;
    2943                 :       2173 :       t = peek ();
    2944                 :            :     }
    2945                 :            : 
    2946                 :   64764094 :   return op1;
    2947                 :            : }
    2948                 :            : 
    2949                 :            : 
    2950                 :            : expression*
    2951                 :   64766287 : parser::parse_boolean_xor ()
    2952                 :            : {
    2953                 :   64766287 :   expression* op1 = parse_boolean_and ();
    2954                 :            : 
    2955                 :   64766267 :   const token* t = peek ();
    2956 [ +  - ][ +  + ]:   64766283 :   while (t && t->type == tok_operator && t->content == "^")
         [ +  + ][ +  + ]
    2957                 :            :     {
    2958         [ +  - ]:         16 :       binary_expression* e = new binary_expression;
    2959                 :         16 :       e->left = op1;
    2960                 :         16 :       e->op = t->content;
    2961                 :         16 :       e->tok = t;
    2962                 :         16 :       next ();
    2963                 :         16 :       e->right = parse_boolean_and ();
    2964                 :         16 :       op1 = e;
    2965                 :         16 :       t = peek ();
    2966                 :            :     }
    2967                 :            : 
    2968                 :   64766267 :   return op1;
    2969                 :            : }
    2970                 :            : 
    2971                 :            : 
    2972                 :            : expression*
    2973                 :   64766303 : parser::parse_boolean_and ()
    2974                 :            : {
    2975                 :   64766303 :   expression* op1 = parse_array_in ();
    2976                 :            : 
    2977                 :   64766283 :   const token* t = peek ();
    2978 [ +  - ][ +  + ]:   65011925 :   while (t && t->type == tok_operator && t->content == "&")
         [ +  + ][ +  + ]
    2979                 :            :     {
    2980         [ +  - ]:     245642 :       binary_expression* e = new binary_expression;
    2981                 :     245642 :       e->left = op1;
    2982                 :     245642 :       e->op = t->content;
    2983                 :     245642 :       e->tok = t;
    2984                 :     245642 :       next ();
    2985                 :     245642 :       e->right = parse_array_in ();
    2986                 :     245642 :       op1 = e;
    2987                 :     245642 :       t = peek ();
    2988                 :            :     }
    2989                 :            : 
    2990                 :   64766283 :   return op1;
    2991                 :            : }
    2992                 :            : 
    2993                 :            : 
    2994                 :            : expression*
    2995                 :   65011945 : parser::parse_array_in ()
    2996                 :            : {
    2997                 :            :   // This is a very tricky case.  All these are legit expressions:
    2998                 :            :   // "a in b"  "a+0 in b" "[a,b] in c" "[c,(d+0)] in b"
    2999         [ +  - ]:   65011945 :   vector<expression*> indexes;
    3000                 :   65011945 :   bool parenthesized = false;
    3001                 :            : 
    3002         [ +  - ]:   65011945 :   const token* t = peek ();
    3003 [ +  - ][ +  + ]:   65011945 :   if (t && t->type == tok_operator && t->content == "[")
         [ +  - ][ +  + ]
                 [ +  + ]
    3004                 :            :     {
    3005         [ +  - ]:       2217 :       swallow ();
    3006                 :       2217 :       parenthesized = true;
    3007                 :            :     }
    3008                 :            : 
    3009                 :         33 :   while (1)
    3010                 :            :     {
    3011         [ +  + ]:   65011978 :       expression* op1 = parse_comparison_or_regex_query ();
    3012         [ +  - ]:   65011958 :       indexes.push_back (op1);
    3013                 :            : 
    3014         [ +  + ]:   65011958 :       if (parenthesized)
    3015                 :            :         {
    3016         [ +  - ]:       2249 :           const token* t = peek ();
    3017 [ +  - ][ +  - ]:       2249 :           if (t && t->type == tok_operator && t->content == ",")
         [ +  - ][ +  + ]
                 [ +  + ]
    3018                 :            :             {
    3019         [ +  - ]:         33 :               swallow ();
    3020                 :         33 :               continue;
    3021                 :            :             }
    3022 [ +  - ][ +  - ]:       2216 :           else if (t && t->type == tok_operator && t->content == "]")
         [ +  - ][ +  - ]
                 [ +  - ]
    3023                 :            :             {
    3024         [ +  - ]:       2216 :               swallow ();
    3025                 :            :               break;
    3026                 :            :             }
    3027                 :            :           else
    3028 [ #  # ][ #  # ]:         20 :             throw parse_error (_("expected ',' or ']'"));
    3029                 :            :         }
    3030                 :            :       else
    3031                 :            :         break; // expecting only one expression
    3032                 :            :     }
    3033                 :            : 
    3034         [ +  - ]:   65011925 :   t = peek ();
    3035 [ +  - ][ +  + ]:   65011925 :   if (t && t->type == tok_keyword && t->content == "in")
         [ +  - ][ +  + ]
                 [ +  + ]
    3036                 :            :     {
    3037 [ +  - ][ +  - ]:      34629 :       array_in *e = new array_in;
    3038                 :      34629 :       e->tok = t;
    3039         [ +  - ]:      34629 :       next ();
    3040                 :            : 
    3041 [ +  - ][ +  - ]:      34629 :       arrayindex* a = new arrayindex;
    3042         [ +  - ]:      34629 :       a->indexes = indexes;
    3043         [ +  - ]:      34629 :       a->base = parse_indexable();
    3044                 :      34629 :       a->tok = a->base->tok;
    3045                 :      34629 :       e->operand = a;
    3046                 :      34629 :       return e;
    3047                 :            :     }
    3048         [ +  - ]:   64977296 :   else if (indexes.size() == 1) // no "in" - need one expression only
    3049                 :   64977296 :     return indexes[0];
    3050                 :            :   else
    3051 [ #  # ][ #  # ]:   65011945 :     throw parse_error (_("unexpected comma-separated expression list"));
                 [ +  - ]
    3052                 :            : }
    3053                 :            : 
    3054                 :            : 
    3055                 :            : expression*
    3056                 :   65011978 : parser::parse_comparison_or_regex_query ()
    3057                 :            : {
    3058                 :   65011978 :   expression* op1 = parse_shift ();
    3059                 :            : 
    3060                 :            :   // TODOXXX for now, =~ is nonassociative
    3061                 :            :   // TODOXXX maybe instead a =~ b == c =~ d --> (a =~ b) == (c =~ d) ??
    3062                 :   65011962 :   const token *t = peek();
    3063 [ +  - ][ +  +  :  163159080 :   if (t && t->type == tok_operator
             +  +  +  + ]
                 [ +  + ]
    3064                 :   49073574 :       && (t->content == "=~" ||
    3065                 :   49073544 :           t->content == "!~"))
    3066                 :            :     {
    3067         [ +  - ]:         51 :       regex_query* r = new regex_query;
    3068                 :         51 :       r->left = op1;
    3069                 :         51 :       r->op = t->content;
    3070                 :         51 :       r->tok = t;
    3071                 :         51 :       next ();
    3072                 :         51 :       r->right = r->re = parse_literal_string();
    3073                 :         47 :       op1 = r;
    3074                 :         47 :       t = peek ();
    3075                 :            :     }
    3076 [ +  - ][ +  +  :  366504641 :   else while (t && t->type == tok_operator
          +  +  +  +  +  
          +  +  +  +  +  
           +  + ][ +  + ]
    3077                 :   50871971 :       && (t->content == ">" ||
    3078                 :   50721040 :           t->content == "<" ||
    3079                 :   50662557 :           t->content == "==" ||
    3080                 :   49231210 :           t->content == "!=" ||
    3081                 :   49112381 :           t->content == "<=" ||
    3082                 :   49095081 :           t->content == ">="))
    3083                 :            :     {
    3084         [ +  - ]:    1798490 :       comparison* e = new comparison;
    3085                 :    1798490 :       e->left = op1;
    3086                 :    1798490 :       e->op = t->content;
    3087                 :    1798490 :       e->tok = t;
    3088                 :    1798490 :       next ();
    3089                 :    1798490 :       e->right = parse_shift ();
    3090                 :    1798490 :       op1 = e;
    3091                 :    1798490 :       t = peek ();
    3092                 :            :     }
    3093                 :            : 
    3094                 :   65011958 :   return op1;
    3095                 :            : }
    3096                 :            : 
    3097                 :            : 
    3098                 :            : expression*
    3099                 :   66810468 : parser::parse_shift ()
    3100                 :            : {
    3101                 :   66810468 :   expression* op1 = parse_concatenation ();
    3102                 :            : 
    3103                 :   66810452 :   const token* t = peek ();
    3104 [ +  - ][ +  +  :  168597725 :   while (t && t->type == tok_operator &&
             +  +  +  + ]
                 [ +  + ]
    3105                 :  101769982 :          (t->content == "<<" || t->content == ">>"))
    3106                 :            :     {
    3107         [ +  - ]:      17291 :       binary_expression* e = new binary_expression;
    3108                 :      17291 :       e->left = op1;
    3109                 :      17291 :       e->op = t->content;
    3110                 :      17291 :       e->tok = t;
    3111                 :      17291 :       next ();
    3112                 :      17291 :       e->right = parse_concatenation ();
    3113                 :      17291 :       op1 = e;
    3114                 :      17291 :       t = peek ();
    3115                 :            :     }
    3116                 :            : 
    3117                 :   66810452 :   return op1;
    3118                 :            : }
    3119                 :            : 
    3120                 :            : 
    3121                 :            : expression*
    3122                 :   66827759 : parser::parse_concatenation ()
    3123                 :            : {
    3124                 :   66827759 :   expression* op1 = parse_additive ();
    3125                 :            : 
    3126                 :   66827743 :   const token* t = peek ();
    3127                 :            :   // XXX: the actual awk string-concatenation operator is *whitespace*.
    3128                 :            :   // I don't know how to easily to model that here.
    3129 [ +  - ][ +  + ]:   67026271 :   while (t && t->type == tok_operator && t->content == ".")
         [ +  + ][ +  + ]
    3130                 :            :     {
    3131         [ +  - ]:     198528 :       concatenation* e = new concatenation;
    3132                 :     198528 :       e->left = op1;
    3133                 :     198528 :       e->op = t->content;
    3134                 :     198528 :       e->tok = t;
    3135                 :     198528 :       next ();
    3136                 :     198528 :       e->right = parse_additive ();
    3137                 :     198528 :       op1 = e;
    3138                 :     198528 :       t = peek ();
    3139                 :            :     }
    3140                 :            : 
    3141                 :   66827743 :   return op1;
    3142                 :            : }
    3143                 :            : 
    3144                 :            : 
    3145                 :            : expression*
    3146                 :   67026287 : parser::parse_additive ()
    3147                 :            : {
    3148                 :   67026287 :   expression* op1 = parse_multiplicative ();
    3149                 :            : 
    3150                 :   67026272 :   const token* t = peek ();
    3151 [ +  - ][ +  +  :  169607498 :   while (t && t->type == tok_operator
             +  +  +  + ]
                 [ +  + ]
    3152                 :  102420606 :       && (t->content == "+" || t->content == "-"))
    3153                 :            :     {
    3154         [ +  - ]:     160621 :       binary_expression* e = new binary_expression;
    3155                 :     160621 :       e->op = t->content;
    3156                 :     160621 :       e->left = op1;
    3157                 :     160621 :       e->tok = t;
    3158                 :     160621 :       next ();
    3159                 :     160621 :       e->right = parse_multiplicative ();
    3160                 :     160620 :       op1 = e;
    3161                 :     160620 :       t = peek ();
    3162                 :            :     }
    3163                 :            : 
    3164                 :   67026271 :   return op1;
    3165                 :            : }
    3166                 :            : 
    3167                 :            : 
    3168                 :            : expression*
    3169                 :   67186908 : parser::parse_multiplicative ()
    3170                 :            : {
    3171                 :   67186908 :   expression* op1 = parse_unary ();
    3172                 :            : 
    3173                 :   67186892 :   const token* t = peek ();
    3174 [ +  - ][ +  +  :  221232781 :   while (t && t->type == tok_operator
          +  +  +  +  +  
              + ][ +  + ]
    3175                 :  153944218 :       && (t->content == "*" || t->content == "/" || t->content == "%"))
    3176                 :            :     {
    3177         [ +  - ]:     101671 :       binary_expression* e = new binary_expression;
    3178                 :     101671 :       e->op = t->content;
    3179                 :     101671 :       e->left = op1;
    3180                 :     101671 :       e->tok = t;
    3181                 :     101671 :       next ();
    3182                 :     101671 :       e->right = parse_unary ();
    3183                 :     101671 :       op1 = e;
    3184                 :     101671 :       t = peek ();
    3185                 :            :     }
    3186                 :            : 
    3187                 :   67186892 :   return op1;
    3188                 :            : }
    3189                 :            : 
    3190                 :            : 
    3191                 :            : expression*
    3192                 :   67571349 : parser::parse_unary ()
    3193                 :            : {
    3194                 :   67571349 :   const token* t = peek ();
    3195 [ +  - ][ +  +  :   80982409 :   if (t && t->type == tok_operator
          +  +  +  +  +  
                +  +  + ]
                 [ +  + ]
    3196                 :    3477920 :       && (t->content == "+" ||
    3197                 :    3477895 :           t->content == "-" ||
    3198                 :    3255749 :           t->content == "!" ||
    3199                 :    3199496 :           t->content == "~" ||
    3200                 :            :           false))
    3201                 :            :     {
    3202         [ +  - ]:     282770 :       unary_expression* e = new unary_expression;
    3203                 :     282770 :       e->op = t->content;
    3204                 :     282770 :       e->tok = t;
    3205                 :     282770 :       next ();
    3206                 :     282770 :       e->operand = parse_unary ();
    3207                 :     282769 :       return e;
    3208                 :            :     }
    3209                 :            :   else
    3210                 :   67571348 :     return parse_crement ();
    3211                 :            : }
    3212                 :            : 
    3213                 :            : 
    3214                 :            : expression*
    3215                 :   67288579 : parser::parse_crement () // as in "increment" / "decrement"
    3216                 :            : {
    3217                 :            :   // NB: Ideally, we'd parse only a symbol as an operand to the
    3218                 :            :   // *crement operators, instead of a general expression value.  We'd
    3219                 :            :   // need more complex lookahead code to tell apart the postfix cases.
    3220                 :            :   // So we just punt, and leave it to pass-3 to signal errors on
    3221                 :            :   // cases like "4++".
    3222                 :            : 
    3223                 :   67288579 :   const token* t = peek ();
    3224 [ +  - ][ +  +  :   73678780 :   if (t && t->type == tok_operator
             +  +  +  + ]
                 [ +  + ]
    3225                 :    6390201 :       && (t->content == "++" || t->content == "--"))
    3226                 :            :     {
    3227         [ +  - ]:        119 :       pre_crement* e = new pre_crement;
    3228                 :        119 :       e->op = t->content;
    3229                 :        119 :       e->tok = t;
    3230                 :        119 :       next ();
    3231                 :        119 :       e->operand = parse_value ();
    3232                 :        119 :       return e;
    3233                 :            :     }
    3234                 :            : 
    3235                 :            :   // post-crement or non-crement
    3236                 :   67288460 :   expression *op1 = parse_value ();
    3237                 :            : 
    3238                 :   67288444 :   t = peek ();
    3239 [ +  - ][ +  +  :  169981879 :   if (t && t->type == tok_operator
             +  +  +  + ]
                 [ +  + ]
    3240                 :  102693435 :       && (t->content == "++" || t->content == "--"))
    3241                 :            :     {
    3242         [ +  - ]:      24389 :       post_crement* e = new post_crement;
    3243                 :      24389 :       e->op = t->content;
    3244                 :      24389 :       e->tok = t;
    3245                 :      24389 :       next ();
    3246                 :      24389 :       e->operand = op1;
    3247                 :      24389 :       return e;
    3248                 :            :     }
    3249                 :            :   else
    3250                 :   67288563 :     return op1;
    3251                 :            : }
    3252                 :            : 
    3253                 :            : 
    3254                 :            : expression*
    3255                 :   67288579 : parser::parse_value ()
    3256                 :            : {
    3257                 :   67288579 :   const token* t = peek ();
    3258         [ -  + ]:   67288579 :   if (! t)
    3259 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected value"));
    3260                 :            : 
    3261         [ +  + ]:   67288579 :   if (t->type == tok_embedded)
    3262                 :            :     {
    3263         [ -  + ]:     626882 :       if (! privileged)
    3264 [ #  # ][ #  # ]:          0 :         throw parse_error (_("embedded expression code in unprivileged script; need stap -g"), false);
    3265                 :            : 
    3266         [ +  - ]:     626882 :       embedded_expr *e = new embedded_expr;
    3267                 :     626882 :       e->tok = t;
    3268                 :     626882 :       e->code = t->content;
    3269                 :     626882 :       next ();
    3270                 :     626882 :       return e;
    3271                 :            :     }
    3272                 :            : 
    3273 [ +  + ][ +  + ]:   66661697 :   if (t->type == tok_operator && t->content == "(")
                 [ +  + ]
    3274                 :            :     {
    3275                 :    1606488 :       swallow ();
    3276                 :    1606488 :       expression* e = parse_expression ();
    3277                 :    1606488 :       t = next ();
    3278 [ +  - ][ -  + ]:    1606488 :       if (! (t->type == tok_operator && t->content == ")"))
                 [ -  + ]
    3279 [ #  # ][ #  # ]:          0 :         throw parse_error (_("expected ')'"));
    3280                 :    1606488 :       swallow ();
    3281                 :    1606488 :       return e;
    3282                 :            :     }
    3283 [ +  + ][ +  + ]:   65055209 :   else if (t->type == tok_operator && t->content == "&")
                 [ +  + ]
    3284                 :            :     {
    3285                 :     148667 :       next (); // Cannot swallow, passing token on...
    3286                 :     148667 :       return parse_target_symbol (t);
    3287                 :            :     }
    3288         [ +  + ]:   66346428 :   else if (t->type == tok_identifier
           [ +  +  +  + ]
                 [ +  + ]
    3289                 :    1439886 :            || (t->type == tok_operator && t->content[0] == '@'))
    3290                 :   50574468 :     return parse_symbol ();
    3291                 :            :   else
    3292                 :   67288570 :     return parse_literal ();
    3293                 :            : }
    3294                 :            : 
    3295                 :            : 
    3296                 :            : const token *
    3297                 :   50626767 : parser::parse_hist_op_or_bare_name (hist_op *&hop, string &name)
    3298                 :            : {
    3299                 :   50626767 :   hop = NULL;
    3300                 :   50626767 :   const token* t = expect_ident_or_atword (name);
    3301 [ +  + ][ +  + ]:   50626766 :   if (name == "@hist_linear" || name == "@hist_log")
                 [ +  + ]
    3302                 :            :     {
    3303 [ +  - ][ +  - ]:        135 :       hop = new hist_op;
    3304 [ +  - ][ +  + ]:        135 :       if (name == "@hist_linear")
    3305                 :         56 :         hop->htype = hist_linear;
    3306 [ +  - ][ +  - ]:         79 :       else if (name == "@hist_log")
    3307                 :         79 :         hop->htype = hist_log;
    3308                 :        135 :       hop->tok = t;
    3309 [ +  - ][ +  - ]:        135 :       expect_op("(");
                 [ +  - ]
    3310         [ +  - ]:        135 :       hop->stat = parse_expression ();
    3311                 :            :       int64_t tnum;
    3312         [ +  + ]:        135 :       if (hop->htype == hist_linear)
    3313                 :            :         {
    3314         [ +  + ]:        224 :           for (size_t i = 0; i < 3; ++i)
    3315                 :            :             {
    3316 [ +  - ][ +  - ]:        168 :               expect_op (",");
                 [ +  - ]
    3317         [ +  - ]:        168 :               expect_number (tnum);
    3318         [ +  - ]:        168 :               hop->params.push_back (tnum);
    3319                 :            :             }
    3320                 :            :         }
    3321 [ +  - ][ +  - ]:        135 :       expect_op(")");
                 [ +  - ]
    3322                 :            :     }
    3323                 :   50626766 :   return t;
    3324                 :            : }
    3325                 :            : 
    3326                 :            : 
    3327                 :            : indexable*
    3328                 :      52198 : parser::parse_indexable ()
    3329                 :            : {
    3330                 :      52198 :   hist_op *hop = NULL;
    3331         [ +  - ]:      52198 :   string name;
    3332         [ +  + ]:      52198 :   const token *tok = parse_hist_op_or_bare_name(hop, name);
    3333         [ +  + ]:      52197 :   if (hop)
    3334                 :         10 :     return hop;
    3335                 :            :   else
    3336                 :            :     {
    3337 [ +  - ][ +  - ]:      52187 :       symbol* sym = new symbol;
    3338         [ +  - ]:      52187 :       sym->name = name;
    3339                 :      52187 :       sym->tok = tok;
    3340                 :      52187 :       return sym;
    3341         [ +  - ]:      52198 :     }
    3342                 :            : }
    3343                 :            : 
    3344                 :            : 
    3345                 :            : // var, indexable[index], func(parms), printf("...", ...), $var,r
    3346                 :            : // @cast, @defined, @entry, @var, $var->member, @stat_op(stat)
    3347                 :   50574468 : expression* parser::parse_symbol ()
    3348                 :            : {
    3349                 :   50574468 :   hist_op *hop = NULL;
    3350                 :   50574468 :   symbol *sym = NULL;
    3351         [ +  - ]:   50574468 :   string name;
    3352         [ +  - ]:   50574468 :   const token *t = parse_hist_op_or_bare_name(hop, name);
    3353                 :            : 
    3354         [ +  + ]:   50574468 :   if (!hop)
    3355                 :            :     {
    3356                 :            :       // If we didn't get a hist_op, then we did get an identifier. We can
    3357                 :            :       // now scrutinize this identifier for the various magic forms of identifier
    3358                 :            :       // (printf, @stat_op, and $var...)
    3359                 :            : 
    3360 [ +  - ][ +  + ]:  199964446 :       if (name == "@cast"
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
    3361         [ +  - ]:   49796668 :           || name == "@var"
    3362 [ +  - ][ +  - ]:   99593334 :           || (name.size() > 0 && name[0] == '$'))
    3363         [ +  - ]:   10299001 :         return parse_target_symbol (t);
    3364                 :            : 
    3365                 :            :       // NB: PR11343: @defined() is not incompatible with earlier versions
    3366                 :            :       // of stap, so no need to check session.compatible for 1.2
    3367 [ +  - ][ +  + ]:   40275443 :       if (name == "@defined")
    3368         [ +  - ]:     629151 :         return parse_defined_op (t);
    3369                 :            : 
    3370 [ +  - ][ +  + ]:   39646292 :       if (name == "@entry")
    3371         [ +  - ]:      32354 :         return parse_entry_op (t);
    3372                 :            : 
    3373 [ +  - ][ +  + ]:   39613938 :       if (name == "@perf")
    3374         [ +  + ]:          9 :         return parse_perf_op (t);
    3375                 :            : 
    3376 [ +  - ][ +  - ]:   39613929 :       if (name.size() > 0 && name[0] == '@')
         [ +  - ][ +  + ]
                 [ +  + ]
    3377                 :            :         {
    3378 [ +  - ][ +  - ]:        567 :           stat_op *sop = new stat_op;
    3379 [ +  - ][ +  + ]:        567 :           if (name == "@avg")
    3380                 :         80 :             sop->ctype = sc_average;
    3381 [ +  - ][ +  + ]:        487 :           else if (name == "@count")
    3382                 :        250 :             sop->ctype = sc_count;
    3383 [ +  - ][ +  + ]:        237 :           else if (name == "@sum")
    3384                 :        100 :             sop->ctype = sc_sum;
    3385 [ +  - ][ +  + ]:        137 :           else if (name == "@min")
    3386                 :         65 :             sop->ctype = sc_min;
    3387 [ +  - ][ +  + ]:         72 :           else if (name == "@max")
    3388                 :         71 :             sop->ctype = sc_max;
    3389                 :            :           else
    3390 [ +  - ][ +  - ]:          1 :             throw parse_error(_("unknown operator ") + name);
    3391 [ +  - ][ +  - ]:        566 :           expect_op("(");
                 [ +  - ]
    3392                 :        566 :           sop->tok = t;
    3393         [ +  - ]:        566 :           sop->stat = parse_expression ();
    3394 [ +  - ][ +  - ]:        566 :           expect_op(")");
                 [ +  - ]
    3395                 :        566 :           return sop;
    3396                 :            :         }
    3397                 :            : 
    3398 [ +  - ][ +  + ]:   39613362 :       else if (print_format *fmt = print_format::create(t))
    3399                 :            :         {
    3400 [ +  - ][ +  + ]:    2166387 :           expect_op("(");
                 [ +  - ]
    3401 [ +  - ][ +  + ]:    8775452 :           if ((name == "print" || name == "println" ||
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
    3402 [ +  - ][ +  - ]:    4196038 :                name == "sprint" || name == "sprintln") &&
    3403 [ +  - ][ +  - ]:    2413028 :               (peek_op("@hist_linear") || peek_op("@hist_log")))
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
           [ #  #  #  #  
             #  #  #  # ]
    3404                 :            :             {
    3405                 :            :               // We have a special case where we recognize
    3406                 :            :               // print(@hist_foo(bar)) as a magic print-the-histogram
    3407                 :            :               // construct. This is sort of gross but it avoids
    3408                 :            :               // promoting histogram references to typeful
    3409                 :            :               // expressions.
    3410                 :            : 
    3411                 :        101 :               hop = NULL;
    3412         [ +  - ]:        101 :               t = parse_hist_op_or_bare_name(hop, name);
    3413         [ -  + ]:        101 :               assert(hop);
    3414                 :            : 
    3415                 :            :               // It is, sadly, possible that even while parsing a
    3416                 :            :               // hist_op, we *mis-guessed* and the user wishes to
    3417                 :            :               // print(@hist_op(foo)[bucket]), a scalar. In that case
    3418                 :            :               // we must parse the arrayindex and print an expression.
    3419                 :            :               //
    3420                 :            :               // XXX: This still fails if the arrayindex is part of a
    3421                 :            :               // larger expression.  To really handle everything, we'd
    3422                 :            :               // need to push back all the hist tokens start over.
    3423                 :            : 
    3424 [ +  - ][ +  - ]:        101 :               if (!peek_op ("["))
         [ +  - ][ +  + ]
    3425                 :        100 :                 fmt->hist = hop;
    3426                 :            :               else
    3427                 :            :                 {
    3428                 :            :                   // This is simplified version of the
    3429                 :            :                   // multi-array-index parser below, because we can
    3430                 :            :                   // only ever have one index on a histogram anyways.
    3431 [ +  - ][ +  - ]:          1 :                   expect_op("[");
                 [ +  - ]
    3432 [ +  - ][ +  - ]:          1 :                   struct arrayindex* ai = new arrayindex;
    3433                 :          1 :                   ai->tok = t;
    3434                 :          1 :                   ai->base = hop;
    3435 [ +  - ][ +  - ]:          1 :                   ai->indexes.push_back (parse_expression ());
    3436 [ +  - ][ +  - ]:          1 :                   expect_op("]");
                 [ +  - ]
    3437         [ +  - ]:          1 :                   fmt->args.push_back(ai);
    3438                 :            : 
    3439                 :            :                   // Consume any subsequent arguments.
    3440 [ +  - ][ +  - ]:          2 :                   while (!peek_op (")"))
         [ +  - ][ +  + ]
    3441                 :            :                     {
    3442 [ +  - ][ +  - ]:          1 :                       expect_op(",");
                 [ +  - ]
    3443         [ +  - ]:          1 :                       expression *e = parse_expression ();
    3444         [ +  - ]:          1 :                       fmt->args.push_back(e);
    3445                 :            :                     }
    3446                 :            :                 }
    3447                 :            :             }
    3448                 :            :           else
    3449                 :            :             {
    3450                 :    2166285 :               int min_args = 0;
    3451         [ +  + ]:    2166285 :               if (fmt->print_with_format)
    3452                 :            :                 {
    3453                 :            :                   // Consume and convert a format string. Agreement between the
    3454                 :            :                   // format string and the arguments is postponed to the
    3455                 :            :                   // typechecking phase.
    3456         [ +  - ]:    2042985 :                   string tmp;
    3457         [ +  - ]:    2042985 :                   expect_unknown (tok_string, tmp);
    3458         [ +  - ]:    2042985 :                   fmt->raw_components = tmp;
    3459 [ +  - ][ +  - ]:    2042985 :                   fmt->components = print_format::string_to_components (tmp);
         [ +  - ][ +  - ]
    3460                 :            :                 }
    3461         [ +  + ]:     123300 :               else if (fmt->print_with_delim)
    3462                 :            :                 {
    3463                 :            :                   // Consume a delimiter to separate arguments.
    3464         [ +  - ]:         32 :                   fmt->delimiter.clear();
    3465                 :         32 :                   fmt->delimiter.type = print_format::conv_literal;
    3466         [ +  + ]:         32 :                   expect_unknown (tok_string, fmt->delimiter.literal_string);
    3467                 :         30 :                   min_args = 2;
    3468                 :            :                 }
    3469                 :            :               else
    3470                 :            :                 {
    3471                 :            :                   // If we are not printing with a format string, we must have
    3472                 :            :                   // at least one argument (of any type).
    3473         [ +  - ]:     123268 :                   expression *e = parse_expression ();
    3474         [ +  - ]:     123268 :                   fmt->args.push_back(e);
    3475                 :            :                 }
    3476                 :            : 
    3477                 :            :               // Consume any subsequent arguments.
    3478 [ +  + ][ +  - ]:    7383889 :               while (min_args || !peek_op (")"))
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  +  
             #  #  #  # ]
    3479                 :            :                 {
    3480 [ +  - ][ +  + ]:    5217610 :                   expect_op(",");
                 [ +  - ]
    3481         [ +  + ]:    5217607 :                   expression *e = parse_expression ();
    3482         [ +  - ]:    5217606 :                   fmt->args.push_back(e);
    3483         [ +  + ]:    5217606 :                   if (min_args)
    3484                 :    5217606 :                     --min_args;
    3485                 :            :                 }
    3486                 :            :             }
    3487 [ +  - ][ +  - ]:    2166381 :           expect_op(")");
                 [ +  - ]
    3488                 :    2166381 :           return fmt;
    3489                 :            :         }
    3490                 :            : 
    3491 [ +  - ][ +  - ]:   37446975 :       else if (peek_op ("(")) // function call
         [ +  - ][ +  + ]
    3492                 :            :         {
    3493         [ +  - ]:    9779318 :           swallow ();
    3494 [ +  - ][ +  - ]:    9779318 :           struct functioncall* f = new functioncall;
    3495                 :    9779318 :           f->tok = t;
    3496         [ +  - ]:    9779318 :           f->function = name;
    3497                 :            :           // Allow empty actual parameter list
    3498 [ +  - ][ +  - ]:    9779318 :           if (peek_op (")"))
         [ +  - ][ +  + ]
    3499                 :            :             {
    3500         [ +  - ]:     864052 :               swallow ();
    3501                 :     864052 :               return f;
    3502                 :            :             }
    3503                 :    1957294 :           while (1)
    3504                 :            :             {
    3505 [ +  - ][ +  - ]:   10872560 :               f->args.push_back (parse_expression ());
    3506 [ +  - ][ +  - ]:   10872560 :               if (peek_op (")"))
         [ +  - ][ +  + ]
    3507                 :            :                 {
    3508         [ +  - ]:    8915266 :                   swallow ();
    3509                 :    8915266 :                   break;
    3510                 :            :                 }
    3511 [ +  - ][ +  - ]:    1957294 :               else if (peek_op (","))
         [ +  - ][ +  - ]
    3512                 :            :                 {
    3513         [ +  - ]:    1957294 :                   swallow ();
    3514                 :    1957294 :                   continue;
    3515                 :            :                 }
    3516                 :            :               else
    3517 [ #  # ][ #  # ]:          0 :                 throw parse_error (_("expected ',' or ')'"));
    3518                 :            :             }
    3519                 :    8915266 :           return f;
    3520                 :            :         }
    3521                 :            : 
    3522                 :            :       else
    3523                 :            :         {
    3524 [ +  - ][ +  - ]:   27667657 :           sym = new symbol;
    3525         [ +  - ]:   27667657 :           sym->name = name;
    3526                 :   27667657 :           sym->tok = t;
    3527                 :            :         }
    3528                 :            :     }
    3529                 :            : 
    3530                 :            :   // By now, either we had a hist_op in the first place, or else
    3531                 :            :   // we had a plain word and it was converted to a symbol.
    3532                 :            : 
    3533         [ -  + ]:   27667681 :   assert (!hop != !sym); // logical XOR
    3534                 :            : 
    3535                 :            :   // All that remains is to check for array indexing
    3536                 :            : 
    3537 [ +  - ][ +  - ]:   27667681 :   if (peek_op ("[")) // array
         [ +  - ][ +  + ]
    3538                 :            :     {
    3539         [ +  - ]:    1046313 :       swallow ();
    3540 [ +  - ][ +  - ]:    1046313 :       struct arrayindex* ai = new arrayindex;
    3541                 :    1046313 :       ai->tok = t;
    3542                 :            : 
    3543         [ +  + ]:    1046313 :       if (hop)
    3544                 :         24 :         ai->base = hop;
    3545                 :            :       else
    3546                 :    1046289 :         ai->base = sym;
    3547                 :            : 
    3548                 :      15828 :       while (1)
    3549                 :            :         {
    3550 [ +  - ][ +  - ]:    1062141 :           ai->indexes.push_back (parse_expression ());
    3551 [ +  - ][ +  - ]:    1062141 :           if (peek_op ("]"))
         [ +  - ][ +  + ]
    3552                 :            :             {
    3553         [ +  - ]:    1046313 :               swallow ();
    3554                 :    1046313 :               break;
    3555                 :            :             }
    3556 [ +  - ][ +  - ]:      15828 :           else if (peek_op (","))
         [ +  - ][ +  - ]
    3557                 :            :             {
    3558         [ +  - ]:      15828 :               swallow ();
    3559                 :      15828 :               continue;
    3560                 :            :             }
    3561                 :            :           else
    3562 [ #  # ][ #  # ]:          0 :             throw parse_error (_("expected ',' or ']'"));
    3563                 :            :         }
    3564                 :    1046313 :       return ai;
    3565                 :            :     }
    3566                 :            : 
    3567                 :            :   // If we got to here, we *should* have a symbol; if we have
    3568                 :            :   // a hist_op on its own, it doesn't count as an expression,
    3569                 :            :   // so we throw a parse error.
    3570                 :            : 
    3571         [ -  + ]:   26621368 :   if (hop)
    3572 [ #  # ][ #  # ]:          0 :     throw parse_error(_("base histogram operator where expression expected"), t);
    3573                 :            : 
    3574         [ +  - ]:   50574468 :   return sym;
    3575                 :            : }
    3576                 :            : 
    3577                 :            : // Parse a @cast or $var.  Given head token has already been consumed.
    3578                 :   11076819 : target_symbol* parser::parse_target_symbol (const token* t)
    3579                 :            : {
    3580                 :   11076819 :   bool addressof = false;
    3581 [ +  + ][ +  + ]:   11076819 :   if (t->type == tok_operator && t->content == "&")
                 [ +  + ]
    3582                 :            :     {
    3583                 :     159443 :       addressof = true;
    3584         [ +  - ]:     159443 :       delete t;
    3585                 :     159443 :       t = next ();
    3586                 :            :     }
    3587                 :            : 
    3588 [ +  + ][ +  + ]:   11076819 :   if (t->type == tok_operator && t->content == "@cast")
                 [ +  + ]
    3589                 :            :     {
    3590         [ +  - ]:     993217 :       cast_op *cop = new cast_op;
    3591                 :     993217 :       cop->tok = t;
    3592                 :     993217 :       cop->name = t->content;
    3593 [ +  - ][ +  - ]:     993217 :       expect_op("(");
                 [ +  - ]
    3594                 :     993217 :       cop->operand = parse_expression ();
    3595 [ +  - ][ +  - ]:     993217 :       expect_op(",");
                 [ +  - ]
    3596                 :     993217 :       expect_unknown(tok_string, cop->type_name);
    3597 [ +  - ][ +  - ]:     993217 :       if (peek_op (","))
         [ +  - ][ +  + ]
    3598                 :            :         {
    3599                 :     458835 :           swallow ();
    3600                 :     458835 :           expect_unknown(tok_string, cop->module);
    3601                 :            :         }
    3602 [ +  - ][ +  - ]:     993217 :       expect_op(")");
                 [ +  - ]
    3603                 :     993217 :       parse_target_symbol_components(cop);
    3604                 :     993217 :       cop->addressof = addressof;
    3605                 :     993217 :       return cop;
    3606                 :            :     }
    3607                 :            : 
    3608 [ +  + ][ +  - ]:   10083602 :   if (t->type == tok_identifier && t->content[0]=='$')
                 [ +  + ]
    3609                 :            :     {
    3610                 :            :       // target_symbol time
    3611         [ +  - ]:   10083601 :       target_symbol *tsym = new target_symbol;
    3612                 :   10083601 :       tsym->tok = t;
    3613                 :   10083601 :       tsym->name = t->content;
    3614                 :   10083601 :       tsym->target_name = "";
    3615                 :   10083601 :       tsym->cu_name = "";
    3616                 :   10083601 :       parse_target_symbol_components(tsym);
    3617                 :   10083601 :       tsym->addressof = addressof;
    3618                 :   10083601 :       return tsym;
    3619                 :            :     }
    3620                 :            : 
    3621 [ +  - ][ +  - ]:          1 :   if (t->type == tok_operator && t->content == "@var")
                 [ +  - ]
    3622                 :            :     {
    3623         [ +  - ]:          1 :       target_symbol *tsym = new target_symbol;
    3624                 :          1 :       tsym->tok = t;
    3625                 :          1 :       tsym->name = t->content;
    3626 [ +  - ][ +  - ]:          1 :       expect_op("(");
                 [ +  - ]
    3627                 :          1 :       expect_unknown(tok_string, tsym->target_name);
    3628                 :          1 :       size_t found_at = tsym->target_name.find("@");
    3629         [ +  - ]:          1 :       if (found_at != string::npos)
    3630         [ +  - ]:          1 :         tsym->cu_name = tsym->target_name.substr(found_at + 1);
    3631                 :            :       else
    3632                 :          0 :         tsym->cu_name = "";
    3633 [ +  - ][ +  - ]:          1 :       expect_op(")");
                 [ +  - ]
    3634                 :          1 :       parse_target_symbol_components(tsym);
    3635                 :          1 :       tsym->addressof = addressof;
    3636                 :          1 :       return tsym;
    3637                 :            :     }
    3638                 :            : 
    3639 [ #  # ][ #  # ]:   11076819 :   throw parse_error (_("expected @cast, @var or $var"));
    3640                 :            : }
    3641                 :            : 
    3642                 :            : 
    3643                 :            : // Parse a @defined().  Given head token has already been consumed.
    3644                 :     629151 : expression* parser::parse_defined_op (const token* t)
    3645                 :            : {
    3646         [ +  - ]:     629151 :   defined_op* dop = new defined_op;
    3647                 :     629151 :   dop->tok = t;
    3648 [ +  - ][ +  - ]:     629151 :   expect_op("(");
                 [ +  - ]
    3649                 :            :   // no need for parse_hist_op... etc., as @defined takes only target_symbols as its operand.
    3650                 :     629151 :   const token* tt = next ();
    3651                 :     629151 :   dop->operand = parse_target_symbol (tt);
    3652 [ +  - ][ +  - ]:     629151 :   expect_op(")");
                 [ +  - ]
    3653                 :     629151 :   return dop;
    3654                 :            : }
    3655                 :            : 
    3656                 :            : 
    3657                 :            : // Parse a @entry().  Given head token has already been consumed.
    3658                 :      32354 : expression* parser::parse_entry_op (const token* t)
    3659                 :            : {
    3660         [ +  - ]:      32354 :   entry_op* eop = new entry_op;
    3661                 :      32354 :   eop->tok = t;
    3662 [ +  - ][ +  - ]:      32354 :   expect_op("(");
                 [ +  - ]
    3663                 :      32354 :   eop->operand = parse_expression ();
    3664 [ +  - ][ +  - ]:      32354 :   expect_op(")");
                 [ +  - ]
    3665                 :      32354 :   return eop;
    3666                 :            : }
    3667                 :            : 
    3668                 :            : 
    3669                 :            : // Parse a @perf().  Given head token has already been consumed.
    3670                 :          9 : expression* parser::parse_perf_op (const token* t)
    3671                 :            : {
    3672         [ +  - ]:          9 :   perf_op* pop = new perf_op;
    3673                 :            : 
    3674         [ -  + ]:          9 :   if (strverscmp(session.compatible.c_str(), "2.1") < 0)
    3675 [ #  # ][ #  # ]:          0 :     throw parse_error (_("expected @cast, @var or $var"));
    3676                 :            : 
    3677                 :          9 :   pop->tok = t;
    3678 [ +  - ][ +  - ]:          9 :   expect_op("(");
                 [ +  - ]
    3679                 :          9 :   pop->operand = parse_literal_string ();
    3680         [ +  + ]:          8 :   if (pop->operand->value == "")
    3681 [ +  - ][ +  - ]:          1 :     throw parse_error (_("expected non-empty string"));
    3682 [ +  - ][ +  - ]:          7 :   expect_op(")");
                 [ +  - ]
    3683                 :          7 :   return pop;
    3684                 :            : }
    3685                 :            : 
    3686                 :            : 
    3687                 :            : 
    3688                 :            : void
    3689                 :   11076819 : parser::parse_target_symbol_components (target_symbol* e)
    3690                 :            : {
    3691                 :   11076819 :   bool pprint = false;
    3692                 :            : 
    3693                 :            :   // check for pretty-print in the form $foo$
    3694                 :   11076819 :   string &base = e->name;
    3695                 :   11076819 :   size_t pprint_pos = base.find_last_not_of('$');
    3696 [ +  - ][ +  + ]:   11076819 :   if (0 < pprint_pos && pprint_pos < base.length() - 1)
                 [ +  + ]
    3697                 :            :     {
    3698         [ +  - ]:         29 :       string pprint_val = base.substr(pprint_pos + 1);
    3699         [ +  - ]:         29 :       base.erase(pprint_pos + 1);
    3700 [ +  - ][ +  - ]:         29 :       e->components.push_back (target_symbol::component(e->tok, pprint_val, true));
                 [ +  - ]
    3701         [ +  - ]:         29 :       pprint = true;
    3702                 :            :     }
    3703                 :            : 
    3704         [ +  + ]:   14819020 :   while (!pprint)
    3705                 :            :     {
    3706 [ +  - ][ +  - ]:   14818915 :       if (peek_op ("->"))
         [ +  - ][ +  + ]
    3707                 :            :         {
    3708         [ +  - ]:    3701179 :           const token* t = next();
    3709         [ +  - ]:    3701179 :           string member;
    3710         [ +  - ]:    3701179 :           expect_ident_or_keyword (member);
    3711                 :            : 
    3712                 :            :           // check for pretty-print in the form $foo->$ or $foo->bar$
    3713         [ +  - ]:    3701179 :           pprint_pos = member.find_last_not_of('$');
    3714         [ +  - ]:    3701179 :           string pprint_val;
    3715 [ +  + ][ +  - ]:    3701179 :           if (pprint_pos == string::npos || pprint_pos < member.length() - 1)
         [ +  + ][ +  + ]
    3716                 :            :             {
    3717 [ +  - ][ +  - ]:         76 :               pprint_val = member.substr(pprint_pos + 1);
                 [ +  - ]
    3718         [ +  - ]:         76 :               member.erase(pprint_pos + 1);
    3719                 :         76 :               pprint = true;
    3720                 :            :             }
    3721                 :            : 
    3722 [ +  - ][ +  + ]:    3701179 :           if (!member.empty())
    3723 [ +  - ][ +  - ]:    3701135 :             e->components.push_back (target_symbol::component(t, member));
                 [ +  - ]
    3724         [ +  + ]:    3701179 :           if (pprint)
    3725 [ +  - ][ +  - ]:    3701179 :             e->components.push_back (target_symbol::component(t, pprint_val, true));
         [ +  - ][ +  - ]
                 [ +  - ]
    3726                 :            :         }
    3727 [ +  - ][ +  - ]:   11117736 :       else if (peek_op ("["))
         [ +  - ][ +  + ]
    3728                 :            :         {
    3729                 :      41022 :           const token* t = next();
    3730                 :      41022 :           expression* index = parse_expression();
    3731         [ -  + ]:      41022 :           literal_number* ln = dynamic_cast<literal_number*>(index);
    3732         [ +  + ]:      41022 :           if (ln)
    3733         [ +  - ]:      34531 :             e->components.push_back (target_symbol::component(t, ln->value));
    3734                 :            :           else
    3735         [ +  - ]:       6491 :             e->components.push_back (target_symbol::component(t, index));
    3736 [ +  - ][ +  - ]:      41022 :           expect_op ("]");
                 [ +  - ]
    3737                 :            :         }
    3738                 :            :       else
    3739                 :   11076714 :         break;
    3740                 :            :     }
    3741                 :            : 
    3742         [ +  + ]:   11076819 :   if (!pprint)
    3743                 :            :     {
    3744                 :            :       // check for pretty-print in the form $foo $
    3745                 :            :       // i.e. as a separate token, esp. for $foo[i]$ and @cast(...)$
    3746                 :   11076714 :       const token* t = peek();
    3747   [ +  +  +  + ]:   14411610 :       if (t->type == tok_identifier &&
                 [ +  + ]
    3748                 :    3334896 :           t->content.find_first_not_of('$') == string::npos)
    3749                 :            :         {
    3750                 :         43 :           t = next();
    3751         [ +  - ]:         43 :           e->components.push_back (target_symbol::component(t, t->content, true));
    3752                 :         43 :           pprint = true;
    3753                 :            :         }
    3754                 :            :     }
    3755                 :            : 
    3756 [ +  + ][ +  - ]:   11076819 :   if (pprint && (peek_op ("->") || peek_op("[")))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ -  +  
          #  #  #  #  #  
                #  #  # ]
    3757 [ #  # ][ #  # ]:          0 :     throw parse_error(_("-> and [ are not accepted for a pretty-printing variable"));
    3758 [ +  - ][ +  - ]:   11084061 : }
    3759                 :            : 
    3760                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9