1*6881a400Schristos /* Rust expression parsing for GDB, the GNU debugger. 2*6881a400Schristos 3*6881a400Schristos Copyright (C) 2016-2023 Free Software Foundation, Inc. 4*6881a400Schristos 5*6881a400Schristos This file is part of GDB. 6*6881a400Schristos 7*6881a400Schristos This program is free software; you can redistribute it and/or modify 8*6881a400Schristos it under the terms of the GNU General Public License as published by 9*6881a400Schristos the Free Software Foundation; either version 3 of the License, or 10*6881a400Schristos (at your option) any later version. 11*6881a400Schristos 12*6881a400Schristos This program is distributed in the hope that it will be useful, 13*6881a400Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 14*6881a400Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*6881a400Schristos GNU General Public License for more details. 16*6881a400Schristos 17*6881a400Schristos You should have received a copy of the GNU General Public License 18*6881a400Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19*6881a400Schristos 20*6881a400Schristos #include "defs.h" 21*6881a400Schristos 22*6881a400Schristos #include "block.h" 23*6881a400Schristos #include "charset.h" 24*6881a400Schristos #include "cp-support.h" 25*6881a400Schristos #include "gdbsupport/gdb_obstack.h" 26*6881a400Schristos #include "gdbsupport/gdb_regex.h" 27*6881a400Schristos #include "rust-lang.h" 28*6881a400Schristos #include "parser-defs.h" 29*6881a400Schristos #include "gdbsupport/selftest.h" 30*6881a400Schristos #include "value.h" 31*6881a400Schristos #include "gdbarch.h" 32*6881a400Schristos #include "rust-exp.h" 33*6881a400Schristos 34*6881a400Schristos using namespace expr; 35*6881a400Schristos 36*6881a400Schristos /* A regular expression for matching Rust numbers. This is split up 37*6881a400Schristos since it is very long and this gives us a way to comment the 38*6881a400Schristos sections. */ 39*6881a400Schristos 40*6881a400Schristos static const char number_regex_text[] = 41*6881a400Schristos /* subexpression 1: allows use of alternation, otherwise uninteresting */ 42*6881a400Schristos "^(" 43*6881a400Schristos /* First comes floating point. */ 44*6881a400Schristos /* Recognize number after the decimal point, with optional 45*6881a400Schristos exponent and optional type suffix. 46*6881a400Schristos subexpression 2: allows "?", otherwise uninteresting 47*6881a400Schristos subexpression 3: if present, type suffix 48*6881a400Schristos */ 49*6881a400Schristos "[0-9][0-9_]*\\.[0-9][0-9_]*([eE][-+]?[0-9][0-9_]*)?(f32|f64)?" 50*6881a400Schristos #define FLOAT_TYPE1 3 51*6881a400Schristos "|" 52*6881a400Schristos /* Recognize exponent without decimal point, with optional type 53*6881a400Schristos suffix. 54*6881a400Schristos subexpression 4: if present, type suffix 55*6881a400Schristos */ 56*6881a400Schristos #define FLOAT_TYPE2 4 57*6881a400Schristos "[0-9][0-9_]*[eE][-+]?[0-9][0-9_]*(f32|f64)?" 58*6881a400Schristos "|" 59*6881a400Schristos /* "23." is a valid floating point number, but "23.e5" and 60*6881a400Schristos "23.f32" are not. So, handle the trailing-. case 61*6881a400Schristos separately. */ 62*6881a400Schristos "[0-9][0-9_]*\\." 63*6881a400Schristos "|" 64*6881a400Schristos /* Finally come integers. 65*6881a400Schristos subexpression 5: text of integer 66*6881a400Schristos subexpression 6: if present, type suffix 67*6881a400Schristos subexpression 7: allows use of alternation, otherwise uninteresting 68*6881a400Schristos */ 69*6881a400Schristos #define INT_TEXT 5 70*6881a400Schristos #define INT_TYPE 6 71*6881a400Schristos "(0x[a-fA-F0-9_]+|0o[0-7_]+|0b[01_]+|[0-9][0-9_]*)" 72*6881a400Schristos "([iu](size|8|16|32|64))?" 73*6881a400Schristos ")"; 74*6881a400Schristos /* The number of subexpressions to allocate space for, including the 75*6881a400Schristos "0th" whole match subexpression. */ 76*6881a400Schristos #define NUM_SUBEXPRESSIONS 8 77*6881a400Schristos 78*6881a400Schristos /* The compiled number-matching regex. */ 79*6881a400Schristos 80*6881a400Schristos static regex_t number_regex; 81*6881a400Schristos 82*6881a400Schristos /* The kinds of tokens. Note that single-character tokens are 83*6881a400Schristos represented by themselves, so for instance '[' is a token. */ 84*6881a400Schristos enum token_type : int 85*6881a400Schristos { 86*6881a400Schristos /* Make sure to start after any ASCII character. */ 87*6881a400Schristos GDBVAR = 256, 88*6881a400Schristos IDENT, 89*6881a400Schristos COMPLETE, 90*6881a400Schristos INTEGER, 91*6881a400Schristos DECIMAL_INTEGER, 92*6881a400Schristos STRING, 93*6881a400Schristos BYTESTRING, 94*6881a400Schristos FLOAT, 95*6881a400Schristos COMPOUND_ASSIGN, 96*6881a400Schristos 97*6881a400Schristos /* Keyword tokens. */ 98*6881a400Schristos KW_AS, 99*6881a400Schristos KW_IF, 100*6881a400Schristos KW_TRUE, 101*6881a400Schristos KW_FALSE, 102*6881a400Schristos KW_SUPER, 103*6881a400Schristos KW_SELF, 104*6881a400Schristos KW_MUT, 105*6881a400Schristos KW_EXTERN, 106*6881a400Schristos KW_CONST, 107*6881a400Schristos KW_FN, 108*6881a400Schristos KW_SIZEOF, 109*6881a400Schristos 110*6881a400Schristos /* Operator tokens. */ 111*6881a400Schristos DOTDOT, 112*6881a400Schristos DOTDOTEQ, 113*6881a400Schristos OROR, 114*6881a400Schristos ANDAND, 115*6881a400Schristos EQEQ, 116*6881a400Schristos NOTEQ, 117*6881a400Schristos LTEQ, 118*6881a400Schristos GTEQ, 119*6881a400Schristos LSH, 120*6881a400Schristos RSH, 121*6881a400Schristos COLONCOLON, 122*6881a400Schristos ARROW, 123*6881a400Schristos }; 124*6881a400Schristos 125*6881a400Schristos /* A typed integer constant. */ 126*6881a400Schristos 127*6881a400Schristos struct typed_val_int 128*6881a400Schristos { 129*6881a400Schristos ULONGEST val; 130*6881a400Schristos struct type *type; 131*6881a400Schristos }; 132*6881a400Schristos 133*6881a400Schristos /* A typed floating point constant. */ 134*6881a400Schristos 135*6881a400Schristos struct typed_val_float 136*6881a400Schristos { 137*6881a400Schristos float_data val; 138*6881a400Schristos struct type *type; 139*6881a400Schristos }; 140*6881a400Schristos 141*6881a400Schristos /* A struct of this type is used to describe a token. */ 142*6881a400Schristos 143*6881a400Schristos struct token_info 144*6881a400Schristos { 145*6881a400Schristos const char *name; 146*6881a400Schristos int value; 147*6881a400Schristos enum exp_opcode opcode; 148*6881a400Schristos }; 149*6881a400Schristos 150*6881a400Schristos /* Identifier tokens. */ 151*6881a400Schristos 152*6881a400Schristos static const struct token_info identifier_tokens[] = 153*6881a400Schristos { 154*6881a400Schristos { "as", KW_AS, OP_NULL }, 155*6881a400Schristos { "false", KW_FALSE, OP_NULL }, 156*6881a400Schristos { "if", 0, OP_NULL }, 157*6881a400Schristos { "mut", KW_MUT, OP_NULL }, 158*6881a400Schristos { "const", KW_CONST, OP_NULL }, 159*6881a400Schristos { "self", KW_SELF, OP_NULL }, 160*6881a400Schristos { "super", KW_SUPER, OP_NULL }, 161*6881a400Schristos { "true", KW_TRUE, OP_NULL }, 162*6881a400Schristos { "extern", KW_EXTERN, OP_NULL }, 163*6881a400Schristos { "fn", KW_FN, OP_NULL }, 164*6881a400Schristos { "sizeof", KW_SIZEOF, OP_NULL }, 165*6881a400Schristos }; 166*6881a400Schristos 167*6881a400Schristos /* Operator tokens, sorted longest first. */ 168*6881a400Schristos 169*6881a400Schristos static const struct token_info operator_tokens[] = 170*6881a400Schristos { 171*6881a400Schristos { ">>=", COMPOUND_ASSIGN, BINOP_RSH }, 172*6881a400Schristos { "<<=", COMPOUND_ASSIGN, BINOP_LSH }, 173*6881a400Schristos 174*6881a400Schristos { "<<", LSH, OP_NULL }, 175*6881a400Schristos { ">>", RSH, OP_NULL }, 176*6881a400Schristos { "&&", ANDAND, OP_NULL }, 177*6881a400Schristos { "||", OROR, OP_NULL }, 178*6881a400Schristos { "==", EQEQ, OP_NULL }, 179*6881a400Schristos { "!=", NOTEQ, OP_NULL }, 180*6881a400Schristos { "<=", LTEQ, OP_NULL }, 181*6881a400Schristos { ">=", GTEQ, OP_NULL }, 182*6881a400Schristos { "+=", COMPOUND_ASSIGN, BINOP_ADD }, 183*6881a400Schristos { "-=", COMPOUND_ASSIGN, BINOP_SUB }, 184*6881a400Schristos { "*=", COMPOUND_ASSIGN, BINOP_MUL }, 185*6881a400Schristos { "/=", COMPOUND_ASSIGN, BINOP_DIV }, 186*6881a400Schristos { "%=", COMPOUND_ASSIGN, BINOP_REM }, 187*6881a400Schristos { "&=", COMPOUND_ASSIGN, BINOP_BITWISE_AND }, 188*6881a400Schristos { "|=", COMPOUND_ASSIGN, BINOP_BITWISE_IOR }, 189*6881a400Schristos { "^=", COMPOUND_ASSIGN, BINOP_BITWISE_XOR }, 190*6881a400Schristos { "..=", DOTDOTEQ, OP_NULL }, 191*6881a400Schristos 192*6881a400Schristos { "::", COLONCOLON, OP_NULL }, 193*6881a400Schristos { "..", DOTDOT, OP_NULL }, 194*6881a400Schristos { "->", ARROW, OP_NULL } 195*6881a400Schristos }; 196*6881a400Schristos 197*6881a400Schristos /* An instance of this is created before parsing, and destroyed when 198*6881a400Schristos parsing is finished. */ 199*6881a400Schristos 200*6881a400Schristos struct rust_parser 201*6881a400Schristos { 202*6881a400Schristos explicit rust_parser (struct parser_state *state) 203*6881a400Schristos : pstate (state) 204*6881a400Schristos { 205*6881a400Schristos } 206*6881a400Schristos 207*6881a400Schristos DISABLE_COPY_AND_ASSIGN (rust_parser); 208*6881a400Schristos 209*6881a400Schristos /* Return the parser's language. */ 210*6881a400Schristos const struct language_defn *language () const 211*6881a400Schristos { 212*6881a400Schristos return pstate->language (); 213*6881a400Schristos } 214*6881a400Schristos 215*6881a400Schristos /* Return the parser's gdbarch. */ 216*6881a400Schristos struct gdbarch *arch () const 217*6881a400Schristos { 218*6881a400Schristos return pstate->gdbarch (); 219*6881a400Schristos } 220*6881a400Schristos 221*6881a400Schristos /* A helper to look up a Rust type, or fail. This only works for 222*6881a400Schristos types defined by rust_language_arch_info. */ 223*6881a400Schristos 224*6881a400Schristos struct type *get_type (const char *name) 225*6881a400Schristos { 226*6881a400Schristos struct type *type; 227*6881a400Schristos 228*6881a400Schristos type = language_lookup_primitive_type (language (), arch (), name); 229*6881a400Schristos if (type == NULL) 230*6881a400Schristos error (_("Could not find Rust type %s"), name); 231*6881a400Schristos return type; 232*6881a400Schristos } 233*6881a400Schristos 234*6881a400Schristos std::string crate_name (const std::string &name); 235*6881a400Schristos std::string super_name (const std::string &ident, unsigned int n_supers); 236*6881a400Schristos 237*6881a400Schristos int lex_character (); 238*6881a400Schristos int lex_number (); 239*6881a400Schristos int lex_string (); 240*6881a400Schristos int lex_identifier (); 241*6881a400Schristos uint32_t lex_hex (int min, int max); 242*6881a400Schristos uint32_t lex_escape (int is_byte); 243*6881a400Schristos int lex_operator (); 244*6881a400Schristos int lex_one_token (); 245*6881a400Schristos void push_back (char c); 246*6881a400Schristos 247*6881a400Schristos /* The main interface to lexing. Lexes one token and updates the 248*6881a400Schristos internal state. */ 249*6881a400Schristos void lex () 250*6881a400Schristos { 251*6881a400Schristos current_token = lex_one_token (); 252*6881a400Schristos } 253*6881a400Schristos 254*6881a400Schristos /* Assuming the current token is TYPE, lex the next token. */ 255*6881a400Schristos void assume (int type) 256*6881a400Schristos { 257*6881a400Schristos gdb_assert (current_token == type); 258*6881a400Schristos lex (); 259*6881a400Schristos } 260*6881a400Schristos 261*6881a400Schristos /* Require the single-character token C, and lex the next token; or 262*6881a400Schristos throw an exception. */ 263*6881a400Schristos void require (char type) 264*6881a400Schristos { 265*6881a400Schristos if (current_token != type) 266*6881a400Schristos error (_("'%c' expected"), type); 267*6881a400Schristos lex (); 268*6881a400Schristos } 269*6881a400Schristos 270*6881a400Schristos /* Entry point for all parsing. */ 271*6881a400Schristos operation_up parse_entry_point () 272*6881a400Schristos { 273*6881a400Schristos lex (); 274*6881a400Schristos operation_up result = parse_expr (); 275*6881a400Schristos if (current_token != 0) 276*6881a400Schristos error (_("Syntax error near '%s'"), pstate->prev_lexptr); 277*6881a400Schristos return result; 278*6881a400Schristos } 279*6881a400Schristos 280*6881a400Schristos operation_up parse_tuple (); 281*6881a400Schristos operation_up parse_array (); 282*6881a400Schristos operation_up name_to_operation (const std::string &name); 283*6881a400Schristos operation_up parse_struct_expr (struct type *type); 284*6881a400Schristos operation_up parse_binop (bool required); 285*6881a400Schristos operation_up parse_range (); 286*6881a400Schristos operation_up parse_expr (); 287*6881a400Schristos operation_up parse_sizeof (); 288*6881a400Schristos operation_up parse_addr (); 289*6881a400Schristos operation_up parse_field (operation_up &&); 290*6881a400Schristos operation_up parse_index (operation_up &&); 291*6881a400Schristos std::vector<operation_up> parse_paren_args (); 292*6881a400Schristos operation_up parse_call (operation_up &&); 293*6881a400Schristos std::vector<struct type *> parse_type_list (); 294*6881a400Schristos std::vector<struct type *> parse_maybe_type_list (); 295*6881a400Schristos struct type *parse_array_type (); 296*6881a400Schristos struct type *parse_slice_type (); 297*6881a400Schristos struct type *parse_pointer_type (); 298*6881a400Schristos struct type *parse_function_type (); 299*6881a400Schristos struct type *parse_tuple_type (); 300*6881a400Schristos struct type *parse_type (); 301*6881a400Schristos std::string parse_path (bool for_expr); 302*6881a400Schristos operation_up parse_string (); 303*6881a400Schristos operation_up parse_tuple_struct (struct type *type); 304*6881a400Schristos operation_up parse_path_expr (); 305*6881a400Schristos operation_up parse_atom (bool required); 306*6881a400Schristos 307*6881a400Schristos void update_innermost_block (struct block_symbol sym); 308*6881a400Schristos struct block_symbol lookup_symbol (const char *name, 309*6881a400Schristos const struct block *block, 310*6881a400Schristos const domain_enum domain); 311*6881a400Schristos struct type *rust_lookup_type (const char *name); 312*6881a400Schristos 313*6881a400Schristos /* Clear some state. This is only used for testing. */ 314*6881a400Schristos #if GDB_SELF_TEST 315*6881a400Schristos void reset (const char *input) 316*6881a400Schristos { 317*6881a400Schristos pstate->prev_lexptr = nullptr; 318*6881a400Schristos pstate->lexptr = input; 319*6881a400Schristos paren_depth = 0; 320*6881a400Schristos current_token = 0; 321*6881a400Schristos current_int_val = {}; 322*6881a400Schristos current_float_val = {}; 323*6881a400Schristos current_string_val = {}; 324*6881a400Schristos current_opcode = OP_NULL; 325*6881a400Schristos } 326*6881a400Schristos #endif /* GDB_SELF_TEST */ 327*6881a400Schristos 328*6881a400Schristos /* Return the token's string value as a string. */ 329*6881a400Schristos std::string get_string () const 330*6881a400Schristos { 331*6881a400Schristos return std::string (current_string_val.ptr, current_string_val.length); 332*6881a400Schristos } 333*6881a400Schristos 334*6881a400Schristos /* A pointer to this is installed globally. */ 335*6881a400Schristos auto_obstack obstack; 336*6881a400Schristos 337*6881a400Schristos /* The parser state gdb gave us. */ 338*6881a400Schristos struct parser_state *pstate; 339*6881a400Schristos 340*6881a400Schristos /* Depth of parentheses. */ 341*6881a400Schristos int paren_depth = 0; 342*6881a400Schristos 343*6881a400Schristos /* The current token's type. */ 344*6881a400Schristos int current_token = 0; 345*6881a400Schristos /* The current token's payload, if any. */ 346*6881a400Schristos typed_val_int current_int_val {}; 347*6881a400Schristos typed_val_float current_float_val {}; 348*6881a400Schristos struct stoken current_string_val {}; 349*6881a400Schristos enum exp_opcode current_opcode = OP_NULL; 350*6881a400Schristos 351*6881a400Schristos /* When completing, this may be set to the field operation to 352*6881a400Schristos complete. */ 353*6881a400Schristos operation_up completion_op; 354*6881a400Schristos }; 355*6881a400Schristos 356*6881a400Schristos /* Return an string referring to NAME, but relative to the crate's 357*6881a400Schristos name. */ 358*6881a400Schristos 359*6881a400Schristos std::string 360*6881a400Schristos rust_parser::crate_name (const std::string &name) 361*6881a400Schristos { 362*6881a400Schristos std::string crate = rust_crate_for_block (pstate->expression_context_block); 363*6881a400Schristos 364*6881a400Schristos if (crate.empty ()) 365*6881a400Schristos error (_("Could not find crate for current location")); 366*6881a400Schristos return "::" + crate + "::" + name; 367*6881a400Schristos } 368*6881a400Schristos 369*6881a400Schristos /* Return a string referring to a "super::" qualified name. IDENT is 370*6881a400Schristos the base name and N_SUPERS is how many "super::"s were provided. 371*6881a400Schristos N_SUPERS can be zero. */ 372*6881a400Schristos 373*6881a400Schristos std::string 374*6881a400Schristos rust_parser::super_name (const std::string &ident, unsigned int n_supers) 375*6881a400Schristos { 376*6881a400Schristos const char *scope = block_scope (pstate->expression_context_block); 377*6881a400Schristos int offset; 378*6881a400Schristos 379*6881a400Schristos if (scope[0] == '\0') 380*6881a400Schristos error (_("Couldn't find namespace scope for self::")); 381*6881a400Schristos 382*6881a400Schristos if (n_supers > 0) 383*6881a400Schristos { 384*6881a400Schristos int len; 385*6881a400Schristos std::vector<int> offsets; 386*6881a400Schristos unsigned int current_len; 387*6881a400Schristos 388*6881a400Schristos current_len = cp_find_first_component (scope); 389*6881a400Schristos while (scope[current_len] != '\0') 390*6881a400Schristos { 391*6881a400Schristos offsets.push_back (current_len); 392*6881a400Schristos gdb_assert (scope[current_len] == ':'); 393*6881a400Schristos /* The "::". */ 394*6881a400Schristos current_len += 2; 395*6881a400Schristos current_len += cp_find_first_component (scope 396*6881a400Schristos + current_len); 397*6881a400Schristos } 398*6881a400Schristos 399*6881a400Schristos len = offsets.size (); 400*6881a400Schristos if (n_supers >= len) 401*6881a400Schristos error (_("Too many super:: uses from '%s'"), scope); 402*6881a400Schristos 403*6881a400Schristos offset = offsets[len - n_supers]; 404*6881a400Schristos } 405*6881a400Schristos else 406*6881a400Schristos offset = strlen (scope); 407*6881a400Schristos 408*6881a400Schristos return "::" + std::string (scope, offset) + "::" + ident; 409*6881a400Schristos } 410*6881a400Schristos 411*6881a400Schristos /* A helper to appropriately munge NAME and BLOCK depending on the 412*6881a400Schristos presence of a leading "::". */ 413*6881a400Schristos 414*6881a400Schristos static void 415*6881a400Schristos munge_name_and_block (const char **name, const struct block **block) 416*6881a400Schristos { 417*6881a400Schristos /* If it is a global reference, skip the current block in favor of 418*6881a400Schristos the static block. */ 419*6881a400Schristos if (startswith (*name, "::")) 420*6881a400Schristos { 421*6881a400Schristos *name += 2; 422*6881a400Schristos *block = block_static_block (*block); 423*6881a400Schristos } 424*6881a400Schristos } 425*6881a400Schristos 426*6881a400Schristos /* Like lookup_symbol, but handles Rust namespace conventions, and 427*6881a400Schristos doesn't require field_of_this_result. */ 428*6881a400Schristos 429*6881a400Schristos struct block_symbol 430*6881a400Schristos rust_parser::lookup_symbol (const char *name, const struct block *block, 431*6881a400Schristos const domain_enum domain) 432*6881a400Schristos { 433*6881a400Schristos struct block_symbol result; 434*6881a400Schristos 435*6881a400Schristos munge_name_and_block (&name, &block); 436*6881a400Schristos 437*6881a400Schristos result = ::lookup_symbol (name, block, domain, NULL); 438*6881a400Schristos if (result.symbol != NULL) 439*6881a400Schristos update_innermost_block (result); 440*6881a400Schristos return result; 441*6881a400Schristos } 442*6881a400Schristos 443*6881a400Schristos /* Look up a type, following Rust namespace conventions. */ 444*6881a400Schristos 445*6881a400Schristos struct type * 446*6881a400Schristos rust_parser::rust_lookup_type (const char *name) 447*6881a400Schristos { 448*6881a400Schristos struct block_symbol result; 449*6881a400Schristos struct type *type; 450*6881a400Schristos 451*6881a400Schristos const struct block *block = pstate->expression_context_block; 452*6881a400Schristos munge_name_and_block (&name, &block); 453*6881a400Schristos 454*6881a400Schristos result = ::lookup_symbol (name, block, STRUCT_DOMAIN, NULL); 455*6881a400Schristos if (result.symbol != NULL) 456*6881a400Schristos { 457*6881a400Schristos update_innermost_block (result); 458*6881a400Schristos return result.symbol->type (); 459*6881a400Schristos } 460*6881a400Schristos 461*6881a400Schristos type = lookup_typename (language (), name, NULL, 1); 462*6881a400Schristos if (type != NULL) 463*6881a400Schristos return type; 464*6881a400Schristos 465*6881a400Schristos /* Last chance, try a built-in type. */ 466*6881a400Schristos return language_lookup_primitive_type (language (), arch (), name); 467*6881a400Schristos } 468*6881a400Schristos 469*6881a400Schristos /* A helper that updates the innermost block as appropriate. */ 470*6881a400Schristos 471*6881a400Schristos void 472*6881a400Schristos rust_parser::update_innermost_block (struct block_symbol sym) 473*6881a400Schristos { 474*6881a400Schristos if (symbol_read_needs_frame (sym.symbol)) 475*6881a400Schristos pstate->block_tracker->update (sym); 476*6881a400Schristos } 477*6881a400Schristos 478*6881a400Schristos /* Lex a hex number with at least MIN digits and at most MAX 479*6881a400Schristos digits. */ 480*6881a400Schristos 481*6881a400Schristos uint32_t 482*6881a400Schristos rust_parser::lex_hex (int min, int max) 483*6881a400Schristos { 484*6881a400Schristos uint32_t result = 0; 485*6881a400Schristos int len = 0; 486*6881a400Schristos /* We only want to stop at MAX if we're lexing a byte escape. */ 487*6881a400Schristos int check_max = min == max; 488*6881a400Schristos 489*6881a400Schristos while ((check_max ? len <= max : 1) 490*6881a400Schristos && ((pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'f') 491*6881a400Schristos || (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'F') 492*6881a400Schristos || (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9'))) 493*6881a400Schristos { 494*6881a400Schristos result *= 16; 495*6881a400Schristos if (pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'f') 496*6881a400Schristos result = result + 10 + pstate->lexptr[0] - 'a'; 497*6881a400Schristos else if (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'F') 498*6881a400Schristos result = result + 10 + pstate->lexptr[0] - 'A'; 499*6881a400Schristos else 500*6881a400Schristos result = result + pstate->lexptr[0] - '0'; 501*6881a400Schristos ++pstate->lexptr; 502*6881a400Schristos ++len; 503*6881a400Schristos } 504*6881a400Schristos 505*6881a400Schristos if (len < min) 506*6881a400Schristos error (_("Not enough hex digits seen")); 507*6881a400Schristos if (len > max) 508*6881a400Schristos { 509*6881a400Schristos gdb_assert (min != max); 510*6881a400Schristos error (_("Overlong hex escape")); 511*6881a400Schristos } 512*6881a400Schristos 513*6881a400Schristos return result; 514*6881a400Schristos } 515*6881a400Schristos 516*6881a400Schristos /* Lex an escape. IS_BYTE is true if we're lexing a byte escape; 517*6881a400Schristos otherwise we're lexing a character escape. */ 518*6881a400Schristos 519*6881a400Schristos uint32_t 520*6881a400Schristos rust_parser::lex_escape (int is_byte) 521*6881a400Schristos { 522*6881a400Schristos uint32_t result; 523*6881a400Schristos 524*6881a400Schristos gdb_assert (pstate->lexptr[0] == '\\'); 525*6881a400Schristos ++pstate->lexptr; 526*6881a400Schristos switch (pstate->lexptr[0]) 527*6881a400Schristos { 528*6881a400Schristos case 'x': 529*6881a400Schristos ++pstate->lexptr; 530*6881a400Schristos result = lex_hex (2, 2); 531*6881a400Schristos break; 532*6881a400Schristos 533*6881a400Schristos case 'u': 534*6881a400Schristos if (is_byte) 535*6881a400Schristos error (_("Unicode escape in byte literal")); 536*6881a400Schristos ++pstate->lexptr; 537*6881a400Schristos if (pstate->lexptr[0] != '{') 538*6881a400Schristos error (_("Missing '{' in Unicode escape")); 539*6881a400Schristos ++pstate->lexptr; 540*6881a400Schristos result = lex_hex (1, 6); 541*6881a400Schristos /* Could do range checks here. */ 542*6881a400Schristos if (pstate->lexptr[0] != '}') 543*6881a400Schristos error (_("Missing '}' in Unicode escape")); 544*6881a400Schristos ++pstate->lexptr; 545*6881a400Schristos break; 546*6881a400Schristos 547*6881a400Schristos case 'n': 548*6881a400Schristos result = '\n'; 549*6881a400Schristos ++pstate->lexptr; 550*6881a400Schristos break; 551*6881a400Schristos case 'r': 552*6881a400Schristos result = '\r'; 553*6881a400Schristos ++pstate->lexptr; 554*6881a400Schristos break; 555*6881a400Schristos case 't': 556*6881a400Schristos result = '\t'; 557*6881a400Schristos ++pstate->lexptr; 558*6881a400Schristos break; 559*6881a400Schristos case '\\': 560*6881a400Schristos result = '\\'; 561*6881a400Schristos ++pstate->lexptr; 562*6881a400Schristos break; 563*6881a400Schristos case '0': 564*6881a400Schristos result = '\0'; 565*6881a400Schristos ++pstate->lexptr; 566*6881a400Schristos break; 567*6881a400Schristos case '\'': 568*6881a400Schristos result = '\''; 569*6881a400Schristos ++pstate->lexptr; 570*6881a400Schristos break; 571*6881a400Schristos case '"': 572*6881a400Schristos result = '"'; 573*6881a400Schristos ++pstate->lexptr; 574*6881a400Schristos break; 575*6881a400Schristos 576*6881a400Schristos default: 577*6881a400Schristos error (_("Invalid escape \\%c in literal"), pstate->lexptr[0]); 578*6881a400Schristos } 579*6881a400Schristos 580*6881a400Schristos return result; 581*6881a400Schristos } 582*6881a400Schristos 583*6881a400Schristos /* A helper for lex_character. Search forward for the closing single 584*6881a400Schristos quote, then convert the bytes from the host charset to UTF-32. */ 585*6881a400Schristos 586*6881a400Schristos static uint32_t 587*6881a400Schristos lex_multibyte_char (const char *text, int *len) 588*6881a400Schristos { 589*6881a400Schristos /* Only look a maximum of 5 bytes for the closing quote. This is 590*6881a400Schristos the maximum for UTF-8. */ 591*6881a400Schristos int quote; 592*6881a400Schristos gdb_assert (text[0] != '\''); 593*6881a400Schristos for (quote = 1; text[quote] != '\0' && text[quote] != '\''; ++quote) 594*6881a400Schristos ; 595*6881a400Schristos *len = quote; 596*6881a400Schristos /* The caller will issue an error. */ 597*6881a400Schristos if (text[quote] == '\0') 598*6881a400Schristos return 0; 599*6881a400Schristos 600*6881a400Schristos auto_obstack result; 601*6881a400Schristos convert_between_encodings (host_charset (), HOST_UTF32, 602*6881a400Schristos (const gdb_byte *) text, 603*6881a400Schristos quote, 1, &result, translit_none); 604*6881a400Schristos 605*6881a400Schristos int size = obstack_object_size (&result); 606*6881a400Schristos if (size > 4) 607*6881a400Schristos error (_("overlong character literal")); 608*6881a400Schristos uint32_t value; 609*6881a400Schristos memcpy (&value, obstack_finish (&result), size); 610*6881a400Schristos return value; 611*6881a400Schristos } 612*6881a400Schristos 613*6881a400Schristos /* Lex a character constant. */ 614*6881a400Schristos 615*6881a400Schristos int 616*6881a400Schristos rust_parser::lex_character () 617*6881a400Schristos { 618*6881a400Schristos int is_byte = 0; 619*6881a400Schristos uint32_t value; 620*6881a400Schristos 621*6881a400Schristos if (pstate->lexptr[0] == 'b') 622*6881a400Schristos { 623*6881a400Schristos is_byte = 1; 624*6881a400Schristos ++pstate->lexptr; 625*6881a400Schristos } 626*6881a400Schristos gdb_assert (pstate->lexptr[0] == '\''); 627*6881a400Schristos ++pstate->lexptr; 628*6881a400Schristos if (pstate->lexptr[0] == '\'') 629*6881a400Schristos error (_("empty character literal")); 630*6881a400Schristos else if (pstate->lexptr[0] == '\\') 631*6881a400Schristos value = lex_escape (is_byte); 632*6881a400Schristos else 633*6881a400Schristos { 634*6881a400Schristos int len; 635*6881a400Schristos value = lex_multibyte_char (&pstate->lexptr[0], &len); 636*6881a400Schristos pstate->lexptr += len; 637*6881a400Schristos } 638*6881a400Schristos 639*6881a400Schristos if (pstate->lexptr[0] != '\'') 640*6881a400Schristos error (_("Unterminated character literal")); 641*6881a400Schristos ++pstate->lexptr; 642*6881a400Schristos 643*6881a400Schristos current_int_val.val = value; 644*6881a400Schristos current_int_val.type = get_type (is_byte ? "u8" : "char"); 645*6881a400Schristos 646*6881a400Schristos return INTEGER; 647*6881a400Schristos } 648*6881a400Schristos 649*6881a400Schristos /* Return the offset of the double quote if STR looks like the start 650*6881a400Schristos of a raw string, or 0 if STR does not start a raw string. */ 651*6881a400Schristos 652*6881a400Schristos static int 653*6881a400Schristos starts_raw_string (const char *str) 654*6881a400Schristos { 655*6881a400Schristos const char *save = str; 656*6881a400Schristos 657*6881a400Schristos if (str[0] != 'r') 658*6881a400Schristos return 0; 659*6881a400Schristos ++str; 660*6881a400Schristos while (str[0] == '#') 661*6881a400Schristos ++str; 662*6881a400Schristos if (str[0] == '"') 663*6881a400Schristos return str - save; 664*6881a400Schristos return 0; 665*6881a400Schristos } 666*6881a400Schristos 667*6881a400Schristos /* Return true if STR looks like the end of a raw string that had N 668*6881a400Schristos hashes at the start. */ 669*6881a400Schristos 670*6881a400Schristos static bool 671*6881a400Schristos ends_raw_string (const char *str, int n) 672*6881a400Schristos { 673*6881a400Schristos int i; 674*6881a400Schristos 675*6881a400Schristos gdb_assert (str[0] == '"'); 676*6881a400Schristos for (i = 0; i < n; ++i) 677*6881a400Schristos if (str[i + 1] != '#') 678*6881a400Schristos return false; 679*6881a400Schristos return true; 680*6881a400Schristos } 681*6881a400Schristos 682*6881a400Schristos /* Lex a string constant. */ 683*6881a400Schristos 684*6881a400Schristos int 685*6881a400Schristos rust_parser::lex_string () 686*6881a400Schristos { 687*6881a400Schristos int is_byte = pstate->lexptr[0] == 'b'; 688*6881a400Schristos int raw_length; 689*6881a400Schristos 690*6881a400Schristos if (is_byte) 691*6881a400Schristos ++pstate->lexptr; 692*6881a400Schristos raw_length = starts_raw_string (pstate->lexptr); 693*6881a400Schristos pstate->lexptr += raw_length; 694*6881a400Schristos gdb_assert (pstate->lexptr[0] == '"'); 695*6881a400Schristos ++pstate->lexptr; 696*6881a400Schristos 697*6881a400Schristos while (1) 698*6881a400Schristos { 699*6881a400Schristos uint32_t value; 700*6881a400Schristos 701*6881a400Schristos if (raw_length > 0) 702*6881a400Schristos { 703*6881a400Schristos if (pstate->lexptr[0] == '"' && ends_raw_string (pstate->lexptr, 704*6881a400Schristos raw_length - 1)) 705*6881a400Schristos { 706*6881a400Schristos /* Exit with lexptr pointing after the final "#". */ 707*6881a400Schristos pstate->lexptr += raw_length; 708*6881a400Schristos break; 709*6881a400Schristos } 710*6881a400Schristos else if (pstate->lexptr[0] == '\0') 711*6881a400Schristos error (_("Unexpected EOF in string")); 712*6881a400Schristos 713*6881a400Schristos value = pstate->lexptr[0] & 0xff; 714*6881a400Schristos if (is_byte && value > 127) 715*6881a400Schristos error (_("Non-ASCII value in raw byte string")); 716*6881a400Schristos obstack_1grow (&obstack, value); 717*6881a400Schristos 718*6881a400Schristos ++pstate->lexptr; 719*6881a400Schristos } 720*6881a400Schristos else if (pstate->lexptr[0] == '"') 721*6881a400Schristos { 722*6881a400Schristos /* Make sure to skip the quote. */ 723*6881a400Schristos ++pstate->lexptr; 724*6881a400Schristos break; 725*6881a400Schristos } 726*6881a400Schristos else if (pstate->lexptr[0] == '\\') 727*6881a400Schristos { 728*6881a400Schristos value = lex_escape (is_byte); 729*6881a400Schristos 730*6881a400Schristos if (is_byte) 731*6881a400Schristos obstack_1grow (&obstack, value); 732*6881a400Schristos else 733*6881a400Schristos convert_between_encodings (HOST_UTF32, "UTF-8", 734*6881a400Schristos (gdb_byte *) &value, 735*6881a400Schristos sizeof (value), sizeof (value), 736*6881a400Schristos &obstack, translit_none); 737*6881a400Schristos } 738*6881a400Schristos else if (pstate->lexptr[0] == '\0') 739*6881a400Schristos error (_("Unexpected EOF in string")); 740*6881a400Schristos else 741*6881a400Schristos { 742*6881a400Schristos value = pstate->lexptr[0] & 0xff; 743*6881a400Schristos if (is_byte && value > 127) 744*6881a400Schristos error (_("Non-ASCII value in byte string")); 745*6881a400Schristos obstack_1grow (&obstack, value); 746*6881a400Schristos ++pstate->lexptr; 747*6881a400Schristos } 748*6881a400Schristos } 749*6881a400Schristos 750*6881a400Schristos current_string_val.length = obstack_object_size (&obstack); 751*6881a400Schristos current_string_val.ptr = (const char *) obstack_finish (&obstack); 752*6881a400Schristos return is_byte ? BYTESTRING : STRING; 753*6881a400Schristos } 754*6881a400Schristos 755*6881a400Schristos /* Return true if STRING starts with whitespace followed by a digit. */ 756*6881a400Schristos 757*6881a400Schristos static bool 758*6881a400Schristos space_then_number (const char *string) 759*6881a400Schristos { 760*6881a400Schristos const char *p = string; 761*6881a400Schristos 762*6881a400Schristos while (p[0] == ' ' || p[0] == '\t') 763*6881a400Schristos ++p; 764*6881a400Schristos if (p == string) 765*6881a400Schristos return false; 766*6881a400Schristos 767*6881a400Schristos return *p >= '0' && *p <= '9'; 768*6881a400Schristos } 769*6881a400Schristos 770*6881a400Schristos /* Return true if C can start an identifier. */ 771*6881a400Schristos 772*6881a400Schristos static bool 773*6881a400Schristos rust_identifier_start_p (char c) 774*6881a400Schristos { 775*6881a400Schristos return ((c >= 'a' && c <= 'z') 776*6881a400Schristos || (c >= 'A' && c <= 'Z') 777*6881a400Schristos || c == '_' 778*6881a400Schristos || c == '$' 779*6881a400Schristos /* Allow any non-ASCII character as an identifier. There 780*6881a400Schristos doesn't seem to be a need to be picky about this. */ 781*6881a400Schristos || (c & 0x80) != 0); 782*6881a400Schristos } 783*6881a400Schristos 784*6881a400Schristos /* Lex an identifier. */ 785*6881a400Schristos 786*6881a400Schristos int 787*6881a400Schristos rust_parser::lex_identifier () 788*6881a400Schristos { 789*6881a400Schristos unsigned int length; 790*6881a400Schristos const struct token_info *token; 791*6881a400Schristos int is_gdb_var = pstate->lexptr[0] == '$'; 792*6881a400Schristos 793*6881a400Schristos bool is_raw = false; 794*6881a400Schristos if (pstate->lexptr[0] == 'r' 795*6881a400Schristos && pstate->lexptr[1] == '#' 796*6881a400Schristos && rust_identifier_start_p (pstate->lexptr[2])) 797*6881a400Schristos { 798*6881a400Schristos is_raw = true; 799*6881a400Schristos pstate->lexptr += 2; 800*6881a400Schristos } 801*6881a400Schristos 802*6881a400Schristos const char *start = pstate->lexptr; 803*6881a400Schristos gdb_assert (rust_identifier_start_p (pstate->lexptr[0])); 804*6881a400Schristos 805*6881a400Schristos ++pstate->lexptr; 806*6881a400Schristos 807*6881a400Schristos /* Allow any non-ASCII character here. This "handles" UTF-8 by 808*6881a400Schristos passing it through. */ 809*6881a400Schristos while ((pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'z') 810*6881a400Schristos || (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'Z') 811*6881a400Schristos || pstate->lexptr[0] == '_' 812*6881a400Schristos || (is_gdb_var && pstate->lexptr[0] == '$') 813*6881a400Schristos || (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9') 814*6881a400Schristos || (pstate->lexptr[0] & 0x80) != 0) 815*6881a400Schristos ++pstate->lexptr; 816*6881a400Schristos 817*6881a400Schristos 818*6881a400Schristos length = pstate->lexptr - start; 819*6881a400Schristos token = NULL; 820*6881a400Schristos if (!is_raw) 821*6881a400Schristos { 822*6881a400Schristos for (const auto &candidate : identifier_tokens) 823*6881a400Schristos { 824*6881a400Schristos if (length == strlen (candidate.name) 825*6881a400Schristos && strncmp (candidate.name, start, length) == 0) 826*6881a400Schristos { 827*6881a400Schristos token = &candidate; 828*6881a400Schristos break; 829*6881a400Schristos } 830*6881a400Schristos } 831*6881a400Schristos } 832*6881a400Schristos 833*6881a400Schristos if (token != NULL) 834*6881a400Schristos { 835*6881a400Schristos if (token->value == 0) 836*6881a400Schristos { 837*6881a400Schristos /* Leave the terminating token alone. */ 838*6881a400Schristos pstate->lexptr = start; 839*6881a400Schristos return 0; 840*6881a400Schristos } 841*6881a400Schristos } 842*6881a400Schristos else if (token == NULL 843*6881a400Schristos && !is_raw 844*6881a400Schristos && (strncmp (start, "thread", length) == 0 845*6881a400Schristos || strncmp (start, "task", length) == 0) 846*6881a400Schristos && space_then_number (pstate->lexptr)) 847*6881a400Schristos { 848*6881a400Schristos /* "task" or "thread" followed by a number terminates the 849*6881a400Schristos parse, per gdb rules. */ 850*6881a400Schristos pstate->lexptr = start; 851*6881a400Schristos return 0; 852*6881a400Schristos } 853*6881a400Schristos 854*6881a400Schristos if (token == NULL || (pstate->parse_completion && pstate->lexptr[0] == '\0')) 855*6881a400Schristos { 856*6881a400Schristos current_string_val.length = length; 857*6881a400Schristos current_string_val.ptr = start; 858*6881a400Schristos } 859*6881a400Schristos 860*6881a400Schristos if (pstate->parse_completion && pstate->lexptr[0] == '\0') 861*6881a400Schristos { 862*6881a400Schristos /* Prevent rustyylex from returning two COMPLETE tokens. */ 863*6881a400Schristos pstate->prev_lexptr = pstate->lexptr; 864*6881a400Schristos return COMPLETE; 865*6881a400Schristos } 866*6881a400Schristos 867*6881a400Schristos if (token != NULL) 868*6881a400Schristos return token->value; 869*6881a400Schristos if (is_gdb_var) 870*6881a400Schristos return GDBVAR; 871*6881a400Schristos return IDENT; 872*6881a400Schristos } 873*6881a400Schristos 874*6881a400Schristos /* Lex an operator. */ 875*6881a400Schristos 876*6881a400Schristos int 877*6881a400Schristos rust_parser::lex_operator () 878*6881a400Schristos { 879*6881a400Schristos const struct token_info *token = NULL; 880*6881a400Schristos 881*6881a400Schristos for (const auto &candidate : operator_tokens) 882*6881a400Schristos { 883*6881a400Schristos if (strncmp (candidate.name, pstate->lexptr, 884*6881a400Schristos strlen (candidate.name)) == 0) 885*6881a400Schristos { 886*6881a400Schristos pstate->lexptr += strlen (candidate.name); 887*6881a400Schristos token = &candidate; 888*6881a400Schristos break; 889*6881a400Schristos } 890*6881a400Schristos } 891*6881a400Schristos 892*6881a400Schristos if (token != NULL) 893*6881a400Schristos { 894*6881a400Schristos current_opcode = token->opcode; 895*6881a400Schristos return token->value; 896*6881a400Schristos } 897*6881a400Schristos 898*6881a400Schristos return *pstate->lexptr++; 899*6881a400Schristos } 900*6881a400Schristos 901*6881a400Schristos /* Lex a number. */ 902*6881a400Schristos 903*6881a400Schristos int 904*6881a400Schristos rust_parser::lex_number () 905*6881a400Schristos { 906*6881a400Schristos regmatch_t subexps[NUM_SUBEXPRESSIONS]; 907*6881a400Schristos int match; 908*6881a400Schristos int is_integer = 0; 909*6881a400Schristos int could_be_decimal = 1; 910*6881a400Schristos int implicit_i32 = 0; 911*6881a400Schristos const char *type_name = NULL; 912*6881a400Schristos struct type *type; 913*6881a400Schristos int end_index; 914*6881a400Schristos int type_index = -1; 915*6881a400Schristos int i; 916*6881a400Schristos 917*6881a400Schristos match = regexec (&number_regex, pstate->lexptr, ARRAY_SIZE (subexps), 918*6881a400Schristos subexps, 0); 919*6881a400Schristos /* Failure means the regexp is broken. */ 920*6881a400Schristos gdb_assert (match == 0); 921*6881a400Schristos 922*6881a400Schristos if (subexps[INT_TEXT].rm_so != -1) 923*6881a400Schristos { 924*6881a400Schristos /* Integer part matched. */ 925*6881a400Schristos is_integer = 1; 926*6881a400Schristos end_index = subexps[INT_TEXT].rm_eo; 927*6881a400Schristos if (subexps[INT_TYPE].rm_so == -1) 928*6881a400Schristos { 929*6881a400Schristos type_name = "i32"; 930*6881a400Schristos implicit_i32 = 1; 931*6881a400Schristos } 932*6881a400Schristos else 933*6881a400Schristos { 934*6881a400Schristos type_index = INT_TYPE; 935*6881a400Schristos could_be_decimal = 0; 936*6881a400Schristos } 937*6881a400Schristos } 938*6881a400Schristos else if (subexps[FLOAT_TYPE1].rm_so != -1) 939*6881a400Schristos { 940*6881a400Schristos /* Found floating point type suffix. */ 941*6881a400Schristos end_index = subexps[FLOAT_TYPE1].rm_so; 942*6881a400Schristos type_index = FLOAT_TYPE1; 943*6881a400Schristos } 944*6881a400Schristos else if (subexps[FLOAT_TYPE2].rm_so != -1) 945*6881a400Schristos { 946*6881a400Schristos /* Found floating point type suffix. */ 947*6881a400Schristos end_index = subexps[FLOAT_TYPE2].rm_so; 948*6881a400Schristos type_index = FLOAT_TYPE2; 949*6881a400Schristos } 950*6881a400Schristos else 951*6881a400Schristos { 952*6881a400Schristos /* Any other floating point match. */ 953*6881a400Schristos end_index = subexps[0].rm_eo; 954*6881a400Schristos type_name = "f64"; 955*6881a400Schristos } 956*6881a400Schristos 957*6881a400Schristos /* We need a special case if the final character is ".". In this 958*6881a400Schristos case we might need to parse an integer. For example, "23.f()" is 959*6881a400Schristos a request for a trait method call, not a syntax error involving 960*6881a400Schristos the floating point number "23.". */ 961*6881a400Schristos gdb_assert (subexps[0].rm_eo > 0); 962*6881a400Schristos if (pstate->lexptr[subexps[0].rm_eo - 1] == '.') 963*6881a400Schristos { 964*6881a400Schristos const char *next = skip_spaces (&pstate->lexptr[subexps[0].rm_eo]); 965*6881a400Schristos 966*6881a400Schristos if (rust_identifier_start_p (*next) || *next == '.') 967*6881a400Schristos { 968*6881a400Schristos --subexps[0].rm_eo; 969*6881a400Schristos is_integer = 1; 970*6881a400Schristos end_index = subexps[0].rm_eo; 971*6881a400Schristos type_name = "i32"; 972*6881a400Schristos could_be_decimal = 1; 973*6881a400Schristos implicit_i32 = 1; 974*6881a400Schristos } 975*6881a400Schristos } 976*6881a400Schristos 977*6881a400Schristos /* Compute the type name if we haven't already. */ 978*6881a400Schristos std::string type_name_holder; 979*6881a400Schristos if (type_name == NULL) 980*6881a400Schristos { 981*6881a400Schristos gdb_assert (type_index != -1); 982*6881a400Schristos type_name_holder = std::string ((pstate->lexptr 983*6881a400Schristos + subexps[type_index].rm_so), 984*6881a400Schristos (subexps[type_index].rm_eo 985*6881a400Schristos - subexps[type_index].rm_so)); 986*6881a400Schristos type_name = type_name_holder.c_str (); 987*6881a400Schristos } 988*6881a400Schristos 989*6881a400Schristos /* Look up the type. */ 990*6881a400Schristos type = get_type (type_name); 991*6881a400Schristos 992*6881a400Schristos /* Copy the text of the number and remove the "_"s. */ 993*6881a400Schristos std::string number; 994*6881a400Schristos for (i = 0; i < end_index && pstate->lexptr[i]; ++i) 995*6881a400Schristos { 996*6881a400Schristos if (pstate->lexptr[i] == '_') 997*6881a400Schristos could_be_decimal = 0; 998*6881a400Schristos else 999*6881a400Schristos number.push_back (pstate->lexptr[i]); 1000*6881a400Schristos } 1001*6881a400Schristos 1002*6881a400Schristos /* Advance past the match. */ 1003*6881a400Schristos pstate->lexptr += subexps[0].rm_eo; 1004*6881a400Schristos 1005*6881a400Schristos /* Parse the number. */ 1006*6881a400Schristos if (is_integer) 1007*6881a400Schristos { 1008*6881a400Schristos uint64_t value; 1009*6881a400Schristos int radix = 10; 1010*6881a400Schristos int offset = 0; 1011*6881a400Schristos 1012*6881a400Schristos if (number[0] == '0') 1013*6881a400Schristos { 1014*6881a400Schristos if (number[1] == 'x') 1015*6881a400Schristos radix = 16; 1016*6881a400Schristos else if (number[1] == 'o') 1017*6881a400Schristos radix = 8; 1018*6881a400Schristos else if (number[1] == 'b') 1019*6881a400Schristos radix = 2; 1020*6881a400Schristos if (radix != 10) 1021*6881a400Schristos { 1022*6881a400Schristos offset = 2; 1023*6881a400Schristos could_be_decimal = 0; 1024*6881a400Schristos } 1025*6881a400Schristos } 1026*6881a400Schristos 1027*6881a400Schristos const char *trailer; 1028*6881a400Schristos value = strtoulst (number.c_str () + offset, &trailer, radix); 1029*6881a400Schristos if (*trailer != '\0') 1030*6881a400Schristos error (_("Integer literal is too large")); 1031*6881a400Schristos if (implicit_i32 && value >= ((uint64_t) 1) << 31) 1032*6881a400Schristos type = get_type ("i64"); 1033*6881a400Schristos 1034*6881a400Schristos current_int_val.val = value; 1035*6881a400Schristos current_int_val.type = type; 1036*6881a400Schristos } 1037*6881a400Schristos else 1038*6881a400Schristos { 1039*6881a400Schristos current_float_val.type = type; 1040*6881a400Schristos bool parsed = parse_float (number.c_str (), number.length (), 1041*6881a400Schristos current_float_val.type, 1042*6881a400Schristos current_float_val.val.data ()); 1043*6881a400Schristos gdb_assert (parsed); 1044*6881a400Schristos } 1045*6881a400Schristos 1046*6881a400Schristos return is_integer ? (could_be_decimal ? DECIMAL_INTEGER : INTEGER) : FLOAT; 1047*6881a400Schristos } 1048*6881a400Schristos 1049*6881a400Schristos /* The lexer. */ 1050*6881a400Schristos 1051*6881a400Schristos int 1052*6881a400Schristos rust_parser::lex_one_token () 1053*6881a400Schristos { 1054*6881a400Schristos /* Skip all leading whitespace. */ 1055*6881a400Schristos while (pstate->lexptr[0] == ' ' 1056*6881a400Schristos || pstate->lexptr[0] == '\t' 1057*6881a400Schristos || pstate->lexptr[0] == '\r' 1058*6881a400Schristos || pstate->lexptr[0] == '\n') 1059*6881a400Schristos ++pstate->lexptr; 1060*6881a400Schristos 1061*6881a400Schristos /* If we hit EOF and we're completing, then return COMPLETE -- maybe 1062*6881a400Schristos we're completing an empty string at the end of a field_expr. 1063*6881a400Schristos But, we don't want to return two COMPLETE tokens in a row. */ 1064*6881a400Schristos if (pstate->lexptr[0] == '\0' && pstate->lexptr == pstate->prev_lexptr) 1065*6881a400Schristos return 0; 1066*6881a400Schristos pstate->prev_lexptr = pstate->lexptr; 1067*6881a400Schristos if (pstate->lexptr[0] == '\0') 1068*6881a400Schristos { 1069*6881a400Schristos if (pstate->parse_completion) 1070*6881a400Schristos { 1071*6881a400Schristos current_string_val.length =0; 1072*6881a400Schristos current_string_val.ptr = ""; 1073*6881a400Schristos return COMPLETE; 1074*6881a400Schristos } 1075*6881a400Schristos return 0; 1076*6881a400Schristos } 1077*6881a400Schristos 1078*6881a400Schristos if (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9') 1079*6881a400Schristos return lex_number (); 1080*6881a400Schristos else if (pstate->lexptr[0] == 'b' && pstate->lexptr[1] == '\'') 1081*6881a400Schristos return lex_character (); 1082*6881a400Schristos else if (pstate->lexptr[0] == 'b' && pstate->lexptr[1] == '"') 1083*6881a400Schristos return lex_string (); 1084*6881a400Schristos else if (pstate->lexptr[0] == 'b' && starts_raw_string (pstate->lexptr + 1)) 1085*6881a400Schristos return lex_string (); 1086*6881a400Schristos else if (starts_raw_string (pstate->lexptr)) 1087*6881a400Schristos return lex_string (); 1088*6881a400Schristos else if (rust_identifier_start_p (pstate->lexptr[0])) 1089*6881a400Schristos return lex_identifier (); 1090*6881a400Schristos else if (pstate->lexptr[0] == '"') 1091*6881a400Schristos return lex_string (); 1092*6881a400Schristos else if (pstate->lexptr[0] == '\'') 1093*6881a400Schristos return lex_character (); 1094*6881a400Schristos else if (pstate->lexptr[0] == '}' || pstate->lexptr[0] == ']') 1095*6881a400Schristos { 1096*6881a400Schristos /* Falls through to lex_operator. */ 1097*6881a400Schristos --paren_depth; 1098*6881a400Schristos } 1099*6881a400Schristos else if (pstate->lexptr[0] == '(' || pstate->lexptr[0] == '{') 1100*6881a400Schristos { 1101*6881a400Schristos /* Falls through to lex_operator. */ 1102*6881a400Schristos ++paren_depth; 1103*6881a400Schristos } 1104*6881a400Schristos else if (pstate->lexptr[0] == ',' && pstate->comma_terminates 1105*6881a400Schristos && paren_depth == 0) 1106*6881a400Schristos return 0; 1107*6881a400Schristos 1108*6881a400Schristos return lex_operator (); 1109*6881a400Schristos } 1110*6881a400Schristos 1111*6881a400Schristos /* Push back a single character to be re-lexed. */ 1112*6881a400Schristos 1113*6881a400Schristos void 1114*6881a400Schristos rust_parser::push_back (char c) 1115*6881a400Schristos { 1116*6881a400Schristos /* Can't be called before any lexing. */ 1117*6881a400Schristos gdb_assert (pstate->prev_lexptr != NULL); 1118*6881a400Schristos 1119*6881a400Schristos --pstate->lexptr; 1120*6881a400Schristos gdb_assert (*pstate->lexptr == c); 1121*6881a400Schristos } 1122*6881a400Schristos 1123*6881a400Schristos 1124*6881a400Schristos 1125*6881a400Schristos /* Parse a tuple or paren expression. */ 1126*6881a400Schristos 1127*6881a400Schristos operation_up 1128*6881a400Schristos rust_parser::parse_tuple () 1129*6881a400Schristos { 1130*6881a400Schristos assume ('('); 1131*6881a400Schristos 1132*6881a400Schristos if (current_token == ')') 1133*6881a400Schristos { 1134*6881a400Schristos lex (); 1135*6881a400Schristos struct type *unit = get_type ("()"); 1136*6881a400Schristos return make_operation<long_const_operation> (unit, 0); 1137*6881a400Schristos } 1138*6881a400Schristos 1139*6881a400Schristos operation_up expr = parse_expr (); 1140*6881a400Schristos if (current_token == ')') 1141*6881a400Schristos { 1142*6881a400Schristos /* Parenthesized expression. */ 1143*6881a400Schristos lex (); 1144*6881a400Schristos return make_operation<rust_parenthesized_operation> (std::move (expr)); 1145*6881a400Schristos } 1146*6881a400Schristos 1147*6881a400Schristos std::vector<operation_up> ops; 1148*6881a400Schristos ops.push_back (std::move (expr)); 1149*6881a400Schristos while (current_token != ')') 1150*6881a400Schristos { 1151*6881a400Schristos if (current_token != ',') 1152*6881a400Schristos error (_("',' or ')' expected")); 1153*6881a400Schristos lex (); 1154*6881a400Schristos 1155*6881a400Schristos /* A trailing "," is ok. */ 1156*6881a400Schristos if (current_token != ')') 1157*6881a400Schristos ops.push_back (parse_expr ()); 1158*6881a400Schristos } 1159*6881a400Schristos 1160*6881a400Schristos assume (')'); 1161*6881a400Schristos 1162*6881a400Schristos error (_("Tuple expressions not supported yet")); 1163*6881a400Schristos } 1164*6881a400Schristos 1165*6881a400Schristos /* Parse an array expression. */ 1166*6881a400Schristos 1167*6881a400Schristos operation_up 1168*6881a400Schristos rust_parser::parse_array () 1169*6881a400Schristos { 1170*6881a400Schristos assume ('['); 1171*6881a400Schristos 1172*6881a400Schristos if (current_token == KW_MUT) 1173*6881a400Schristos lex (); 1174*6881a400Schristos 1175*6881a400Schristos operation_up result; 1176*6881a400Schristos operation_up expr = parse_expr (); 1177*6881a400Schristos if (current_token == ';') 1178*6881a400Schristos { 1179*6881a400Schristos lex (); 1180*6881a400Schristos operation_up rhs = parse_expr (); 1181*6881a400Schristos result = make_operation<rust_array_operation> (std::move (expr), 1182*6881a400Schristos std::move (rhs)); 1183*6881a400Schristos } 1184*6881a400Schristos else if (current_token == ',') 1185*6881a400Schristos { 1186*6881a400Schristos std::vector<operation_up> ops; 1187*6881a400Schristos ops.push_back (std::move (expr)); 1188*6881a400Schristos while (current_token != ']') 1189*6881a400Schristos { 1190*6881a400Schristos if (current_token != ',') 1191*6881a400Schristos error (_("',' or ']' expected")); 1192*6881a400Schristos lex (); 1193*6881a400Schristos ops.push_back (parse_expr ()); 1194*6881a400Schristos } 1195*6881a400Schristos ops.shrink_to_fit (); 1196*6881a400Schristos int len = ops.size () - 1; 1197*6881a400Schristos result = make_operation<array_operation> (0, len, std::move (ops)); 1198*6881a400Schristos } 1199*6881a400Schristos else if (current_token != ']') 1200*6881a400Schristos error (_("',', ';', or ']' expected")); 1201*6881a400Schristos 1202*6881a400Schristos require (']'); 1203*6881a400Schristos 1204*6881a400Schristos return result; 1205*6881a400Schristos } 1206*6881a400Schristos 1207*6881a400Schristos /* Turn a name into an operation. */ 1208*6881a400Schristos 1209*6881a400Schristos operation_up 1210*6881a400Schristos rust_parser::name_to_operation (const std::string &name) 1211*6881a400Schristos { 1212*6881a400Schristos struct block_symbol sym = lookup_symbol (name.c_str (), 1213*6881a400Schristos pstate->expression_context_block, 1214*6881a400Schristos VAR_DOMAIN); 1215*6881a400Schristos if (sym.symbol != nullptr && sym.symbol->aclass () != LOC_TYPEDEF) 1216*6881a400Schristos return make_operation<var_value_operation> (sym); 1217*6881a400Schristos 1218*6881a400Schristos struct type *type = nullptr; 1219*6881a400Schristos 1220*6881a400Schristos if (sym.symbol != nullptr) 1221*6881a400Schristos { 1222*6881a400Schristos gdb_assert (sym.symbol->aclass () == LOC_TYPEDEF); 1223*6881a400Schristos type = sym.symbol->type (); 1224*6881a400Schristos } 1225*6881a400Schristos if (type == nullptr) 1226*6881a400Schristos type = rust_lookup_type (name.c_str ()); 1227*6881a400Schristos if (type == nullptr) 1228*6881a400Schristos error (_("No symbol '%s' in current context"), name.c_str ()); 1229*6881a400Schristos 1230*6881a400Schristos if (type->code () == TYPE_CODE_STRUCT && type->num_fields () == 0) 1231*6881a400Schristos { 1232*6881a400Schristos /* A unit-like struct. */ 1233*6881a400Schristos operation_up result (new rust_aggregate_operation (type, {}, {})); 1234*6881a400Schristos return result; 1235*6881a400Schristos } 1236*6881a400Schristos else 1237*6881a400Schristos return make_operation<type_operation> (type); 1238*6881a400Schristos } 1239*6881a400Schristos 1240*6881a400Schristos /* Parse a struct expression. */ 1241*6881a400Schristos 1242*6881a400Schristos operation_up 1243*6881a400Schristos rust_parser::parse_struct_expr (struct type *type) 1244*6881a400Schristos { 1245*6881a400Schristos assume ('{'); 1246*6881a400Schristos 1247*6881a400Schristos if (type->code () != TYPE_CODE_STRUCT 1248*6881a400Schristos || rust_tuple_type_p (type) 1249*6881a400Schristos || rust_tuple_struct_type_p (type)) 1250*6881a400Schristos error (_("Struct expression applied to non-struct type")); 1251*6881a400Schristos 1252*6881a400Schristos std::vector<std::pair<std::string, operation_up>> field_v; 1253*6881a400Schristos while (current_token != '}' && current_token != DOTDOT) 1254*6881a400Schristos { 1255*6881a400Schristos if (current_token != IDENT) 1256*6881a400Schristos error (_("'}', '..', or identifier expected")); 1257*6881a400Schristos 1258*6881a400Schristos std::string name = get_string (); 1259*6881a400Schristos lex (); 1260*6881a400Schristos 1261*6881a400Schristos operation_up expr; 1262*6881a400Schristos if (current_token == ',' || current_token == '}' 1263*6881a400Schristos || current_token == DOTDOT) 1264*6881a400Schristos expr = name_to_operation (name); 1265*6881a400Schristos else 1266*6881a400Schristos { 1267*6881a400Schristos require (':'); 1268*6881a400Schristos expr = parse_expr (); 1269*6881a400Schristos } 1270*6881a400Schristos field_v.emplace_back (std::move (name), std::move (expr)); 1271*6881a400Schristos 1272*6881a400Schristos /* A trailing "," is ok. */ 1273*6881a400Schristos if (current_token == ',') 1274*6881a400Schristos lex (); 1275*6881a400Schristos } 1276*6881a400Schristos 1277*6881a400Schristos operation_up others; 1278*6881a400Schristos if (current_token == DOTDOT) 1279*6881a400Schristos { 1280*6881a400Schristos lex (); 1281*6881a400Schristos others = parse_expr (); 1282*6881a400Schristos } 1283*6881a400Schristos 1284*6881a400Schristos require ('}'); 1285*6881a400Schristos 1286*6881a400Schristos return make_operation<rust_aggregate_operation> (type, 1287*6881a400Schristos std::move (others), 1288*6881a400Schristos std::move (field_v)); 1289*6881a400Schristos } 1290*6881a400Schristos 1291*6881a400Schristos /* Used by the operator precedence parser. */ 1292*6881a400Schristos struct rustop_item 1293*6881a400Schristos { 1294*6881a400Schristos rustop_item (int token_, int precedence_, enum exp_opcode opcode_, 1295*6881a400Schristos operation_up &&op_) 1296*6881a400Schristos : token (token_), 1297*6881a400Schristos precedence (precedence_), 1298*6881a400Schristos opcode (opcode_), 1299*6881a400Schristos op (std::move (op_)) 1300*6881a400Schristos { 1301*6881a400Schristos } 1302*6881a400Schristos 1303*6881a400Schristos /* The token value. */ 1304*6881a400Schristos int token; 1305*6881a400Schristos /* Precedence of this operator. */ 1306*6881a400Schristos int precedence; 1307*6881a400Schristos /* This is used only for assign-modify. */ 1308*6881a400Schristos enum exp_opcode opcode; 1309*6881a400Schristos /* The right hand side of this operation. */ 1310*6881a400Schristos operation_up op; 1311*6881a400Schristos }; 1312*6881a400Schristos 1313*6881a400Schristos /* An operator precedence parser for binary operations, including 1314*6881a400Schristos "as". */ 1315*6881a400Schristos 1316*6881a400Schristos operation_up 1317*6881a400Schristos rust_parser::parse_binop (bool required) 1318*6881a400Schristos { 1319*6881a400Schristos /* All the binary operators. Each one is of the form 1320*6881a400Schristos OPERATION(TOKEN, PRECEDENCE, TYPE) 1321*6881a400Schristos TOKEN is the corresponding operator token. 1322*6881a400Schristos PRECEDENCE is a value indicating relative precedence. 1323*6881a400Schristos TYPE is the operation type corresponding to the operator. 1324*6881a400Schristos Assignment operations are handled specially, not via this 1325*6881a400Schristos table; they have precedence 0. */ 1326*6881a400Schristos #define ALL_OPS \ 1327*6881a400Schristos OPERATION ('*', 10, mul_operation) \ 1328*6881a400Schristos OPERATION ('/', 10, div_operation) \ 1329*6881a400Schristos OPERATION ('%', 10, rem_operation) \ 1330*6881a400Schristos OPERATION ('@', 9, repeat_operation) \ 1331*6881a400Schristos OPERATION ('+', 8, add_operation) \ 1332*6881a400Schristos OPERATION ('-', 8, sub_operation) \ 1333*6881a400Schristos OPERATION (LSH, 7, lsh_operation) \ 1334*6881a400Schristos OPERATION (RSH, 7, rsh_operation) \ 1335*6881a400Schristos OPERATION ('&', 6, bitwise_and_operation) \ 1336*6881a400Schristos OPERATION ('^', 5, bitwise_xor_operation) \ 1337*6881a400Schristos OPERATION ('|', 4, bitwise_ior_operation) \ 1338*6881a400Schristos OPERATION (EQEQ, 3, equal_operation) \ 1339*6881a400Schristos OPERATION (NOTEQ, 3, notequal_operation) \ 1340*6881a400Schristos OPERATION ('<', 3, less_operation) \ 1341*6881a400Schristos OPERATION (LTEQ, 3, leq_operation) \ 1342*6881a400Schristos OPERATION ('>', 3, gtr_operation) \ 1343*6881a400Schristos OPERATION (GTEQ, 3, geq_operation) \ 1344*6881a400Schristos OPERATION (ANDAND, 2, logical_and_operation) \ 1345*6881a400Schristos OPERATION (OROR, 1, logical_or_operation) 1346*6881a400Schristos 1347*6881a400Schristos #define ASSIGN_PREC 0 1348*6881a400Schristos 1349*6881a400Schristos operation_up start = parse_atom (required); 1350*6881a400Schristos if (start == nullptr) 1351*6881a400Schristos { 1352*6881a400Schristos gdb_assert (!required); 1353*6881a400Schristos return start; 1354*6881a400Schristos } 1355*6881a400Schristos 1356*6881a400Schristos std::vector<rustop_item> operator_stack; 1357*6881a400Schristos operator_stack.emplace_back (0, -1, OP_NULL, std::move (start)); 1358*6881a400Schristos 1359*6881a400Schristos while (true) 1360*6881a400Schristos { 1361*6881a400Schristos int this_token = current_token; 1362*6881a400Schristos enum exp_opcode compound_assign_op = OP_NULL; 1363*6881a400Schristos int precedence = -2; 1364*6881a400Schristos 1365*6881a400Schristos switch (this_token) 1366*6881a400Schristos { 1367*6881a400Schristos #define OPERATION(TOKEN, PRECEDENCE, TYPE) \ 1368*6881a400Schristos case TOKEN: \ 1369*6881a400Schristos precedence = PRECEDENCE; \ 1370*6881a400Schristos lex (); \ 1371*6881a400Schristos break; 1372*6881a400Schristos 1373*6881a400Schristos ALL_OPS 1374*6881a400Schristos 1375*6881a400Schristos #undef OPERATION 1376*6881a400Schristos 1377*6881a400Schristos case COMPOUND_ASSIGN: 1378*6881a400Schristos compound_assign_op = current_opcode; 1379*6881a400Schristos /* FALLTHROUGH */ 1380*6881a400Schristos case '=': 1381*6881a400Schristos precedence = ASSIGN_PREC; 1382*6881a400Schristos lex (); 1383*6881a400Schristos break; 1384*6881a400Schristos 1385*6881a400Schristos /* "as" must be handled specially. */ 1386*6881a400Schristos case KW_AS: 1387*6881a400Schristos { 1388*6881a400Schristos lex (); 1389*6881a400Schristos rustop_item &lhs = operator_stack.back (); 1390*6881a400Schristos struct type *type = parse_type (); 1391*6881a400Schristos lhs.op = make_operation<unop_cast_operation> (std::move (lhs.op), 1392*6881a400Schristos type); 1393*6881a400Schristos } 1394*6881a400Schristos /* Bypass the rest of the loop. */ 1395*6881a400Schristos continue; 1396*6881a400Schristos 1397*6881a400Schristos default: 1398*6881a400Schristos /* Arrange to pop the entire stack. */ 1399*6881a400Schristos precedence = -2; 1400*6881a400Schristos break; 1401*6881a400Schristos } 1402*6881a400Schristos 1403*6881a400Schristos /* Make sure that assignments are right-associative while other 1404*6881a400Schristos operations are left-associative. */ 1405*6881a400Schristos while ((precedence == ASSIGN_PREC 1406*6881a400Schristos ? precedence < operator_stack.back ().precedence 1407*6881a400Schristos : precedence <= operator_stack.back ().precedence) 1408*6881a400Schristos && operator_stack.size () > 1) 1409*6881a400Schristos { 1410*6881a400Schristos rustop_item rhs = std::move (operator_stack.back ()); 1411*6881a400Schristos operator_stack.pop_back (); 1412*6881a400Schristos 1413*6881a400Schristos rustop_item &lhs = operator_stack.back (); 1414*6881a400Schristos 1415*6881a400Schristos switch (rhs.token) 1416*6881a400Schristos { 1417*6881a400Schristos #define OPERATION(TOKEN, PRECEDENCE, TYPE) \ 1418*6881a400Schristos case TOKEN: \ 1419*6881a400Schristos lhs.op = make_operation<TYPE> (std::move (lhs.op), \ 1420*6881a400Schristos std::move (rhs.op)); \ 1421*6881a400Schristos break; 1422*6881a400Schristos 1423*6881a400Schristos ALL_OPS 1424*6881a400Schristos 1425*6881a400Schristos #undef OPERATION 1426*6881a400Schristos 1427*6881a400Schristos case '=': 1428*6881a400Schristos case COMPOUND_ASSIGN: 1429*6881a400Schristos { 1430*6881a400Schristos if (rhs.token == '=') 1431*6881a400Schristos lhs.op = (make_operation<assign_operation> 1432*6881a400Schristos (std::move (lhs.op), std::move (rhs.op))); 1433*6881a400Schristos else 1434*6881a400Schristos lhs.op = (make_operation<assign_modify_operation> 1435*6881a400Schristos (rhs.opcode, std::move (lhs.op), 1436*6881a400Schristos std::move (rhs.op))); 1437*6881a400Schristos 1438*6881a400Schristos struct type *unit_type = get_type ("()"); 1439*6881a400Schristos 1440*6881a400Schristos operation_up nil (new long_const_operation (unit_type, 0)); 1441*6881a400Schristos lhs.op = (make_operation<comma_operation> 1442*6881a400Schristos (std::move (lhs.op), std::move (nil))); 1443*6881a400Schristos } 1444*6881a400Schristos break; 1445*6881a400Schristos 1446*6881a400Schristos default: 1447*6881a400Schristos gdb_assert_not_reached ("bad binary operator"); 1448*6881a400Schristos } 1449*6881a400Schristos } 1450*6881a400Schristos 1451*6881a400Schristos if (precedence == -2) 1452*6881a400Schristos break; 1453*6881a400Schristos 1454*6881a400Schristos operator_stack.emplace_back (this_token, precedence, compound_assign_op, 1455*6881a400Schristos parse_atom (true)); 1456*6881a400Schristos } 1457*6881a400Schristos 1458*6881a400Schristos gdb_assert (operator_stack.size () == 1); 1459*6881a400Schristos return std::move (operator_stack[0].op); 1460*6881a400Schristos #undef ALL_OPS 1461*6881a400Schristos } 1462*6881a400Schristos 1463*6881a400Schristos /* Parse a range expression. */ 1464*6881a400Schristos 1465*6881a400Schristos operation_up 1466*6881a400Schristos rust_parser::parse_range () 1467*6881a400Schristos { 1468*6881a400Schristos enum range_flag kind = (RANGE_HIGH_BOUND_DEFAULT 1469*6881a400Schristos | RANGE_LOW_BOUND_DEFAULT); 1470*6881a400Schristos 1471*6881a400Schristos operation_up lhs; 1472*6881a400Schristos if (current_token != DOTDOT && current_token != DOTDOTEQ) 1473*6881a400Schristos { 1474*6881a400Schristos lhs = parse_binop (true); 1475*6881a400Schristos kind &= ~RANGE_LOW_BOUND_DEFAULT; 1476*6881a400Schristos } 1477*6881a400Schristos 1478*6881a400Schristos if (current_token == DOTDOT) 1479*6881a400Schristos kind |= RANGE_HIGH_BOUND_EXCLUSIVE; 1480*6881a400Schristos else if (current_token != DOTDOTEQ) 1481*6881a400Schristos return lhs; 1482*6881a400Schristos lex (); 1483*6881a400Schristos 1484*6881a400Schristos /* A "..=" range requires a high bound, but otherwise it is 1485*6881a400Schristos optional. */ 1486*6881a400Schristos operation_up rhs = parse_binop ((kind & RANGE_HIGH_BOUND_EXCLUSIVE) == 0); 1487*6881a400Schristos if (rhs != nullptr) 1488*6881a400Schristos kind &= ~RANGE_HIGH_BOUND_DEFAULT; 1489*6881a400Schristos 1490*6881a400Schristos return make_operation<rust_range_operation> (kind, 1491*6881a400Schristos std::move (lhs), 1492*6881a400Schristos std::move (rhs)); 1493*6881a400Schristos } 1494*6881a400Schristos 1495*6881a400Schristos /* Parse an expression. */ 1496*6881a400Schristos 1497*6881a400Schristos operation_up 1498*6881a400Schristos rust_parser::parse_expr () 1499*6881a400Schristos { 1500*6881a400Schristos return parse_range (); 1501*6881a400Schristos } 1502*6881a400Schristos 1503*6881a400Schristos /* Parse a sizeof expression. */ 1504*6881a400Schristos 1505*6881a400Schristos operation_up 1506*6881a400Schristos rust_parser::parse_sizeof () 1507*6881a400Schristos { 1508*6881a400Schristos assume (KW_SIZEOF); 1509*6881a400Schristos 1510*6881a400Schristos require ('('); 1511*6881a400Schristos operation_up result = make_operation<unop_sizeof_operation> (parse_expr ()); 1512*6881a400Schristos require (')'); 1513*6881a400Schristos return result; 1514*6881a400Schristos } 1515*6881a400Schristos 1516*6881a400Schristos /* Parse an address-of operation. */ 1517*6881a400Schristos 1518*6881a400Schristos operation_up 1519*6881a400Schristos rust_parser::parse_addr () 1520*6881a400Schristos { 1521*6881a400Schristos assume ('&'); 1522*6881a400Schristos 1523*6881a400Schristos if (current_token == KW_MUT) 1524*6881a400Schristos lex (); 1525*6881a400Schristos 1526*6881a400Schristos return make_operation<rust_unop_addr_operation> (parse_atom (true)); 1527*6881a400Schristos } 1528*6881a400Schristos 1529*6881a400Schristos /* Parse a field expression. */ 1530*6881a400Schristos 1531*6881a400Schristos operation_up 1532*6881a400Schristos rust_parser::parse_field (operation_up &&lhs) 1533*6881a400Schristos { 1534*6881a400Schristos assume ('.'); 1535*6881a400Schristos 1536*6881a400Schristos operation_up result; 1537*6881a400Schristos switch (current_token) 1538*6881a400Schristos { 1539*6881a400Schristos case IDENT: 1540*6881a400Schristos case COMPLETE: 1541*6881a400Schristos { 1542*6881a400Schristos bool is_complete = current_token == COMPLETE; 1543*6881a400Schristos auto struct_op = new rust_structop (std::move (lhs), get_string ()); 1544*6881a400Schristos lex (); 1545*6881a400Schristos if (is_complete) 1546*6881a400Schristos { 1547*6881a400Schristos completion_op.reset (struct_op); 1548*6881a400Schristos pstate->mark_struct_expression (struct_op); 1549*6881a400Schristos /* Throw to the outermost level of the parser. */ 1550*6881a400Schristos error (_("not really an error")); 1551*6881a400Schristos } 1552*6881a400Schristos result.reset (struct_op); 1553*6881a400Schristos } 1554*6881a400Schristos break; 1555*6881a400Schristos 1556*6881a400Schristos case DECIMAL_INTEGER: 1557*6881a400Schristos result = make_operation<rust_struct_anon> (current_int_val.val, 1558*6881a400Schristos std::move (lhs)); 1559*6881a400Schristos lex (); 1560*6881a400Schristos break; 1561*6881a400Schristos 1562*6881a400Schristos case INTEGER: 1563*6881a400Schristos error (_("'_' not allowed in integers in anonymous field references")); 1564*6881a400Schristos 1565*6881a400Schristos default: 1566*6881a400Schristos error (_("field name expected")); 1567*6881a400Schristos } 1568*6881a400Schristos 1569*6881a400Schristos return result; 1570*6881a400Schristos } 1571*6881a400Schristos 1572*6881a400Schristos /* Parse an index expression. */ 1573*6881a400Schristos 1574*6881a400Schristos operation_up 1575*6881a400Schristos rust_parser::parse_index (operation_up &&lhs) 1576*6881a400Schristos { 1577*6881a400Schristos assume ('['); 1578*6881a400Schristos operation_up rhs = parse_expr (); 1579*6881a400Schristos require (']'); 1580*6881a400Schristos 1581*6881a400Schristos return make_operation<rust_subscript_operation> (std::move (lhs), 1582*6881a400Schristos std::move (rhs)); 1583*6881a400Schristos } 1584*6881a400Schristos 1585*6881a400Schristos /* Parse a sequence of comma-separated expressions in parens. */ 1586*6881a400Schristos 1587*6881a400Schristos std::vector<operation_up> 1588*6881a400Schristos rust_parser::parse_paren_args () 1589*6881a400Schristos { 1590*6881a400Schristos assume ('('); 1591*6881a400Schristos 1592*6881a400Schristos std::vector<operation_up> args; 1593*6881a400Schristos while (current_token != ')') 1594*6881a400Schristos { 1595*6881a400Schristos if (!args.empty ()) 1596*6881a400Schristos { 1597*6881a400Schristos if (current_token != ',') 1598*6881a400Schristos error (_("',' or ')' expected")); 1599*6881a400Schristos lex (); 1600*6881a400Schristos } 1601*6881a400Schristos 1602*6881a400Schristos args.push_back (parse_expr ()); 1603*6881a400Schristos } 1604*6881a400Schristos 1605*6881a400Schristos assume (')'); 1606*6881a400Schristos 1607*6881a400Schristos return args; 1608*6881a400Schristos } 1609*6881a400Schristos 1610*6881a400Schristos /* Parse the parenthesized part of a function call. */ 1611*6881a400Schristos 1612*6881a400Schristos operation_up 1613*6881a400Schristos rust_parser::parse_call (operation_up &&lhs) 1614*6881a400Schristos { 1615*6881a400Schristos std::vector<operation_up> args = parse_paren_args (); 1616*6881a400Schristos 1617*6881a400Schristos return make_operation<funcall_operation> (std::move (lhs), 1618*6881a400Schristos std::move (args)); 1619*6881a400Schristos } 1620*6881a400Schristos 1621*6881a400Schristos /* Parse a list of types. */ 1622*6881a400Schristos 1623*6881a400Schristos std::vector<struct type *> 1624*6881a400Schristos rust_parser::parse_type_list () 1625*6881a400Schristos { 1626*6881a400Schristos std::vector<struct type *> result; 1627*6881a400Schristos result.push_back (parse_type ()); 1628*6881a400Schristos while (current_token == ',') 1629*6881a400Schristos { 1630*6881a400Schristos lex (); 1631*6881a400Schristos result.push_back (parse_type ()); 1632*6881a400Schristos } 1633*6881a400Schristos return result; 1634*6881a400Schristos } 1635*6881a400Schristos 1636*6881a400Schristos /* Parse a possibly-empty list of types, surrounded in parens. */ 1637*6881a400Schristos 1638*6881a400Schristos std::vector<struct type *> 1639*6881a400Schristos rust_parser::parse_maybe_type_list () 1640*6881a400Schristos { 1641*6881a400Schristos assume ('('); 1642*6881a400Schristos std::vector<struct type *> types; 1643*6881a400Schristos if (current_token != ')') 1644*6881a400Schristos types = parse_type_list (); 1645*6881a400Schristos require (')'); 1646*6881a400Schristos return types; 1647*6881a400Schristos } 1648*6881a400Schristos 1649*6881a400Schristos /* Parse an array type. */ 1650*6881a400Schristos 1651*6881a400Schristos struct type * 1652*6881a400Schristos rust_parser::parse_array_type () 1653*6881a400Schristos { 1654*6881a400Schristos assume ('['); 1655*6881a400Schristos struct type *elt_type = parse_type (); 1656*6881a400Schristos require (';'); 1657*6881a400Schristos 1658*6881a400Schristos if (current_token != INTEGER && current_token != DECIMAL_INTEGER) 1659*6881a400Schristos error (_("integer expected")); 1660*6881a400Schristos ULONGEST val = current_int_val.val; 1661*6881a400Schristos lex (); 1662*6881a400Schristos require (']'); 1663*6881a400Schristos 1664*6881a400Schristos return lookup_array_range_type (elt_type, 0, val - 1); 1665*6881a400Schristos } 1666*6881a400Schristos 1667*6881a400Schristos /* Parse a slice type. */ 1668*6881a400Schristos 1669*6881a400Schristos struct type * 1670*6881a400Schristos rust_parser::parse_slice_type () 1671*6881a400Schristos { 1672*6881a400Schristos assume ('&'); 1673*6881a400Schristos 1674*6881a400Schristos bool is_slice = current_token == '['; 1675*6881a400Schristos if (is_slice) 1676*6881a400Schristos lex (); 1677*6881a400Schristos 1678*6881a400Schristos struct type *target = parse_type (); 1679*6881a400Schristos 1680*6881a400Schristos if (is_slice) 1681*6881a400Schristos { 1682*6881a400Schristos require (']'); 1683*6881a400Schristos return rust_slice_type ("&[*gdb*]", target, get_type ("usize")); 1684*6881a400Schristos } 1685*6881a400Schristos 1686*6881a400Schristos /* For now we treat &x and *x identically. */ 1687*6881a400Schristos return lookup_pointer_type (target); 1688*6881a400Schristos } 1689*6881a400Schristos 1690*6881a400Schristos /* Parse a pointer type. */ 1691*6881a400Schristos 1692*6881a400Schristos struct type * 1693*6881a400Schristos rust_parser::parse_pointer_type () 1694*6881a400Schristos { 1695*6881a400Schristos assume ('*'); 1696*6881a400Schristos 1697*6881a400Schristos if (current_token == KW_MUT || current_token == KW_CONST) 1698*6881a400Schristos lex (); 1699*6881a400Schristos 1700*6881a400Schristos struct type *target = parse_type (); 1701*6881a400Schristos /* For the time being we ignore mut/const. */ 1702*6881a400Schristos return lookup_pointer_type (target); 1703*6881a400Schristos } 1704*6881a400Schristos 1705*6881a400Schristos /* Parse a function type. */ 1706*6881a400Schristos 1707*6881a400Schristos struct type * 1708*6881a400Schristos rust_parser::parse_function_type () 1709*6881a400Schristos { 1710*6881a400Schristos assume (KW_FN); 1711*6881a400Schristos 1712*6881a400Schristos if (current_token != '(') 1713*6881a400Schristos error (_("'(' expected")); 1714*6881a400Schristos 1715*6881a400Schristos std::vector<struct type *> types = parse_maybe_type_list (); 1716*6881a400Schristos 1717*6881a400Schristos if (current_token != ARROW) 1718*6881a400Schristos error (_("'->' expected")); 1719*6881a400Schristos lex (); 1720*6881a400Schristos 1721*6881a400Schristos struct type *result_type = parse_type (); 1722*6881a400Schristos 1723*6881a400Schristos struct type **argtypes = nullptr; 1724*6881a400Schristos if (!types.empty ()) 1725*6881a400Schristos argtypes = types.data (); 1726*6881a400Schristos 1727*6881a400Schristos result_type = lookup_function_type_with_arguments (result_type, 1728*6881a400Schristos types.size (), 1729*6881a400Schristos argtypes); 1730*6881a400Schristos return lookup_pointer_type (result_type); 1731*6881a400Schristos } 1732*6881a400Schristos 1733*6881a400Schristos /* Parse a tuple type. */ 1734*6881a400Schristos 1735*6881a400Schristos struct type * 1736*6881a400Schristos rust_parser::parse_tuple_type () 1737*6881a400Schristos { 1738*6881a400Schristos std::vector<struct type *> types = parse_maybe_type_list (); 1739*6881a400Schristos 1740*6881a400Schristos auto_obstack obstack; 1741*6881a400Schristos obstack_1grow (&obstack, '('); 1742*6881a400Schristos for (int i = 0; i < types.size (); ++i) 1743*6881a400Schristos { 1744*6881a400Schristos std::string type_name = type_to_string (types[i]); 1745*6881a400Schristos 1746*6881a400Schristos if (i > 0) 1747*6881a400Schristos obstack_1grow (&obstack, ','); 1748*6881a400Schristos obstack_grow_str (&obstack, type_name.c_str ()); 1749*6881a400Schristos } 1750*6881a400Schristos 1751*6881a400Schristos obstack_grow_str0 (&obstack, ")"); 1752*6881a400Schristos const char *name = (const char *) obstack_finish (&obstack); 1753*6881a400Schristos 1754*6881a400Schristos /* We don't allow creating new tuple types (yet), but we do allow 1755*6881a400Schristos looking up existing tuple types. */ 1756*6881a400Schristos struct type *result = rust_lookup_type (name); 1757*6881a400Schristos if (result == nullptr) 1758*6881a400Schristos error (_("could not find tuple type '%s'"), name); 1759*6881a400Schristos 1760*6881a400Schristos return result; 1761*6881a400Schristos } 1762*6881a400Schristos 1763*6881a400Schristos /* Parse a type. */ 1764*6881a400Schristos 1765*6881a400Schristos struct type * 1766*6881a400Schristos rust_parser::parse_type () 1767*6881a400Schristos { 1768*6881a400Schristos switch (current_token) 1769*6881a400Schristos { 1770*6881a400Schristos case '[': 1771*6881a400Schristos return parse_array_type (); 1772*6881a400Schristos case '&': 1773*6881a400Schristos return parse_slice_type (); 1774*6881a400Schristos case '*': 1775*6881a400Schristos return parse_pointer_type (); 1776*6881a400Schristos case KW_FN: 1777*6881a400Schristos return parse_function_type (); 1778*6881a400Schristos case '(': 1779*6881a400Schristos return parse_tuple_type (); 1780*6881a400Schristos case KW_SELF: 1781*6881a400Schristos case KW_SUPER: 1782*6881a400Schristos case COLONCOLON: 1783*6881a400Schristos case KW_EXTERN: 1784*6881a400Schristos case IDENT: 1785*6881a400Schristos { 1786*6881a400Schristos std::string path = parse_path (false); 1787*6881a400Schristos struct type *result = rust_lookup_type (path.c_str ()); 1788*6881a400Schristos if (result == nullptr) 1789*6881a400Schristos error (_("No type name '%s' in current context"), path.c_str ()); 1790*6881a400Schristos return result; 1791*6881a400Schristos } 1792*6881a400Schristos default: 1793*6881a400Schristos error (_("type expected")); 1794*6881a400Schristos } 1795*6881a400Schristos } 1796*6881a400Schristos 1797*6881a400Schristos /* Parse a path. */ 1798*6881a400Schristos 1799*6881a400Schristos std::string 1800*6881a400Schristos rust_parser::parse_path (bool for_expr) 1801*6881a400Schristos { 1802*6881a400Schristos unsigned n_supers = 0; 1803*6881a400Schristos int first_token = current_token; 1804*6881a400Schristos 1805*6881a400Schristos switch (current_token) 1806*6881a400Schristos { 1807*6881a400Schristos case KW_SELF: 1808*6881a400Schristos lex (); 1809*6881a400Schristos if (current_token != COLONCOLON) 1810*6881a400Schristos return "self"; 1811*6881a400Schristos lex (); 1812*6881a400Schristos /* FALLTHROUGH */ 1813*6881a400Schristos case KW_SUPER: 1814*6881a400Schristos while (current_token == KW_SUPER) 1815*6881a400Schristos { 1816*6881a400Schristos ++n_supers; 1817*6881a400Schristos lex (); 1818*6881a400Schristos if (current_token != COLONCOLON) 1819*6881a400Schristos error (_("'::' expected")); 1820*6881a400Schristos lex (); 1821*6881a400Schristos } 1822*6881a400Schristos break; 1823*6881a400Schristos 1824*6881a400Schristos case COLONCOLON: 1825*6881a400Schristos lex (); 1826*6881a400Schristos break; 1827*6881a400Schristos 1828*6881a400Schristos case KW_EXTERN: 1829*6881a400Schristos /* This is a gdb extension to make it possible to refer to items 1830*6881a400Schristos in other crates. It just bypasses adding the current crate 1831*6881a400Schristos to the front of the name. */ 1832*6881a400Schristos lex (); 1833*6881a400Schristos break; 1834*6881a400Schristos } 1835*6881a400Schristos 1836*6881a400Schristos if (current_token != IDENT) 1837*6881a400Schristos error (_("identifier expected")); 1838*6881a400Schristos std::string path = get_string (); 1839*6881a400Schristos bool saw_ident = true; 1840*6881a400Schristos lex (); 1841*6881a400Schristos 1842*6881a400Schristos /* The condition here lets us enter the loop even if we see 1843*6881a400Schristos "ident<...>". */ 1844*6881a400Schristos while (current_token == COLONCOLON || current_token == '<') 1845*6881a400Schristos { 1846*6881a400Schristos if (current_token == COLONCOLON) 1847*6881a400Schristos { 1848*6881a400Schristos lex (); 1849*6881a400Schristos saw_ident = false; 1850*6881a400Schristos 1851*6881a400Schristos if (current_token == IDENT) 1852*6881a400Schristos { 1853*6881a400Schristos path = path + "::" + get_string (); 1854*6881a400Schristos lex (); 1855*6881a400Schristos saw_ident = true; 1856*6881a400Schristos } 1857*6881a400Schristos else if (current_token == COLONCOLON) 1858*6881a400Schristos { 1859*6881a400Schristos /* The code below won't detect this scenario. */ 1860*6881a400Schristos error (_("unexpected '::'")); 1861*6881a400Schristos } 1862*6881a400Schristos } 1863*6881a400Schristos 1864*6881a400Schristos if (current_token != '<') 1865*6881a400Schristos continue; 1866*6881a400Schristos 1867*6881a400Schristos /* Expression use name::<...>, whereas types use name<...>. */ 1868*6881a400Schristos if (for_expr) 1869*6881a400Schristos { 1870*6881a400Schristos /* Expressions use "name::<...>", so if we saw an identifier 1871*6881a400Schristos after the "::", we ignore the "<" here. */ 1872*6881a400Schristos if (saw_ident) 1873*6881a400Schristos break; 1874*6881a400Schristos } 1875*6881a400Schristos else 1876*6881a400Schristos { 1877*6881a400Schristos /* Types use "name<...>", so we need to have seen the 1878*6881a400Schristos identifier. */ 1879*6881a400Schristos if (!saw_ident) 1880*6881a400Schristos break; 1881*6881a400Schristos } 1882*6881a400Schristos 1883*6881a400Schristos lex (); 1884*6881a400Schristos std::vector<struct type *> types = parse_type_list (); 1885*6881a400Schristos if (current_token == '>') 1886*6881a400Schristos lex (); 1887*6881a400Schristos else if (current_token == RSH) 1888*6881a400Schristos { 1889*6881a400Schristos push_back ('>'); 1890*6881a400Schristos lex (); 1891*6881a400Schristos } 1892*6881a400Schristos else 1893*6881a400Schristos error (_("'>' expected")); 1894*6881a400Schristos 1895*6881a400Schristos path += "<"; 1896*6881a400Schristos for (int i = 0; i < types.size (); ++i) 1897*6881a400Schristos { 1898*6881a400Schristos if (i > 0) 1899*6881a400Schristos path += ","; 1900*6881a400Schristos path += type_to_string (types[i]); 1901*6881a400Schristos } 1902*6881a400Schristos path += ">"; 1903*6881a400Schristos break; 1904*6881a400Schristos } 1905*6881a400Schristos 1906*6881a400Schristos switch (first_token) 1907*6881a400Schristos { 1908*6881a400Schristos case KW_SELF: 1909*6881a400Schristos case KW_SUPER: 1910*6881a400Schristos return super_name (path, n_supers); 1911*6881a400Schristos 1912*6881a400Schristos case COLONCOLON: 1913*6881a400Schristos return crate_name (path); 1914*6881a400Schristos 1915*6881a400Schristos case KW_EXTERN: 1916*6881a400Schristos return "::" + path; 1917*6881a400Schristos 1918*6881a400Schristos case IDENT: 1919*6881a400Schristos return path; 1920*6881a400Schristos 1921*6881a400Schristos default: 1922*6881a400Schristos gdb_assert_not_reached ("missing case in path parsing"); 1923*6881a400Schristos } 1924*6881a400Schristos } 1925*6881a400Schristos 1926*6881a400Schristos /* Handle the parsing for a string expression. */ 1927*6881a400Schristos 1928*6881a400Schristos operation_up 1929*6881a400Schristos rust_parser::parse_string () 1930*6881a400Schristos { 1931*6881a400Schristos gdb_assert (current_token == STRING); 1932*6881a400Schristos 1933*6881a400Schristos /* Wrap the raw string in the &str struct. */ 1934*6881a400Schristos struct type *type = rust_lookup_type ("&str"); 1935*6881a400Schristos if (type == nullptr) 1936*6881a400Schristos error (_("Could not find type '&str'")); 1937*6881a400Schristos 1938*6881a400Schristos std::vector<std::pair<std::string, operation_up>> field_v; 1939*6881a400Schristos 1940*6881a400Schristos size_t len = current_string_val.length; 1941*6881a400Schristos operation_up str = make_operation<string_operation> (get_string ()); 1942*6881a400Schristos operation_up addr 1943*6881a400Schristos = make_operation<rust_unop_addr_operation> (std::move (str)); 1944*6881a400Schristos field_v.emplace_back ("data_ptr", std::move (addr)); 1945*6881a400Schristos 1946*6881a400Schristos struct type *valtype = get_type ("usize"); 1947*6881a400Schristos operation_up lenop = make_operation<long_const_operation> (valtype, len); 1948*6881a400Schristos field_v.emplace_back ("length", std::move (lenop)); 1949*6881a400Schristos 1950*6881a400Schristos return make_operation<rust_aggregate_operation> (type, 1951*6881a400Schristos operation_up (), 1952*6881a400Schristos std::move (field_v)); 1953*6881a400Schristos } 1954*6881a400Schristos 1955*6881a400Schristos /* Parse a tuple struct expression. */ 1956*6881a400Schristos 1957*6881a400Schristos operation_up 1958*6881a400Schristos rust_parser::parse_tuple_struct (struct type *type) 1959*6881a400Schristos { 1960*6881a400Schristos std::vector<operation_up> args = parse_paren_args (); 1961*6881a400Schristos 1962*6881a400Schristos std::vector<std::pair<std::string, operation_up>> field_v (args.size ()); 1963*6881a400Schristos for (int i = 0; i < args.size (); ++i) 1964*6881a400Schristos field_v[i] = { string_printf ("__%d", i), std::move (args[i]) }; 1965*6881a400Schristos 1966*6881a400Schristos return (make_operation<rust_aggregate_operation> 1967*6881a400Schristos (type, operation_up (), std::move (field_v))); 1968*6881a400Schristos } 1969*6881a400Schristos 1970*6881a400Schristos /* Parse a path expression. */ 1971*6881a400Schristos 1972*6881a400Schristos operation_up 1973*6881a400Schristos rust_parser::parse_path_expr () 1974*6881a400Schristos { 1975*6881a400Schristos std::string path = parse_path (true); 1976*6881a400Schristos 1977*6881a400Schristos if (current_token == '{') 1978*6881a400Schristos { 1979*6881a400Schristos struct type *type = rust_lookup_type (path.c_str ()); 1980*6881a400Schristos if (type == nullptr) 1981*6881a400Schristos error (_("Could not find type '%s'"), path.c_str ()); 1982*6881a400Schristos 1983*6881a400Schristos return parse_struct_expr (type); 1984*6881a400Schristos } 1985*6881a400Schristos else if (current_token == '(') 1986*6881a400Schristos { 1987*6881a400Schristos struct type *type = rust_lookup_type (path.c_str ()); 1988*6881a400Schristos /* If this is actually a tuple struct expression, handle it 1989*6881a400Schristos here. If it is a call, it will be handled elsewhere. */ 1990*6881a400Schristos if (type != nullptr) 1991*6881a400Schristos { 1992*6881a400Schristos if (!rust_tuple_struct_type_p (type)) 1993*6881a400Schristos error (_("Type %s is not a tuple struct"), path.c_str ()); 1994*6881a400Schristos return parse_tuple_struct (type); 1995*6881a400Schristos } 1996*6881a400Schristos } 1997*6881a400Schristos 1998*6881a400Schristos return name_to_operation (path); 1999*6881a400Schristos } 2000*6881a400Schristos 2001*6881a400Schristos /* Parse an atom. "Atom" isn't a Rust term, but this refers to a 2002*6881a400Schristos single unitary item in the grammar; but here including some unary 2003*6881a400Schristos prefix and postfix expressions. */ 2004*6881a400Schristos 2005*6881a400Schristos operation_up 2006*6881a400Schristos rust_parser::parse_atom (bool required) 2007*6881a400Schristos { 2008*6881a400Schristos operation_up result; 2009*6881a400Schristos 2010*6881a400Schristos switch (current_token) 2011*6881a400Schristos { 2012*6881a400Schristos case '(': 2013*6881a400Schristos result = parse_tuple (); 2014*6881a400Schristos break; 2015*6881a400Schristos 2016*6881a400Schristos case '[': 2017*6881a400Schristos result = parse_array (); 2018*6881a400Schristos break; 2019*6881a400Schristos 2020*6881a400Schristos case INTEGER: 2021*6881a400Schristos case DECIMAL_INTEGER: 2022*6881a400Schristos result = make_operation<long_const_operation> (current_int_val.type, 2023*6881a400Schristos current_int_val.val); 2024*6881a400Schristos lex (); 2025*6881a400Schristos break; 2026*6881a400Schristos 2027*6881a400Schristos case FLOAT: 2028*6881a400Schristos result = make_operation<float_const_operation> (current_float_val.type, 2029*6881a400Schristos current_float_val.val); 2030*6881a400Schristos lex (); 2031*6881a400Schristos break; 2032*6881a400Schristos 2033*6881a400Schristos case STRING: 2034*6881a400Schristos result = parse_string (); 2035*6881a400Schristos lex (); 2036*6881a400Schristos break; 2037*6881a400Schristos 2038*6881a400Schristos case BYTESTRING: 2039*6881a400Schristos result = make_operation<string_operation> (get_string ()); 2040*6881a400Schristos lex (); 2041*6881a400Schristos break; 2042*6881a400Schristos 2043*6881a400Schristos case KW_TRUE: 2044*6881a400Schristos case KW_FALSE: 2045*6881a400Schristos result = make_operation<bool_operation> (current_token == KW_TRUE); 2046*6881a400Schristos lex (); 2047*6881a400Schristos break; 2048*6881a400Schristos 2049*6881a400Schristos case GDBVAR: 2050*6881a400Schristos /* This is kind of a hacky approach. */ 2051*6881a400Schristos { 2052*6881a400Schristos pstate->push_dollar (current_string_val); 2053*6881a400Schristos result = pstate->pop (); 2054*6881a400Schristos lex (); 2055*6881a400Schristos } 2056*6881a400Schristos break; 2057*6881a400Schristos 2058*6881a400Schristos case KW_SELF: 2059*6881a400Schristos case KW_SUPER: 2060*6881a400Schristos case COLONCOLON: 2061*6881a400Schristos case KW_EXTERN: 2062*6881a400Schristos case IDENT: 2063*6881a400Schristos result = parse_path_expr (); 2064*6881a400Schristos break; 2065*6881a400Schristos 2066*6881a400Schristos case '*': 2067*6881a400Schristos lex (); 2068*6881a400Schristos result = make_operation<rust_unop_ind_operation> (parse_atom (true)); 2069*6881a400Schristos break; 2070*6881a400Schristos case '+': 2071*6881a400Schristos lex (); 2072*6881a400Schristos result = make_operation<unary_plus_operation> (parse_atom (true)); 2073*6881a400Schristos break; 2074*6881a400Schristos case '-': 2075*6881a400Schristos lex (); 2076*6881a400Schristos result = make_operation<unary_neg_operation> (parse_atom (true)); 2077*6881a400Schristos break; 2078*6881a400Schristos case '!': 2079*6881a400Schristos lex (); 2080*6881a400Schristos result = make_operation<rust_unop_compl_operation> (parse_atom (true)); 2081*6881a400Schristos break; 2082*6881a400Schristos case KW_SIZEOF: 2083*6881a400Schristos result = parse_sizeof (); 2084*6881a400Schristos break; 2085*6881a400Schristos case '&': 2086*6881a400Schristos result = parse_addr (); 2087*6881a400Schristos break; 2088*6881a400Schristos 2089*6881a400Schristos default: 2090*6881a400Schristos if (!required) 2091*6881a400Schristos return {}; 2092*6881a400Schristos error (_("unexpected token")); 2093*6881a400Schristos } 2094*6881a400Schristos 2095*6881a400Schristos /* Now parse suffixes. */ 2096*6881a400Schristos while (true) 2097*6881a400Schristos { 2098*6881a400Schristos switch (current_token) 2099*6881a400Schristos { 2100*6881a400Schristos case '.': 2101*6881a400Schristos result = parse_field (std::move (result)); 2102*6881a400Schristos break; 2103*6881a400Schristos 2104*6881a400Schristos case '[': 2105*6881a400Schristos result = parse_index (std::move (result)); 2106*6881a400Schristos break; 2107*6881a400Schristos 2108*6881a400Schristos case '(': 2109*6881a400Schristos result = parse_call (std::move (result)); 2110*6881a400Schristos break; 2111*6881a400Schristos 2112*6881a400Schristos default: 2113*6881a400Schristos return result; 2114*6881a400Schristos } 2115*6881a400Schristos } 2116*6881a400Schristos } 2117*6881a400Schristos 2118*6881a400Schristos 2119*6881a400Schristos 2120*6881a400Schristos /* The parser as exposed to gdb. */ 2121*6881a400Schristos 2122*6881a400Schristos int 2123*6881a400Schristos rust_language::parser (struct parser_state *state) const 2124*6881a400Schristos { 2125*6881a400Schristos rust_parser parser (state); 2126*6881a400Schristos 2127*6881a400Schristos operation_up result; 2128*6881a400Schristos try 2129*6881a400Schristos { 2130*6881a400Schristos result = parser.parse_entry_point (); 2131*6881a400Schristos } 2132*6881a400Schristos catch (const gdb_exception &exc) 2133*6881a400Schristos { 2134*6881a400Schristos if (state->parse_completion) 2135*6881a400Schristos { 2136*6881a400Schristos result = std::move (parser.completion_op); 2137*6881a400Schristos if (result == nullptr) 2138*6881a400Schristos throw; 2139*6881a400Schristos } 2140*6881a400Schristos else 2141*6881a400Schristos throw; 2142*6881a400Schristos } 2143*6881a400Schristos 2144*6881a400Schristos state->set_operation (std::move (result)); 2145*6881a400Schristos 2146*6881a400Schristos return 0; 2147*6881a400Schristos } 2148*6881a400Schristos 2149*6881a400Schristos 2150*6881a400Schristos 2151*6881a400Schristos #if GDB_SELF_TEST 2152*6881a400Schristos 2153*6881a400Schristos /* A test helper that lexes a string, expecting a single token. */ 2154*6881a400Schristos 2155*6881a400Schristos static void 2156*6881a400Schristos rust_lex_test_one (rust_parser *parser, const char *input, int expected) 2157*6881a400Schristos { 2158*6881a400Schristos int token; 2159*6881a400Schristos 2160*6881a400Schristos parser->reset (input); 2161*6881a400Schristos 2162*6881a400Schristos token = parser->lex_one_token (); 2163*6881a400Schristos SELF_CHECK (token == expected); 2164*6881a400Schristos 2165*6881a400Schristos if (token) 2166*6881a400Schristos { 2167*6881a400Schristos token = parser->lex_one_token (); 2168*6881a400Schristos SELF_CHECK (token == 0); 2169*6881a400Schristos } 2170*6881a400Schristos } 2171*6881a400Schristos 2172*6881a400Schristos /* Test that INPUT lexes as the integer VALUE. */ 2173*6881a400Schristos 2174*6881a400Schristos static void 2175*6881a400Schristos rust_lex_int_test (rust_parser *parser, const char *input, 2176*6881a400Schristos ULONGEST value, int kind) 2177*6881a400Schristos { 2178*6881a400Schristos rust_lex_test_one (parser, input, kind); 2179*6881a400Schristos SELF_CHECK (parser->current_int_val.val == value); 2180*6881a400Schristos } 2181*6881a400Schristos 2182*6881a400Schristos /* Test that INPUT throws an exception with text ERR. */ 2183*6881a400Schristos 2184*6881a400Schristos static void 2185*6881a400Schristos rust_lex_exception_test (rust_parser *parser, const char *input, 2186*6881a400Schristos const char *err) 2187*6881a400Schristos { 2188*6881a400Schristos try 2189*6881a400Schristos { 2190*6881a400Schristos /* The "kind" doesn't matter. */ 2191*6881a400Schristos rust_lex_test_one (parser, input, DECIMAL_INTEGER); 2192*6881a400Schristos SELF_CHECK (0); 2193*6881a400Schristos } 2194*6881a400Schristos catch (const gdb_exception_error &except) 2195*6881a400Schristos { 2196*6881a400Schristos SELF_CHECK (strcmp (except.what (), err) == 0); 2197*6881a400Schristos } 2198*6881a400Schristos } 2199*6881a400Schristos 2200*6881a400Schristos /* Test that INPUT lexes as the identifier, string, or byte-string 2201*6881a400Schristos VALUE. KIND holds the expected token kind. */ 2202*6881a400Schristos 2203*6881a400Schristos static void 2204*6881a400Schristos rust_lex_stringish_test (rust_parser *parser, const char *input, 2205*6881a400Schristos const char *value, int kind) 2206*6881a400Schristos { 2207*6881a400Schristos rust_lex_test_one (parser, input, kind); 2208*6881a400Schristos SELF_CHECK (parser->get_string () == value); 2209*6881a400Schristos } 2210*6881a400Schristos 2211*6881a400Schristos /* Helper to test that a string parses as a given token sequence. */ 2212*6881a400Schristos 2213*6881a400Schristos static void 2214*6881a400Schristos rust_lex_test_sequence (rust_parser *parser, const char *input, int len, 2215*6881a400Schristos const int expected[]) 2216*6881a400Schristos { 2217*6881a400Schristos int i; 2218*6881a400Schristos 2219*6881a400Schristos parser->reset (input); 2220*6881a400Schristos 2221*6881a400Schristos for (i = 0; i < len; ++i) 2222*6881a400Schristos { 2223*6881a400Schristos int token = parser->lex_one_token (); 2224*6881a400Schristos SELF_CHECK (token == expected[i]); 2225*6881a400Schristos } 2226*6881a400Schristos } 2227*6881a400Schristos 2228*6881a400Schristos /* Tests for an integer-parsing corner case. */ 2229*6881a400Schristos 2230*6881a400Schristos static void 2231*6881a400Schristos rust_lex_test_trailing_dot (rust_parser *parser) 2232*6881a400Schristos { 2233*6881a400Schristos const int expected1[] = { DECIMAL_INTEGER, '.', IDENT, '(', ')', 0 }; 2234*6881a400Schristos const int expected2[] = { INTEGER, '.', IDENT, '(', ')', 0 }; 2235*6881a400Schristos const int expected3[] = { FLOAT, EQEQ, '(', ')', 0 }; 2236*6881a400Schristos const int expected4[] = { DECIMAL_INTEGER, DOTDOT, DECIMAL_INTEGER, 0 }; 2237*6881a400Schristos 2238*6881a400Schristos rust_lex_test_sequence (parser, "23.g()", ARRAY_SIZE (expected1), expected1); 2239*6881a400Schristos rust_lex_test_sequence (parser, "23_0.g()", ARRAY_SIZE (expected2), 2240*6881a400Schristos expected2); 2241*6881a400Schristos rust_lex_test_sequence (parser, "23.==()", ARRAY_SIZE (expected3), 2242*6881a400Schristos expected3); 2243*6881a400Schristos rust_lex_test_sequence (parser, "23..25", ARRAY_SIZE (expected4), expected4); 2244*6881a400Schristos } 2245*6881a400Schristos 2246*6881a400Schristos /* Tests of completion. */ 2247*6881a400Schristos 2248*6881a400Schristos static void 2249*6881a400Schristos rust_lex_test_completion (rust_parser *parser) 2250*6881a400Schristos { 2251*6881a400Schristos const int expected[] = { IDENT, '.', COMPLETE, 0 }; 2252*6881a400Schristos 2253*6881a400Schristos parser->pstate->parse_completion = 1; 2254*6881a400Schristos 2255*6881a400Schristos rust_lex_test_sequence (parser, "something.wha", ARRAY_SIZE (expected), 2256*6881a400Schristos expected); 2257*6881a400Schristos rust_lex_test_sequence (parser, "something.", ARRAY_SIZE (expected), 2258*6881a400Schristos expected); 2259*6881a400Schristos 2260*6881a400Schristos parser->pstate->parse_completion = 0; 2261*6881a400Schristos } 2262*6881a400Schristos 2263*6881a400Schristos /* Test pushback. */ 2264*6881a400Schristos 2265*6881a400Schristos static void 2266*6881a400Schristos rust_lex_test_push_back (rust_parser *parser) 2267*6881a400Schristos { 2268*6881a400Schristos int token; 2269*6881a400Schristos 2270*6881a400Schristos parser->reset (">>="); 2271*6881a400Schristos 2272*6881a400Schristos token = parser->lex_one_token (); 2273*6881a400Schristos SELF_CHECK (token == COMPOUND_ASSIGN); 2274*6881a400Schristos SELF_CHECK (parser->current_opcode == BINOP_RSH); 2275*6881a400Schristos 2276*6881a400Schristos parser->push_back ('='); 2277*6881a400Schristos 2278*6881a400Schristos token = parser->lex_one_token (); 2279*6881a400Schristos SELF_CHECK (token == '='); 2280*6881a400Schristos 2281*6881a400Schristos token = parser->lex_one_token (); 2282*6881a400Schristos SELF_CHECK (token == 0); 2283*6881a400Schristos } 2284*6881a400Schristos 2285*6881a400Schristos /* Unit test the lexer. */ 2286*6881a400Schristos 2287*6881a400Schristos static void 2288*6881a400Schristos rust_lex_tests (void) 2289*6881a400Schristos { 2290*6881a400Schristos /* Set up dummy "parser", so that rust_type works. */ 2291*6881a400Schristos struct parser_state ps (language_def (language_rust), target_gdbarch (), 2292*6881a400Schristos nullptr, 0, 0, nullptr, 0, nullptr, false); 2293*6881a400Schristos rust_parser parser (&ps); 2294*6881a400Schristos 2295*6881a400Schristos rust_lex_test_one (&parser, "", 0); 2296*6881a400Schristos rust_lex_test_one (&parser, " \t \n \r ", 0); 2297*6881a400Schristos rust_lex_test_one (&parser, "thread 23", 0); 2298*6881a400Schristos rust_lex_test_one (&parser, "task 23", 0); 2299*6881a400Schristos rust_lex_test_one (&parser, "th 104", 0); 2300*6881a400Schristos rust_lex_test_one (&parser, "ta 97", 0); 2301*6881a400Schristos 2302*6881a400Schristos rust_lex_int_test (&parser, "'z'", 'z', INTEGER); 2303*6881a400Schristos rust_lex_int_test (&parser, "'\\xff'", 0xff, INTEGER); 2304*6881a400Schristos rust_lex_int_test (&parser, "'\\u{1016f}'", 0x1016f, INTEGER); 2305*6881a400Schristos rust_lex_int_test (&parser, "b'z'", 'z', INTEGER); 2306*6881a400Schristos rust_lex_int_test (&parser, "b'\\xfe'", 0xfe, INTEGER); 2307*6881a400Schristos rust_lex_int_test (&parser, "b'\\xFE'", 0xfe, INTEGER); 2308*6881a400Schristos rust_lex_int_test (&parser, "b'\\xfE'", 0xfe, INTEGER); 2309*6881a400Schristos 2310*6881a400Schristos /* Test all escapes in both modes. */ 2311*6881a400Schristos rust_lex_int_test (&parser, "'\\n'", '\n', INTEGER); 2312*6881a400Schristos rust_lex_int_test (&parser, "'\\r'", '\r', INTEGER); 2313*6881a400Schristos rust_lex_int_test (&parser, "'\\t'", '\t', INTEGER); 2314*6881a400Schristos rust_lex_int_test (&parser, "'\\\\'", '\\', INTEGER); 2315*6881a400Schristos rust_lex_int_test (&parser, "'\\0'", '\0', INTEGER); 2316*6881a400Schristos rust_lex_int_test (&parser, "'\\''", '\'', INTEGER); 2317*6881a400Schristos rust_lex_int_test (&parser, "'\\\"'", '"', INTEGER); 2318*6881a400Schristos 2319*6881a400Schristos rust_lex_int_test (&parser, "b'\\n'", '\n', INTEGER); 2320*6881a400Schristos rust_lex_int_test (&parser, "b'\\r'", '\r', INTEGER); 2321*6881a400Schristos rust_lex_int_test (&parser, "b'\\t'", '\t', INTEGER); 2322*6881a400Schristos rust_lex_int_test (&parser, "b'\\\\'", '\\', INTEGER); 2323*6881a400Schristos rust_lex_int_test (&parser, "b'\\0'", '\0', INTEGER); 2324*6881a400Schristos rust_lex_int_test (&parser, "b'\\''", '\'', INTEGER); 2325*6881a400Schristos rust_lex_int_test (&parser, "b'\\\"'", '"', INTEGER); 2326*6881a400Schristos 2327*6881a400Schristos rust_lex_exception_test (&parser, "'z", "Unterminated character literal"); 2328*6881a400Schristos rust_lex_exception_test (&parser, "b'\\x0'", "Not enough hex digits seen"); 2329*6881a400Schristos rust_lex_exception_test (&parser, "b'\\u{0}'", 2330*6881a400Schristos "Unicode escape in byte literal"); 2331*6881a400Schristos rust_lex_exception_test (&parser, "'\\x0'", "Not enough hex digits seen"); 2332*6881a400Schristos rust_lex_exception_test (&parser, "'\\u0'", "Missing '{' in Unicode escape"); 2333*6881a400Schristos rust_lex_exception_test (&parser, "'\\u{0", "Missing '}' in Unicode escape"); 2334*6881a400Schristos rust_lex_exception_test (&parser, "'\\u{0000007}", "Overlong hex escape"); 2335*6881a400Schristos rust_lex_exception_test (&parser, "'\\u{}", "Not enough hex digits seen"); 2336*6881a400Schristos rust_lex_exception_test (&parser, "'\\Q'", "Invalid escape \\Q in literal"); 2337*6881a400Schristos rust_lex_exception_test (&parser, "b'\\Q'", "Invalid escape \\Q in literal"); 2338*6881a400Schristos 2339*6881a400Schristos rust_lex_int_test (&parser, "23", 23, DECIMAL_INTEGER); 2340*6881a400Schristos rust_lex_int_test (&parser, "2_344__29", 234429, INTEGER); 2341*6881a400Schristos rust_lex_int_test (&parser, "0x1f", 0x1f, INTEGER); 2342*6881a400Schristos rust_lex_int_test (&parser, "23usize", 23, INTEGER); 2343*6881a400Schristos rust_lex_int_test (&parser, "23i32", 23, INTEGER); 2344*6881a400Schristos rust_lex_int_test (&parser, "0x1_f", 0x1f, INTEGER); 2345*6881a400Schristos rust_lex_int_test (&parser, "0b1_101011__", 0x6b, INTEGER); 2346*6881a400Schristos rust_lex_int_test (&parser, "0o001177i64", 639, INTEGER); 2347*6881a400Schristos rust_lex_int_test (&parser, "0x123456789u64", 0x123456789ull, INTEGER); 2348*6881a400Schristos 2349*6881a400Schristos rust_lex_test_trailing_dot (&parser); 2350*6881a400Schristos 2351*6881a400Schristos rust_lex_test_one (&parser, "23.", FLOAT); 2352*6881a400Schristos rust_lex_test_one (&parser, "23.99f32", FLOAT); 2353*6881a400Schristos rust_lex_test_one (&parser, "23e7", FLOAT); 2354*6881a400Schristos rust_lex_test_one (&parser, "23E-7", FLOAT); 2355*6881a400Schristos rust_lex_test_one (&parser, "23e+7", FLOAT); 2356*6881a400Schristos rust_lex_test_one (&parser, "23.99e+7f64", FLOAT); 2357*6881a400Schristos rust_lex_test_one (&parser, "23.82f32", FLOAT); 2358*6881a400Schristos 2359*6881a400Schristos rust_lex_stringish_test (&parser, "hibob", "hibob", IDENT); 2360*6881a400Schristos rust_lex_stringish_test (&parser, "hibob__93", "hibob__93", IDENT); 2361*6881a400Schristos rust_lex_stringish_test (&parser, "thread", "thread", IDENT); 2362*6881a400Schristos rust_lex_stringish_test (&parser, "r#true", "true", IDENT); 2363*6881a400Schristos 2364*6881a400Schristos const int expected1[] = { IDENT, DECIMAL_INTEGER, 0 }; 2365*6881a400Schristos rust_lex_test_sequence (&parser, "r#thread 23", ARRAY_SIZE (expected1), 2366*6881a400Schristos expected1); 2367*6881a400Schristos const int expected2[] = { IDENT, '#', 0 }; 2368*6881a400Schristos rust_lex_test_sequence (&parser, "r#", ARRAY_SIZE (expected2), expected2); 2369*6881a400Schristos 2370*6881a400Schristos rust_lex_stringish_test (&parser, "\"string\"", "string", STRING); 2371*6881a400Schristos rust_lex_stringish_test (&parser, "\"str\\ting\"", "str\ting", STRING); 2372*6881a400Schristos rust_lex_stringish_test (&parser, "\"str\\\"ing\"", "str\"ing", STRING); 2373*6881a400Schristos rust_lex_stringish_test (&parser, "r\"str\\ing\"", "str\\ing", STRING); 2374*6881a400Schristos rust_lex_stringish_test (&parser, "r#\"str\\ting\"#", "str\\ting", STRING); 2375*6881a400Schristos rust_lex_stringish_test (&parser, "r###\"str\\\"ing\"###", "str\\\"ing", 2376*6881a400Schristos STRING); 2377*6881a400Schristos 2378*6881a400Schristos rust_lex_stringish_test (&parser, "b\"string\"", "string", BYTESTRING); 2379*6881a400Schristos rust_lex_stringish_test (&parser, "b\"\x73tring\"", "string", BYTESTRING); 2380*6881a400Schristos rust_lex_stringish_test (&parser, "b\"str\\\"ing\"", "str\"ing", BYTESTRING); 2381*6881a400Schristos rust_lex_stringish_test (&parser, "br####\"\\x73tring\"####", "\\x73tring", 2382*6881a400Schristos BYTESTRING); 2383*6881a400Schristos 2384*6881a400Schristos for (const auto &candidate : identifier_tokens) 2385*6881a400Schristos rust_lex_test_one (&parser, candidate.name, candidate.value); 2386*6881a400Schristos 2387*6881a400Schristos for (const auto &candidate : operator_tokens) 2388*6881a400Schristos rust_lex_test_one (&parser, candidate.name, candidate.value); 2389*6881a400Schristos 2390*6881a400Schristos rust_lex_test_completion (&parser); 2391*6881a400Schristos rust_lex_test_push_back (&parser); 2392*6881a400Schristos } 2393*6881a400Schristos 2394*6881a400Schristos #endif /* GDB_SELF_TEST */ 2395*6881a400Schristos 2396*6881a400Schristos 2397*6881a400Schristos 2398*6881a400Schristos void _initialize_rust_exp (); 2399*6881a400Schristos void 2400*6881a400Schristos _initialize_rust_exp () 2401*6881a400Schristos { 2402*6881a400Schristos int code = regcomp (&number_regex, number_regex_text, REG_EXTENDED); 2403*6881a400Schristos /* If the regular expression was incorrect, it was a programming 2404*6881a400Schristos error. */ 2405*6881a400Schristos gdb_assert (code == 0); 2406*6881a400Schristos 2407*6881a400Schristos #if GDB_SELF_TEST 2408*6881a400Schristos selftests::register_test ("rust-lex", rust_lex_tests); 2409*6881a400Schristos #endif 2410*6881a400Schristos } 2411