From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23921 invoked by alias); 4 Oct 2002 09:25:27 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 23911 invoked from network); 4 Oct 2002 09:25:25 -0000 Received: from unknown (HELO mail-out2.apple.com) (17.254.0.51) by sources.redhat.com with SMTP; 4 Oct 2002 09:25:25 -0000 Received: from mailgate2.apple.com (A17-129-100-225.apple.com [17.129.100.225]) by mail-out2.apple.com (8.11.3/8.11.3) with ESMTP id g949PPs29614 for ; Fri, 4 Oct 2002 02:25:25 -0700 (PDT) Received: from scv3.apple.com (scv3.apple.com) by mailgate2.apple.com (Content Technologies SMTPRS 4.2.1) with ESMTP id ; Fri, 4 Oct 2002 02:25:24 -0700 Received: from molly.local. (vpn-scv-x2-142.apple.com [17.219.193.142]) by scv3.apple.com (8.11.3/8.11.3) with ESMTP id g949PI325771; Fri, 4 Oct 2002 02:25:18 -0700 (PDT) Date: Fri, 04 Oct 2002 02:25:00 -0000 Subject: Re: Add rules for ObjC files Content-Type: multipart/mixed; boundary=Apple-Mail-4--418257061 Mime-Version: 1.0 (Apple Message framework v543) Cc: gdb-patches@sources.redhat.com To: Adam Fedor From: Klee Dienes In-Reply-To: <3D9CF4C4.6030903@doc.com> Message-Id: <3239ADC4-D77B-11D6-A34B-00039396EEB8@mit.edu> X-SW-Source: 2002-10/txt/msg00124.txt.bz2 --Apple-Mail-4--418257061 Content-Transfer-Encoding: 7bit Content-Type: text/plain; delsp=yes; charset=US-ASCII; format=flowed Content-length: 975 I'm not sure if this is something you want to hassle with at the moment, or if you'd prefer to let it wait as a modification once a working version of the Objective-C patches are successfully committed. But just as a heads-up, I should mention that in more recent versions of our GDB, we've folded in all of the Objective-C support directly into c-exp.y, and removed objc-exp.y as a file entirely. Most of objc-exp.y was always just an out-of-date copy of c-exp.y, anyway; moving the (rather small) changes into c-exp.y directly not only allowed us to track changes to the C parser much more smoothly, it should also allow for much better Objective-C++ support. You'll probably want to look at the most recent version of our GDB tree (http://www.opensource.apple.com/projects/darwin/6.0/source/other/gdb- 20020918.tar.gz; no registration or anything similar required), and check out our changes to c-exp.y; I've attached them for your convenience. --Apple-Mail-4--418257061 Content-Disposition: attachment; filename=objc.diffs Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name="objc.diffs" Content-length: 9129 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. */ --Apple-Mail-4--418257061 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed Content-length: 482 One downside to having the changes directly in c-exp.y is that I don't know of any good way to conditionalize them; though I am by no means a bison guru. The following diffs are unrelated to Objective-C; I'm attaching them just for your reference (the ones in generic.diffs are likely to be removed in our sources soon as well; the ones in number-parsing.diffs remove a memory leak caused by calling parse_number on invalid, but are unrelated to the Objective-C changes). --Apple-Mail-4--418257061 Content-Disposition: attachment; filename=number-parsing.diffs Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name="number-parsing.diffs" Content-length: 3114 Index: c-exp.y =================================================================== RCS file: /cvs/Darwin/src/live/cygnus/src/gdb/c-exp.y,v retrieving revision 1.1.1.8 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:33:41 @@ -1384,19 +1490,23 @@ case '9': { /* It's a number. */ - int got_dot = 0, got_e = 0, toktype; + /* Initialize toktype to anything other than ERROR. */ + int got_dot = 0, got_e = 0, toktype = FLOAT; register char *p = tokstart; int hex = input_radix > 10; + int local_radix = input_radix; - if (c == '0' && (p[1] == 'x' || p[1] == 'X')) + if (tokchr == '0' && (p[1] == 'x' || p[1] == 'X')) { p += 2; hex = 1; + local_radix = 16; } - else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D')) + else if (tokchr == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D')) { p += 2; hex = 0; + local_radix = 10; } for (;; ++p) @@ -1404,25 +1514,42 @@ /* This test includes !hex because 'e' is a valid hex digit and thus does not indicate a floating point number when the radix is hex. */ - if (!hex && !got_e && (*p == 'e' || *p == 'E')) - got_dot = got_e = 1; + + if (!hex && (*p == 'e' || *p == 'E')) + if (got_e) + toktype = ERROR; /* only one 'e' in a float */ + else + got_e = 1; /* This test does not include !hex, because a '.' always indicates a decimal floating point number regardless of the radix. */ - else if (!got_dot && *p == '.') - got_dot = 1; - else if (got_e && (p[-1] == 'e' || p[-1] == 'E') - && (*p == '-' || *p == '+')) + else if (*p == '.') + if (got_dot) + toktype = ERROR; /* only one '.' in a float */ + else + got_dot = 1; + else if (got_e && (p[-1] == 'e' || p[-1] == 'E') && + (*p == '-' || *p == '+')) /* This is the sign of the exponent, not the end of the number. */ continue; - /* We will take any letters or digits. parse_number will - complain if past the radix, or if L or U are not final. */ - else if ((*p < '0' || *p > '9') - && ((*p < 'a' || *p > 'z') - && (*p < 'A' || *p > 'Z'))) - break; + /* Always take decimal digits; parse_number handles radix error */ + else if (*p >= '0' && *p <= '9') + continue; + /* We will take letters only if hex is true, and only + up to what the input radix would permit. FSF was content + to rely on parse_number to validate; but it leaks. */ + else if (*p >= 'a' && *p <= 'z') { + if (!hex || *p >= ('a' + local_radix - 10)) + toktype = ERROR; + } + else if (*p >= 'A' && *p <= 'Z') { + if (!hex || *p >= ('A' + local_radix - 10)) + toktype = ERROR; + } + else break; } - toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval); + if (toktype != ERROR) + toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval); if (toktype == ERROR) { char *err_copy = (char *) alloca (p - tokstart + 1); --Apple-Mail-4--418257061 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed Content-length: 2 --Apple-Mail-4--418257061 Content-Disposition: attachment; filename=generic.diffs Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name="generic.diffs" Content-length: 1216 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 @@ -659,7 +745,7 @@ builtin_type_int); } else - if (!have_full_symbols () && !have_partial_symbols ()) + if (!have_full_symbols () && !have_partial_symbols () && !have_minimal_symbols ()) error ("No symbol table is loaded. Use the \"file\" command."); else error ("No symbol \"%s\" in current context.", name); @@ -714,7 +809,7 @@ lookup_function_type (builtin_type_int), builtin_type_int); } - else if (!have_full_symbols () && !have_partial_symbols ()) + else if (!have_full_symbols () && !have_partial_symbols () && !have_minimal_symbols ()) error ("No symbol table is loaded. Use the \"file\" command."); else error ("No symbol \"%s\" in current context.", @@ -1825,5 +2008,8 @@ if (prev_lexptr) lexptr = prev_lexptr; - error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr); + if (*lexptr == '\0') + error("A %s near end of expression.", (msg ? msg : "error")); + else + error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr); } --Apple-Mail-4--418257061 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed Content-length: 409 On Thursday, October 3, 2002, at 09:54 PM, Adam Fedor wrote: > This patch adds rules for the ObjC files but does not enable them. > > 2002-10-03 Adam Fedor > > * Makefile.in (SFILES): Add objc-exp.y objc-lang.c. > (objc_lang_h): Define. > (YYFILES): Add objc-exp.tab.c. > (local-maintainer-clean): Remove objc-exp.tab.c. > (objc-exp.tab.c, objc-exp.tab.o, objc-lang.o): New target. --Apple-Mail-4--418257061--