diff -u -r1.1.1.8 c-exp.y --- c-exp.y 2002/09/26 20:56:42 1.1.1.8 +++ c-exp.y 2002/10/04 08:31:39 @@ -46,9 +46,11 @@ #include "parser-defs.h" #include "language.h" #include "c-lang.h" +#include "objc-lang.h" /* For Obj-C language constructs. */ #include "bfd.h" /* Required by objfiles.h. */ #include "symfile.h" /* Required by objfiles.h. */ #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */ +#include "completer.h" /* For skip_quoted. */ #include "charset.h" /* Flag indicating we're dealing with HP-compiled objects */ @@ -140,6 +142,7 @@ struct block *bval; enum exp_opcode opcode; struct internalvar *ivar; + struct objc_class_str class; struct type **tvec; int *ivec; @@ -173,8 +176,11 @@ nonterminal "name", which matches either NAME or TYPENAME. */ %token STRING -%token NAME /* BLOCKNAME defined below to give it higher precedence. */ +%token NSSTRING /* Obj-C Foundation "NSString" literal */ +%token SELECTOR /* Obj-C "@selector" pseudo-operator */ +%token NAME /* BLOCKNAME defined below to give it higher precedence. */ %token TYPENAME +%token CLASSNAME /* Obj-C Class name */ %type name %type name_not_typename %type typename @@ -324,6 +330,71 @@ { write_exp_elt_opcode (BINOP_SUBSCRIPT); } ; +/* The rules below parse Obj-C message calls of the form: + '[' target selector {':' argument}* ']' */ + +exp : '[' TYPENAME + { + CORE_ADDR class; + + class = lookup_objc_class (copy_name ($2.stoken)); + if (class == 0) + error ("%s is not an ObjC Class", + copy_name ($2.stoken)); + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_int); + write_exp_elt_longcst ((LONGEST) class); + write_exp_elt_opcode (OP_LONG); + start_msglist(); + } + msglist ']' + { write_exp_elt_opcode (OP_MSGCALL); + end_msglist(); + write_exp_elt_opcode (OP_MSGCALL); + } + ; + +exp : '[' CLASSNAME + { + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_int); + write_exp_elt_longcst ((LONGEST) $2.class); + write_exp_elt_opcode (OP_LONG); + start_msglist(); + } + msglist ']' + { write_exp_elt_opcode (OP_MSGCALL); + end_msglist(); + write_exp_elt_opcode (OP_MSGCALL); + } + ; + +exp : '[' exp + { start_msglist(); } + msglist ']' + { write_exp_elt_opcode (OP_MSGCALL); + end_msglist(); + write_exp_elt_opcode (OP_MSGCALL); + } + ; + +msglist : name + { add_msglist(&$1, 0); } + | msgarglist + ; + +msgarglist : msgarg + | msgarglist msgarg + ; + +msgarg : name ':' exp + { add_msglist(&$1, 1); } + | ':' exp /* Unnamed argument. */ + { add_msglist(0, 1); } + | ',' exp /* Variable number of arguments. */ + { add_msglist(0, 0); } + ; + exp : exp '(' /* This is to save the value of arglist_len being accumulated by an outer function call. */ @@ -499,6 +570,13 @@ /* Already written by write_dollar_variable. */ ; +exp : SELECTOR + { + write_exp_elt_opcode (OP_SELECTOR); + write_exp_string ($1); + write_exp_elt_opcode (OP_SELECTOR); } + + exp : SIZEOF '(' type ')' %prec UNARY { write_exp_elt_opcode (OP_LONG); write_exp_elt_type (builtin_type_int); @@ -531,6 +609,14 @@ write_exp_elt_opcode (OP_ARRAY); } ; +exp : NSSTRING /* ObjC NextStep NSString constant + * of the form '@' '"' string '"'. + */ + { write_exp_elt_opcode (OP_NSSTRING); + write_exp_string ($1); + write_exp_elt_opcode (OP_NSSTRING); } + ; + /* C++. */ exp : THIS { write_exp_elt_opcode (OP_THIS); @@ -804,6 +899,14 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */ : TYPENAME { $$ = $1.type; } + | CLASSNAME + { + if ($1.type == NULL) + error ("No symbol \"%s\" in current context.", + copy_name($1.stoken)); + else + $$ = $1.type; + } | INT_KEYWORD { $$ = builtin_type_int; } | LONG @@ -951,7 +1054,8 @@ name : NAME { $$ = $1.stoken; } | BLOCKNAME { $$ = $1.stoken; } | TYPENAME { $$ = $1.stoken; } - | NAME_OR_INT { $$ = $1.stoken; } + | CLASSNAME { $$ = $1.stoken; } + | NAME_OR_INT { $$ = $1.stoken; } ; name_not_typename : NAME @@ -1239,6 +1343,7 @@ int c; int namelen; unsigned int i; + int tokchr; char *tokstart; char *tokptr; int tempbufindex; @@ -1284,7 +1389,7 @@ return tokentab2[i].token; } - switch (c = *tokstart) + switch (tokchr = *tokstart) { case 0: /* If we were just scanning the result of a macro expansion, @@ -1331,7 +1436,8 @@ c = *lexptr++; if (c != '\'') { - namelen = skip_quoted (tokstart) - tokstart; + namelen = skip_quoted (tokstart, get_gdb_completer_word_break_characters ()) + - tokstart; if (namelen > 2) { lexptr = tokstart + namelen; @@ -1349,14 +1455,14 @@ case '(': paren_depth++; lexptr++; - return c; + return '('; case ')': if (paren_depth == 0) return 0; paren_depth--; lexptr++; - return c; + return ')'; case ',': if (comma_terminates @@ -1364,7 +1470,7 @@ && ! scanning_macro_expansion ()) return 0; lexptr++; - return c; + return ','; case '.': /* Might be a floating point number. */ @@ -1445,7 +1572,6 @@ case '^': case '~': case '!': - case '@': case '<': case '>': case '[': @@ -1457,8 +1583,42 @@ case '}': symbol: lexptr++; - return c; + return tokchr; + case '@': + if (strncmp (tokstart, "@selector", 9) == 0) + { + tokptr = strchr (tokstart, '('); + if (tokptr == NULL) + error ("Missing '(' in @selector(...)"); + tempbufindex = 0; + /* skip the '(' */ + tokptr++; + do { + /* Grow the static temp buffer if necessary, including allocating + the first one on demand. */ + if (tempbufindex + 1 >= tempbufsize) + { + tempbuf = (char *) realloc (tempbuf, tempbufsize += 64); + } + tempbuf[tempbufindex++] = *tokptr++; + } while ((*tokptr != ')') && (*tokptr != '\0')); + if (*tokptr++ != ')') + error ("Missing ')' in @selector(...)"); + tempbuf[tempbufindex] = '\0'; + yylval.sval.ptr = tempbuf; + yylval.sval.length = tempbufindex; + lexptr = tokptr; + return SELECTOR; + } + if (tokstart[1] != '"') + { + lexptr++; + return tokchr; + } + /* Obj-C NSString constant: fall through and parse like STRING. */ + tokstart++; + case '"': /* Build the gdb internal form of the input string in tempbuf, @@ -1522,13 +1682,13 @@ yylval.sval.ptr = tempbuf; yylval.sval.length = tempbufindex; lexptr = tokptr; - return (STRING); + return (tokchr == '@' ? NSSTRING : STRING); } - if (!(c == '_' || c == '$' - || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) + if (!(tokchr == '_' || tokchr == '$' || + (tokchr >= 'a' && tokchr <= 'z') || (tokchr >= 'A' && tokchr <= 'Z'))) /* We must have come across a bad character (e.g. ';'). */ - error ("Invalid character '%c' in expression.", c); + error ("Invalid character '%c' in expression.", tokchr); /* It's a name. See how long it is. */ namelen = 0; @@ -1672,16 +1832,22 @@ char *tmp = copy_name (yylval.sval); struct symbol *sym; int is_a_field_of_this = 0; + int *need_this; int hextype; + if (current_language->la_language == language_cplus + || current_language->la_language == language_objc + || current_language->la_language == language_objcplus) + need_this = &is_a_field_of_this; + else + need_this = (int *) NULL; + sym = lookup_symbol (tmp, expression_context_block, - VAR_NAMESPACE, - current_language->la_language == language_cplus - ? &is_a_field_of_this : (int *) NULL, + VAR_NAMESPACE, need_this, (struct symtab **) NULL); /* Call lookup_symtab, not lookup_partial_symtab, in case there are no psymtabs (coff, xcoff, or some future change to blow away the - psymtabs once once symbols are read). */ + psymtabs once symbols are read). */ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) { yylval.ssym.sym = sym; @@ -1794,6 +1960,23 @@ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0) return TYPENAME; + /* See if it's an Obj-C classname. */ + if (!sym && should_lookup_objc_class ()) + { + extern struct symbol *lookup_struct_typedef (); + sym = lookup_struct_typedef (tmp, expression_context_block, 1); + if (sym) + { + CORE_ADDR Class = lookup_objc_class (tmp); + if (Class) + { + yylval.class.class = Class; + yylval.class.type = SYMBOL_TYPE (sym); + return CLASSNAME; + } + } + } + /* Input names that aren't symbols but ARE valid hex numbers, when the input radix permits them, can be names or numbers depending on the parse. Note we support radixes > 16 here. */