Annotation of gcc/objc-actions.c, revision 1.1

1.1     ! root        1: /* Implement classes and message passing for Objective C.
        !             2:    Copyright (C) 1992 Free Software Foundation, Inc.
        !             3:    Author: Steve Naroff.
        !             4: 
        !             5: This file is part of GNU CC.
        !             6: 
        !             7: GNU CC is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 2, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU CC is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU CC; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: /*
        !            22:  *      Purpose: This module implements the Objective-C 4.0 language.
        !            23:  *
        !            24:  *      compatibility issues (with the Stepstone translator):
        !            25:  *
        !            26:  *     - does not recognize the following 3.3 constructs.
        !            27:  *       @requires, @classes, @messages, = (...)
        !            28:  *     - methods with variable arguments must conform to ANSI standard.
        !            29:  *     - tagged structure definitions that appear in BOTH the interface
        !            30:  *       and implementation are not allowed.
        !            31:  *      - public/private: all instance variables are public within the
        !            32:  *        context of the implementation...I consider this to be a bug in
        !            33:  *        the translator.
        !            34:  *      - statically allocated objects are not supported. the user will
        !            35:  *        receive an error if this service is requested.
        !            36:  *
        !            37:  *      code generation `options':
        !            38:  *
        !            39:  *      - OBJC_INT_SELECTORS, OBJC_NONUNIQUE_SELECTORS
        !            40:  */
        !            41: 
        !            42: #include <stdio.h>
        !            43: #include "config.h"
        !            44: #include "tree.h"
        !            45: #include "c-tree.h"
        !            46: #include "c-lex.h"
        !            47: #include "flags.h"
        !            48: #include "objc-actions.h"
        !            49: #include "input.h"
        !            50: 
        !            51: /* Define the special tree codes that we use.  */
        !            52: 
        !            53: /* Table indexed by tree code giving a string containing a character
        !            54:    classifying the tree code.  Possibilities are
        !            55:    t, d, s, c, r, <, 1 and 2.  See objc-tree.def for details.  */
        !            56: 
        !            57: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
        !            58: 
        !            59: char *objc_tree_code_type[] = {
        !            60:   "x",
        !            61: #include "objc-tree.def"
        !            62: };
        !            63: #undef DEFTREECODE
        !            64: 
        !            65: /* Table indexed by tree code giving number of expression
        !            66:    operands beyond the fixed part of the node structure.
        !            67:    Not used for types or decls.  */
        !            68: 
        !            69: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
        !            70: 
        !            71: int objc_tree_code_length[] = {
        !            72:   0,
        !            73: #include "objc-tree.def"
        !            74: };
        !            75: #undef DEFTREECODE
        !            76: 
        !            77: /* Names of tree components.
        !            78:    Used for printing out the tree and error messages.  */
        !            79: #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
        !            80: 
        !            81: char *objc_tree_code_name[] = {
        !            82:   "@@dummy",
        !            83: #include "objc-tree.def"
        !            84: };
        !            85: #undef DEFTREECODE
        !            86: 
        !            87: /* for encode_method_def */
        !            88: #include "rtl.h"
        !            89: 
        !            90: #define OBJC_VERSION   2
        !            91: 
        !            92: #define NULLT  (tree) 0
        !            93: 
        !            94: #define OBJC_ENCODE_INLINE_DEFS        0
        !            95: #define OBJC_ENCODE_DONT_INLINE_DEFS   1
        !            96: 
        !            97: /*** Private Interface (procedures) ***/
        !            98: 
        !            99: /* code generation */
        !           100: 
        !           101: static void synth_module_prologue ();
        !           102: static char *build_module_descriptor ();
        !           103: static tree init_module_descriptor ();
        !           104: static void build_module_entry ();
        !           105: static tree build_objc_method_call ();
        !           106: static void build_message_selector_pool ();
        !           107: static void build_selector_translation_table ();
        !           108: static tree build_ivar_chain ();
        !           109: 
        !           110: static tree build_ivar_template ();
        !           111: static tree build_method_template ();
        !           112: static tree build_private_template ();
        !           113: static void build_class_template ();
        !           114: static void build_category_template ();
        !           115: static tree build_super_template ();
        !           116: 
        !           117: static void synth_forward_declarations ();
        !           118: static void generate_ivar_lists ();
        !           119: static void generate_dispatch_tables ();
        !           120: static void generate_shared_structures ();
        !           121: 
        !           122: static tree build_msg_pool_reference ();
        !           123: static tree init_selector ();
        !           124: static tree build_keword_selector ();
        !           125: static tree synth_id_with_class_suffix ();
        !           126: 
        !           127: /* misc. bookkeeping */
        !           128: 
        !           129: typedef struct hashedEntry     *hash;
        !           130: typedef struct hashedAttribute  *attr;
        !           131: 
        !           132: struct hashedAttribute {
        !           133:         attr    next;
        !           134:         tree    value;
        !           135: };
        !           136: struct hashedEntry {
        !           137:         attr    list;
        !           138:        hash    next;
        !           139:        tree    key;
        !           140: };
        !           141: static void hash_init ();
        !           142: static void hash_enter ();
        !           143: static hash hash_lookup ();
        !           144: static void hash_add_attr ();
        !           145: static tree lookup_method ();
        !           146: static tree lookup_instance_method_static ();
        !           147: static tree lookup_class_method_static ();
        !           148: static tree add_class ();
        !           149: static int  add_selector_reference ();
        !           150: static void add_class_reference ();
        !           151: static int  add_objc_string ();
        !           152: 
        !           153: /* type encoding */
        !           154: 
        !           155: static void encode_aggregate ();
        !           156: static void encode_bitfield ();
        !           157: static void encode_type ();
        !           158: static void encode_field_decl ();
        !           159: 
        !           160: static void really_start_method ();
        !           161: static int  comp_method_with_proto ();
        !           162: static int  comp_proto_with_proto ();
        !           163: static tree get_arg_type_list ();
        !           164: static tree expr_last ();
        !           165: 
        !           166: /* utilities for debugging and error diagnostics: */
        !           167: 
        !           168: static void warn_with_method ();
        !           169: static void error_with_method ();
        !           170: static void error_with_ivar ();
        !           171: static char *gen_method_decl ();
        !           172: static char *gen_declaration ();
        !           173: static char *gen_declarator ();
        !           174: static int is_complex_decl ();
        !           175: static void adorn_decl ();
        !           176: static void dump_interfaces ();
        !           177: 
        !           178: /*** Private Interface (data) ***/
        !           179: 
        !           180: /* reserved tag definitions: */
        !           181: 
        !           182: #define TYPE_ID                        "id"
        !           183: #define TAG_OBJECT             "objc_object"
        !           184: #define TAG_CLASS              "objc_class"
        !           185: #define TAG_SUPER              "objc_super"
        !           186: #define TAG_SELECTOR           "objc_selector"
        !           187: 
        !           188: #define _TAG_CLASS             "_objc_class"
        !           189: #define _TAG_IVAR              "_objc_ivar"
        !           190: #define _TAG_IVAR_LIST         "_objc_ivar_list"
        !           191: #define _TAG_METHOD            "_objc_method"
        !           192: #define _TAG_METHOD_LIST       "_objc_method_list"
        !           193: #define _TAG_CATEGORY          "_objc_category"
        !           194: #define _TAG_MODULE            "_objc_module"
        !           195: #define _TAG_SYMTAB            "_objc_symtab"
        !           196: #define _TAG_SUPER             "_objc_super"
        !           197: 
        !           198: /* set by `continue_class ()' and checked by `is_public ()' */
        !           199: 
        !           200: #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC(record_type))
        !           201: #define TYPED_OBJECT(type) \
        !           202:        (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
        !           203: 
        !           204: /* some commonly used instances of "identifier_node". */
        !           205: 
        !           206: static tree self_id, _cmd_id, _msg_id, _msgSuper_id;
        !           207: static tree objc_getClass_id, objc_getMetaClass_id;
        !           208: 
        !           209: static tree self_decl, _msg_decl, _msgSuper_decl;
        !           210: static tree objc_getClass_decl, objc_getMetaClass_decl;
        !           211: 
        !           212: static tree super_type, _selector_type, id_type, class_type;
        !           213: static tree instance_type;
        !           214: 
        !           215: static tree interface_chain = NULLT;
        !           216: 
        !           217: /* chains to manage selectors that are referenced and defined in the module */
        !           218: 
        !           219: static tree cls_ref_chain = NULLT;     /* classes referenced */
        !           220: static tree sel_ref_chain = NULLT;     /* selectors referenced */
        !           221: static tree sel_refdef_chain = NULLT;  /* selectors references & defined */
        !           222: static int  max_selector_index;                /* total # of selector referenced */
        !           223: 
        !           224: /* hash tables to manage the global pool of method prototypes */
        !           225: 
        !           226: static hash *nst_method_hash_list = 0;
        !           227: static hash *cls_method_hash_list = 0;
        !           228: 
        !           229: /* the following are used when compiling a class implementation.
        !           230:  *
        !           231:  * implementation_template will normally be an anInterface, however if
        !           232:  * none exists this will be equal to implementation_context...it is
        !           233:  * set in start_class.
        !           234:  */
        !           235: 
        !           236: /* backend data declarations */
        !           237: 
        !           238: static tree _OBJC_SYMBOLS_decl;
        !           239: static tree    _OBJC_INSTANCE_VARIABLES_decl, _OBJC_CLASS_VARIABLES_decl;
        !           240: static tree    _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl;
        !           241: static tree    _OBJC_CLASS_decl, _OBJC_METACLASS_decl;
        !           242: #ifdef OBJC_NONUNIQUE_SELECTORS
        !           243: static tree    _OBJC_SELECTOR_REFERENCES_decl;
        !           244: #endif
        !           245: static tree _OBJC_MODULES_decl;
        !           246: static tree _OBJC_STRINGS_decl;
        !           247: 
        !           248: static tree implementation_context = NULLT,
        !           249:            implementation_template = NULLT;
        !           250: 
        !           251: struct imp_entry {
        !           252:   struct imp_entry *next;
        !           253:   tree imp_context;
        !           254:   tree imp_template;
        !           255:   tree class_decl;             /* _OBJC_CLASS_<my_name>; */
        !           256:   tree meta_decl;              /* _OBJC_METACLASS_<my_name>; */
        !           257: };
        !           258: static struct imp_entry *imp_list = 0;
        !           259: static int imp_count = 0;      /* `@implementation' */
        !           260: static int cat_count = 0;      /* `@category' */
        !           261: 
        !           262: static tree objc_class_template, objc_category_template, _PRIVATE_record;
        !           263: static tree _clsSuper_ref, __clsSuper_ref;
        !           264: 
        !           265: static tree objc_method_template, objc_ivar_template;
        !           266: static tree objc_symtab_template, objc_module_template;
        !           267: static tree objc_super_template, objc_object_reference;
        !           268: 
        !           269: static tree objc_object_id, objc_class_id;
        !           270: #ifdef OBJC_NONUNIQUE_SELECTORS
        !           271: static tree _OBJC_SELECTOR_REFERENCES_id;
        !           272: #endif
        !           273: static tree _OBJC_SUPER_decl;
        !           274: 
        !           275: static tree method_context = NULLT;
        !           276: static int  method_slot = 0;   /* used by start_method_def */
        !           277: 
        !           278: #define BUFSIZE                512
        !           279: 
        !           280: static char *errbuf;   /* a buffer for error diagnostics */
        !           281: static char *utlbuf;   /* a buffer for general utility */
        !           282: 
        !           283: extern char *strcpy (), *strcat ();
        !           284: 
        !           285: extern tree groktypename_in_parm_context ();
        !           286: 
        !           287: extern struct obstack permanent_obstack, *current_obstack,  *rtl_obstack;
        !           288: 
        !           289: /* data imported from toplev.c  */
        !           290: 
        !           291: extern char *dump_base_name;
        !           292: 
        !           293: /* Open and close the file for outputting class declarations, if requested.  */
        !           294: 
        !           295: int flag_gen_declaration = 0;
        !           296: 
        !           297: FILE *gen_declaration_file;
        !           298: 
        !           299: /* Warn if multiple methods are seen for the same selector, but with
        !           300:    different argument types. */
        !           301: 
        !           302: int warn_selector = 0;
        !           303: 
        !           304: void
        !           305: lang_init ()
        !           306: {
        !           307:   /* the beginning of the file is a new line; check for # */
        !           308:   /* With luck, we discover the real source file's name from that
        !           309:      and put it in input_filename.  */
        !           310:   ungetc (check_newline (), finput);
        !           311: 
        !           312:   /* If gen_declaration desired, open the output file.  */
        !           313:   if (flag_gen_declaration)
        !           314:     {
        !           315:       int dump_base_name_length = strlen (dump_base_name);
        !           316:       register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
        !           317:       strcpy (dumpname, dump_base_name);
        !           318:       strcat (dumpname, ".decl");
        !           319:       gen_declaration_file = fopen (dumpname, "w");
        !           320:       if (gen_declaration_file == 0)
        !           321:        pfatal_with_name (dumpname);
        !           322:     }
        !           323: 
        !           324:   if (doing_objc_thang)
        !           325:     init_objc ();
        !           326: }
        !           327: 
        !           328: void
        !           329: objc_finish ()
        !           330: {
        !           331:   if (doing_objc_thang)
        !           332:     finish_objc ();            /* Objective-C finalization */
        !           333: 
        !           334:   if (gen_declaration_file)
        !           335:     fclose (gen_declaration_file);
        !           336: }
        !           337: 
        !           338: void
        !           339: lang_finish ()
        !           340: {
        !           341: }
        !           342: 
        !           343: int
        !           344: lang_decode_option (p)
        !           345:      char *p;
        !           346: {
        !           347:   if (!strcmp (p, "-lang-objc"))
        !           348:     doing_objc_thang = 1;
        !           349:   else if (!strcmp (p, "-gen-decls"))
        !           350:     flag_gen_declaration = 1;
        !           351:   else if (!strcmp (p, "-Wselector"))
        !           352:     warn_selector = 1;
        !           353:   else if (!strcmp (p, "-Wno-selector"))
        !           354:     warn_selector = 0;
        !           355:   else
        !           356:     return c_decode_option (p);
        !           357: 
        !           358:   return 1;
        !           359: }
        !           360: 
        !           361: static tree
        !           362: define_decl (declarator, declspecs)
        !           363:      tree declarator;
        !           364:      tree declspecs;
        !           365: {
        !           366:   tree decl = start_decl (declarator, declspecs, 0);
        !           367:   finish_decl (decl, NULLT, NULLT);
        !           368:   return decl;
        !           369: }
        !           370: 
        !           371: /*
        !           372:  * rules for statically typed objects...called from `c-typeck.comptypes'.
        !           373:  *
        !           374:  * an assignment of the form `a' = `b' is permitted if:
        !           375:  *
        !           376:  *   - `a' is of type "id".
        !           377:  *   - `a' and `b' are the same class type.
        !           378:  *   - `a' and `b' are of class types A and B such that B is a descendant
        !           379:  *     of A.
        !           380:  */
        !           381: 
        !           382: int
        !           383: maybe_objc_comptypes (lhs, rhs)
        !           384:      tree lhs, rhs;
        !           385: {
        !           386:   if (doing_objc_thang)
        !           387:     return objc_comptypes (lhs, rhs);
        !           388:   return 0;
        !           389: }
        !           390: 
        !           391: int
        !           392: objc_comptypes (lhs, rhs)
        !           393:      tree lhs;
        !           394:      tree rhs;
        !           395: {
        !           396:   /* `id' = `<class> *', `<class> *' = `id' */
        !           397: 
        !           398:   if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
        !           399:       || (TYPED_OBJECT (lhs) && TYPE_NAME (rhs) == objc_object_id))
        !           400:     return 1;
        !           401: 
        !           402:   /* `id' = `Class', `Class' = `id' */
        !           403: 
        !           404: 
        !           405:   else if ((TYPE_NAME (lhs) == objc_object_id &&
        !           406:            TYPE_NAME (rhs) == objc_class_id) ||
        !           407:           (TYPE_NAME (lhs) == objc_class_id &&
        !           408:            TYPE_NAME (rhs) == objc_object_id))
        !           409:     return 1;
        !           410: 
        !           411:   /* `<class> *' = `<class> *' */
        !           412: 
        !           413:   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
        !           414:     {
        !           415:       tree lname = TYPE_NAME (lhs), rname = TYPE_NAME (rhs);
        !           416: 
        !           417:       if (lname == rname)
        !           418:        return 1;
        !           419:       else
        !           420:        {
        !           421:          /* if the left hand side is a super class of the right hand side,
        !           422:             allow it...
        !           423:             */
        !           424:          tree rinter = lookup_interface (rname);
        !           425: 
        !           426:          while (rinter)
        !           427:            {
        !           428:              if (lname == CLASS_SUPER_NAME (rinter))
        !           429:                return 1;
        !           430: 
        !           431:              rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
        !           432:            }
        !           433: 
        !           434:          return 0;
        !           435:        }
        !           436:     }
        !           437:   else
        !           438:     return 0;
        !           439: }
        !           440: 
        !           441: /* Called from c-decl.c before all calls to rest_of_decl_compilation.  */
        !           442: 
        !           443: void
        !           444: maybe_objc_check_decl (decl)
        !           445:      tree decl;
        !           446: {
        !           447:   if (doing_objc_thang)
        !           448:     objc_check_decl (decl);
        !           449: }
        !           450: 
        !           451: void
        !           452: objc_check_decl (decl)
        !           453:      tree decl;
        !           454: {
        !           455:   tree type = TREE_TYPE (decl);
        !           456:   static int alreadyWarned = 0;
        !           457: 
        !           458:   if (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
        !           459:     {
        !           460:       if (!alreadyWarned)
        !           461:        {
        !           462:          error ("GNU compiler does not support statically allocated objects");
        !           463:          alreadyWarned = 1;
        !           464:        }
        !           465:       error_with_decl (decl, "`%s' cannot be statically allocated");
        !           466:     }
        !           467: }
        !           468: 
        !           469: /* implement static typing. at this point, we know we have an interface... */
        !           470: 
        !           471: tree
        !           472: get_static_reference (interface)
        !           473:      tree interface;
        !           474: {
        !           475:   return xref_tag (RECORD_TYPE, CLASS_NAME (interface));
        !           476: }
        !           477: 
        !           478: /*
        !           479:  *     purpose: "play" parser, creating/installing representations
        !           480:  *              of the declarations that are required by Objective-C.
        !           481:  *
        !           482:  *     model:
        !           483:  *
        !           484:  *             type_spec--------->sc_spec
        !           485:  *             (tree_list)        (tree_list)
        !           486:  *                 |                  |
        !           487:  *                 |                  |
        !           488:  *             identifier_node    identifier_node
        !           489:  */
        !           490: static void
        !           491: synth_module_prologue ()
        !           492: {
        !           493:   tree sc_spec, type_spec, decl_specs, expr_decl, parms, record;
        !           494: 
        !           495:   /* defined in `objc.h' */
        !           496:   objc_object_id = get_identifier (TAG_OBJECT);
        !           497: 
        !           498:   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
        !           499: 
        !           500:   id_type = groktypename (build_tree_list (
        !           501:                                           build_tree_list (NULLT, objc_object_reference),
        !           502:                                           build1 (INDIRECT_REF, NULLT, NULLT)));
        !           503: 
        !           504:   objc_class_id = get_identifier (TAG_CLASS);
        !           505:   
        !           506:   class_type = groktypename (build_tree_list
        !           507:                             (build_tree_list
        !           508:                              (NULLT, xref_tag (RECORD_TYPE, objc_class_id)),
        !           509:                              build1 (INDIRECT_REF, NULLT, NULLT)));
        !           510: 
        !           511: /* Declare SEL type before prototypes for objc_msgSend(), or else those
        !           512:    struct tags are considered local to the prototype and won't match the one
        !           513:    in <objc/objc-runtime.h>. */
        !           514: 
        !           515: #ifdef OBJC_INT_SELECTORS
        !           516:   /* `unsigned int' */
        !           517:   _selector_type = unsigned_type_node;
        !           518: #else
        !           519:   /* `struct objc_selector *' */
        !           520:   _selector_type = groktypename (build_tree_list (
        !           521:             build_tree_list (NULLT,
        !           522:                              xref_tag (RECORD_TYPE,
        !           523:                                        get_identifier (TAG_SELECTOR))),
        !           524:             build1 (INDIRECT_REF, NULLT, NULLT)));
        !           525: #endif /* not OBJC_INT_SELECTORS */
        !           526: 
        !           527:   /* forward declare type...or else the prototype for `super' will bitch */
        !           528:   groktypename (build_tree_list (build_tree_list (NULLT,
        !           529:                                                  xref_tag (RECORD_TYPE, get_identifier (TAG_SUPER))),
        !           530:                                 build1 (INDIRECT_REF, NULLT, NULLT)));
        !           531: 
        !           532:   _msg_id = get_identifier ("objc_msgSend");
        !           533:   _msgSuper_id = get_identifier ("objc_msgSendSuper");
        !           534:   objc_getClass_id = get_identifier ("objc_getClass");
        !           535:   objc_getMetaClass_id = get_identifier ("objc_getMetaClass");
        !           536: 
        !           537:   /* struct objc_object *objc_msgSend (id, SEL, ...); */
        !           538:   pushlevel (0);
        !           539:   decl_specs = build_tree_list (NULLT, objc_object_reference);
        !           540:   push_parm_decl (build_tree_list (decl_specs,
        !           541:                                   build1 (INDIRECT_REF, NULLT, NULLT)));
        !           542: 
        !           543: #ifdef OBJC_INT_SELECTORS
        !           544:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
        !           545:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !           546:   expr_decl = NULLT;
        !           547: #else
        !           548:   decl_specs = build_tree_list (NULLT,
        !           549:                                xref_tag (RECORD_TYPE,
        !           550:                                          get_identifier (TAG_SELECTOR)));
        !           551:   expr_decl = build1 (INDIRECT_REF, NULLT, NULLT);
        !           552: #endif /* not OBJC_INT_SELECTORS */
        !           553: 
        !           554:   push_parm_decl (build_tree_list (decl_specs, expr_decl));
        !           555:   parms = get_parm_info (0);
        !           556:   poplevel (0, 0, 0);
        !           557: 
        !           558:   decl_specs = build_tree_list (NULLT, objc_object_reference);
        !           559:   expr_decl = build_nt (CALL_EXPR, _msg_id, parms, NULLT);
        !           560:   expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
        !           561: 
        !           562:   _msg_decl = define_decl (expr_decl, decl_specs);
        !           563: 
        !           564:   /* struct objc_object *objc_msgSendSuper (struct objc_super *, SEL, ...); */
        !           565:   pushlevel (0);
        !           566:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !           567:                                                 get_identifier (TAG_SUPER)));
        !           568:   push_parm_decl (build_tree_list (decl_specs,
        !           569:                                   build1 (INDIRECT_REF, NULLT, NULLT)));
        !           570: 
        !           571: #ifdef OBJC_INT_SELECTORS
        !           572:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
        !           573:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !           574:   expr_decl = NULLT;
        !           575: #else /* not OBJC_INT_SELECTORS */
        !           576:   decl_specs = build_tree_list (NULLT,
        !           577:                                xref_tag (RECORD_TYPE,
        !           578:                                          get_identifier (TAG_SELECTOR)));
        !           579:   expr_decl = build1 (INDIRECT_REF, NULLT, NULLT);
        !           580: #endif /* not OBJC_INT_SELECTORS */
        !           581: 
        !           582:   push_parm_decl (build_tree_list (decl_specs, expr_decl));
        !           583:   parms = get_parm_info (0);
        !           584:   poplevel (0, 0, 0);
        !           585: 
        !           586:   decl_specs = build_tree_list (NULLT, objc_object_reference);
        !           587:   expr_decl = build_nt (CALL_EXPR, _msgSuper_id, parms, NULLT);
        !           588:   expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
        !           589: 
        !           590:   _msgSuper_decl = define_decl (expr_decl, decl_specs);
        !           591: 
        !           592:   /* id objc_getClass (); */
        !           593:   parms = build_tree_list (NULLT, NULLT);
        !           594:   expr_decl = build_nt (CALL_EXPR, objc_getClass_id, parms, NULLT);
        !           595:   expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
        !           596: 
        !           597:   objc_getClass_decl = define_decl (expr_decl, decl_specs);
        !           598: 
        !           599:   /* id objc_getMetaClass (); */
        !           600:   parms = build_tree_list (NULLT, NULLT);
        !           601:   expr_decl = build_nt (CALL_EXPR, objc_getMetaClass_id, parms, NULLT);
        !           602:   expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
        !           603: 
        !           604:   objc_getMetaClass_decl = define_decl (expr_decl, decl_specs);
        !           605: 
        !           606: #ifdef OBJC_NONUNIQUE_SELECTORS
        !           607:   _OBJC_SELECTOR_REFERENCES_id = get_identifier ("_OBJC_SELECTOR_REFERENCES");
        !           608: 
        !           609:   /* extern SEL _OBJC_SELECTOR_REFERENCES[]; */
        !           610:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_EXTERN], NULLT);
        !           611:   
        !           612: #ifdef OBJC_INT_SELECTORS
        !           613:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], sc_spec);
        !           614:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !           615:   expr_decl = _OBJC_SELECTOR_REFERENCES_id;
        !           616: #else  /* not OBJC_INT_SELECTORS */
        !           617:   decl_specs = build_tree_list (NULLT,
        !           618:                                xref_tag (RECORD_TYPE,
        !           619:                                          get_identifier (TAG_SELECTOR)));
        !           620:   expr_decl = build1 (INDIRECT_REF, NULLT, _OBJC_SELECTOR_REFERENCES_id);
        !           621: #endif /* not OBJC_INT_SELECTORS */
        !           622: 
        !           623:   expr_decl = build_nt (ARRAY_REF, expr_decl, NULLT);
        !           624:   _OBJC_SELECTOR_REFERENCES_decl = define_decl (expr_decl, decl_specs);
        !           625: #endif
        !           626: }
        !           627: 
        !           628: /*
        !           629:  * custom "build_string ()" which sets TREE_TYPE!
        !           630:  */
        !           631: static tree
        !           632: my_build_string (len, str)
        !           633:      int len;
        !           634:      char *str;
        !           635: {
        !           636:   int wide_flag = 0;
        !           637:   tree aString = build_string (len, str);
        !           638:   /*
        !           639:    *  some code from "combine_strings ()", which is local to c-parse.y.
        !           640:    */
        !           641:   if (TREE_TYPE (aString) == int_array_type_node)
        !           642:     wide_flag = 1;
        !           643: 
        !           644:   TREE_TYPE (aString) =
        !           645:     build_array_type (wide_flag ? integer_type_node : char_type_node,
        !           646:                      build_index_type (build_int_2 (len - 1, 0)));
        !           647: 
        !           648:   TREE_CONSTANT (aString) = 1; /* puts string in the ".text" segment */
        !           649:   TREE_STATIC (aString) = 1;
        !           650: 
        !           651:   return aString;
        !           652: }
        !           653: 
        !           654: /*
        !           655:  *     struct objc_symtab {
        !           656:  *             long sel_ref_cnt;
        !           657:  *             char *refs;
        !           658:  *             long cls_def_cnt;
        !           659:  *             long cat_def_cnt;
        !           660:  *             void *defs[cls_def_cnt + cat_def_cnt];
        !           661:  *     };
        !           662:  */
        !           663: static void
        !           664: build_objc_symtab_template ()
        !           665: {
        !           666:   tree decl_specs, field_decl, field_decl_chain;
        !           667: 
        !           668:   objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (_TAG_SYMTAB));
        !           669: 
        !           670:   /* long sel_ref_cnt; */
        !           671: 
        !           672:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !           673:   field_decl = get_identifier ("sel_ref_cnt");
        !           674:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           675:   field_decl_chain = field_decl;
        !           676: 
        !           677: #ifdef OBJC_INT_SELECTORS
        !           678:   /* unsigned int *sel_ref; */
        !           679:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
        !           680:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !           681:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("refs"));
        !           682: #else /* not OBJC_INT_SELECTORS */
        !           683:   /* struct objc_selector **sel_ref; */
        !           684:   decl_specs = build_tree_list (NULLT,
        !           685:                                xref_tag (RECORD_TYPE,
        !           686:                                          get_identifier (TAG_SELECTOR)));
        !           687:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("refs"));
        !           688:   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
        !           689: #endif /* not OBJC_INT_SELECTORS */
        !           690: 
        !           691:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           692:   chainon (field_decl_chain, field_decl);
        !           693: 
        !           694:   /* short cls_def_cnt; */
        !           695: 
        !           696:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_SHORT]);
        !           697:   field_decl = get_identifier ("cls_def_cnt");
        !           698:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           699:   chainon (field_decl_chain, field_decl);
        !           700: 
        !           701:   /* short cat_def_cnt; */
        !           702: 
        !           703:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_SHORT]);
        !           704:   field_decl = get_identifier ("cat_def_cnt");
        !           705:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           706:   chainon (field_decl_chain, field_decl);
        !           707: 
        !           708:   /* void *defs[cls_def_cnt + cat_def_cnt]; */
        !           709: 
        !           710:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_VOID]);
        !           711:   field_decl = build_nt (ARRAY_REF, get_identifier ("defs"),
        !           712:                         build_int_2 (imp_count + cat_count, 0));
        !           713:   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
        !           714:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           715:   chainon (field_decl_chain, field_decl);
        !           716: 
        !           717:   finish_struct (objc_symtab_template, field_decl_chain);
        !           718: }
        !           719: 
        !           720: static tree
        !           721: init_def_list ()
        !           722: {
        !           723:   tree expr, initlist = NULLT;
        !           724:   struct imp_entry *impent;
        !           725: 
        !           726:   if (imp_count)
        !           727:     for (impent = imp_list; impent; impent = impent->next)
        !           728:       {
        !           729:        if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
        !           730:          {
        !           731:            expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
        !           732:            initlist = tree_cons (NULLT, expr, initlist);
        !           733:          }
        !           734:       }
        !           735: 
        !           736:   if (cat_count)
        !           737:     for (impent = imp_list; impent; impent = impent->next)
        !           738:       {
        !           739:        if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
        !           740:          {
        !           741:            expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
        !           742:            initlist = tree_cons (NULLT, expr, initlist);
        !           743:          }
        !           744:       }
        !           745:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !           746: }
        !           747: 
        !           748: /*
        !           749:  *     struct objc_symtab {
        !           750:  *             long sel_ref_cnt;
        !           751:  *             char *refs;
        !           752:  *             long cls_def_cnt;
        !           753:  *             long cat_def_cnt;
        !           754:  *             void *defs[cls_def_cnt + cat_def_cnt];
        !           755:  *     };
        !           756:  */
        !           757: static tree
        !           758: init_objc_symtab ()
        !           759: {
        !           760:   tree initlist;
        !           761: 
        !           762:   /* sel_ref_cnt = { ..., 5, ... } */
        !           763: 
        !           764:   if (sel_ref_chain)
        !           765:     initlist = build_tree_list (NULLT, build_int_2 (max_selector_index, 0));
        !           766:   else
        !           767:     initlist = build_tree_list (NULLT, build_int_2 (0, 0));
        !           768: 
        !           769:   /* refs = { ..., _OBJC_SELECTOR_REFERENCES, ... } */
        !           770: 
        !           771: #ifndef OBJC_NONUNIQUE_SELECTORS
        !           772:   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !           773: #else
        !           774:   if (sel_ref_chain)
        !           775:     initlist = tree_cons (NULLT, _OBJC_SELECTOR_REFERENCES_decl, initlist);
        !           776:   else
        !           777:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !           778: #endif
        !           779: 
        !           780:   /* cls_def_cnt = { ..., 5, ... } */
        !           781: 
        !           782:   initlist = tree_cons (NULLT, build_int_2 (imp_count, 0), initlist);
        !           783: 
        !           784:   /* cat_def_cnt = { ..., 5, ... } */
        !           785: 
        !           786:   initlist = tree_cons (NULLT, build_int_2 (cat_count, 0), initlist);
        !           787: 
        !           788:   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
        !           789: 
        !           790:   if (imp_count || cat_count)
        !           791:     initlist = tree_cons (NULLT, init_def_list (), initlist);
        !           792: 
        !           793:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !           794: }
        !           795: 
        !           796: static void
        !           797: forward_declare_categories ()
        !           798: {
        !           799:   struct imp_entry *impent;
        !           800:   tree sav = implementation_context;
        !           801:   for (impent = imp_list; impent; impent = impent->next)
        !           802:     {
        !           803:       if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
        !           804:        {
        !           805:          tree sc_spec, decl_specs, decl;
        !           806: 
        !           807:          sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
        !           808:          decl_specs = tree_cons (NULLT, objc_category_template, sc_spec);
        !           809: 
        !           810:          implementation_context = impent->imp_context;
        !           811:          impent->class_decl = define_decl (
        !           812:                                            synth_id_with_class_suffix ("_OBJC_CATEGORY"),
        !           813:                                            decl_specs);
        !           814:        }
        !           815:     }
        !           816:   implementation_context = sav;
        !           817: }
        !           818: 
        !           819: static void
        !           820: generate_objc_symtab_decl ()
        !           821: {
        !           822:   tree sc_spec;
        !           823: 
        !           824:   if (!objc_category_template)
        !           825:     build_category_template ();
        !           826: 
        !           827:   /* forward declare categories */
        !           828:   if (cat_count)
        !           829:     forward_declare_categories ();
        !           830: 
        !           831:   if (!objc_symtab_template)
        !           832:     build_objc_symtab_template ();
        !           833: 
        !           834:   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
        !           835: 
        !           836:   _OBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
        !           837:                                   tree_cons (NULLT, objc_symtab_template, sc_spec), 1);
        !           838: 
        !           839:   finish_decl (_OBJC_SYMBOLS_decl, init_objc_symtab (), NULLT);
        !           840: }
        !           841: 
        !           842: /*
        !           843:  *     tree_node------->tree_node----->...
        !           844:  *          |                |
        !           845:  *          | (value)        | (value)
        !           846:  *          |                |
        !           847:  *       expr             expr
        !           848:  */
        !           849: static tree
        !           850: init_module_descriptor ()
        !           851: {
        !           852:   tree initlist, expr;
        !           853: 
        !           854:   /* version = { 1, ... } */
        !           855: 
        !           856:   expr = build_int_2 (OBJC_VERSION, 0);
        !           857:   initlist = build_tree_list (NULLT, expr);
        !           858: 
        !           859:   /* size = { ..., sizeof (struct objc_module), ... } */
        !           860: 
        !           861:   expr = build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_module_template)) /
        !           862:                      BITS_PER_UNIT, 0);
        !           863:   initlist = tree_cons (NULLT, expr, initlist);
        !           864: 
        !           865:   /* name = { ..., "foo.m", ... } */
        !           866: 
        !           867:   expr = build_msg_pool_reference (
        !           868:                                   add_objc_string (get_identifier (input_filename)));
        !           869:   initlist = tree_cons (NULLT, expr, initlist);
        !           870: 
        !           871:   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
        !           872: 
        !           873:   if (_OBJC_SYMBOLS_decl)
        !           874:     expr = build_unary_op (ADDR_EXPR, _OBJC_SYMBOLS_decl, 0);
        !           875:   else
        !           876:     expr = build_int_2 (0, 0);
        !           877:   initlist = tree_cons (NULLT, expr, initlist);
        !           878: 
        !           879:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !           880: }
        !           881: 
        !           882: /* Write out the data structures to describe Objective C classes defined.
        !           883:    If appropriate, compile and output a setup function to initialize them.
        !           884:    Return a string which is the name of a function to call to initialize
        !           885:    the Objective C data structures for this file (and perhaps for other files
        !           886:    also).  */
        !           887: 
        !           888: static char *
        !           889: build_module_descriptor ()
        !           890: {
        !           891:   tree decl_specs, field_decl, field_decl_chain;
        !           892: 
        !           893:   objc_module_template = start_struct (RECORD_TYPE, get_identifier (_TAG_MODULE));
        !           894: 
        !           895:   /* long version; */
        !           896: 
        !           897:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !           898:   field_decl = get_identifier ("version");
        !           899:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           900:   field_decl_chain = field_decl;
        !           901: 
        !           902:   /* long  size; */
        !           903: 
        !           904:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !           905:   field_decl = get_identifier ("size");
        !           906:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           907:   chainon (field_decl_chain, field_decl);
        !           908: 
        !           909:   /* char  *name; */
        !           910: 
        !           911:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !           912:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
        !           913:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           914:   chainon (field_decl_chain, field_decl);
        !           915: 
        !           916:   /* struct objc_symtab *symtab; */
        !           917: 
        !           918:   decl_specs = get_identifier (_TAG_SYMTAB);
        !           919:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
        !           920:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("symtab"));
        !           921:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !           922:   chainon (field_decl_chain, field_decl);
        !           923: 
        !           924:   finish_struct (objc_module_template, field_decl_chain);
        !           925: 
        !           926:   /* create an instance of "objc_module" */
        !           927: 
        !           928:   decl_specs = tree_cons (NULLT, objc_module_template,
        !           929:                          build_tree_list (NULLT, ridpointers[(int) RID_STATIC]));
        !           930: 
        !           931:   _OBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
        !           932:                                   decl_specs, 1);
        !           933: 
        !           934:   finish_decl (_OBJC_MODULES_decl, init_module_descriptor (), NULLT);
        !           935: 
        !           936:   /* Mark the decl as used to avoid "defined but not used" warning. */
        !           937:   TREE_USED (_OBJC_MODULES_decl) = 1;
        !           938: 
        !           939:   /* Generate a constructor call for the module descriptor. 
        !           940:      This code was generated by reading the grammar rules
        !           941:      of c-parse.y;  Therefore, it may not be the most efficient
        !           942:      way of generating the requisite code. */
        !           943: #ifndef NEXT_OBJC_RUNTIME
        !           944:   {
        !           945:     tree parms, function_decl, decelerator, void_list_node;
        !           946:     tree function_type;
        !           947:     char *buf;
        !           948:     char *global_object_name = 0;
        !           949:     tree t;
        !           950: 
        !           951:     /* Use a global object (which is already required to be unique over
        !           952:        the program) rather than the file name (which imposes extra
        !           953:        constraints).  -- [email protected], 10 Jan 1990.  */
        !           954: 
        !           955:     /* Find the name of some global object defined in this file.  */
        !           956:     for (t = getdecls (); t; t = TREE_CHAIN (t))
        !           957:       if (TREE_PUBLIC (t) && !TREE_EXTERNAL (t) && DECL_INITIAL (t) != 0)
        !           958:        {
        !           959:          global_object_name = IDENTIFIER_POINTER (DECL_NAME (t));
        !           960:          break;
        !           961:        }
        !           962: 
        !           963:     /* If none, use the name of the file.  */
        !           964:     if (!global_object_name)
        !           965:       {
        !           966:        char *p, *q;
        !           967:        global_object_name
        !           968:          = (char *) alloca (strlen (main_input_filename) + 1);
        !           969: 
        !           970:        p = main_input_filename;
        !           971:        q = global_object_name;
        !           972: 
        !           973:        /* Replace any weird characters in the file name.  */
        !           974:        for (; *p; p++)
        !           975:          if (! ((*p >= '0' && *p <= '9')
        !           976:                 || (*p >= 'A' && *p <= 'Z')
        !           977:                 || (*p >= 'a' && *p <= 'z')))
        !           978:            *q++ = '_';
        !           979:          else
        !           980:            *q++ = *p;
        !           981:        *q = 0;
        !           982:       }
        !           983: 
        !           984:     /* Make the constructor name from the name we have found.  */
        !           985:     buf = (char *) xmalloc (sizeof (CONSTRUCTOR_NAME_FORMAT)
        !           986:                            + strlen (global_object_name));
        !           987:     sprintf (buf, CONSTRUCTOR_NAME_FORMAT, global_object_name);
        !           988: 
        !           989:     /* Declare void __objc_execClass (void*); */
        !           990: 
        !           991:     void_list_node = build_tree_list (NULL_TREE, void_type_node);
        !           992:     function_type
        !           993:       = build_function_type (void_type_node,  
        !           994:                             tree_cons (NULL_TREE, ptr_type_node,  
        !           995:                                        void_list_node));
        !           996:     function_decl = build_decl (FUNCTION_DECL,  
        !           997:                                get_identifier ("__objc_execClass"),  
        !           998:                                function_type);
        !           999:     TREE_EXTERNAL (function_decl) = 1;
        !          1000:     TREE_PUBLIC (function_decl) = 1;
        !          1001:     pushdecl (function_decl);
        !          1002:     rest_of_decl_compilation (function_decl, 0, 0, 0);
        !          1003: 
        !          1004:     parms
        !          1005:       = build_tree_list (NULLT,
        !          1006:                         build_unary_op (ADDR_EXPR, _OBJC_MODULES_decl, 0));
        !          1007:     decelerator = build_function_call (function_decl, parms);
        !          1008: 
        !          1009:     /* void __objc_file_init () {objc_execClass(&L_OBJC_MODULES);}  */
        !          1010: 
        !          1011:     start_function (void_list_node,
        !          1012:                    build_parse_node (CALL_EXPR, get_identifier (buf),
        !          1013:                                      /* This has the format of the output
        !          1014:                                         of get_parm_info.  */
        !          1015:                                      tree_cons (NULL_TREE, NULL_TREE,
        !          1016:                                                 void_list_node),
        !          1017:                                      NULL_TREE),
        !          1018:                    0, 0);
        !          1019: #if 0 /* This should be turned back on later
        !          1020:         for the systems where collect is not needed.  */
        !          1021:     /* Make these functions nonglobal
        !          1022:        so each file can use the same name.  */
        !          1023:     TREE_PUBLIC (current_function_decl) = 0;
        !          1024: #endif
        !          1025:     TREE_USED (current_function_decl) = 1;
        !          1026:     store_parm_decls ();
        !          1027: 
        !          1028:     assemble_external (function_decl);
        !          1029:     c_expand_expr_stmt (decelerator);
        !          1030: 
        !          1031:     finish_function (0);
        !          1032: 
        !          1033:     /* Return the name of the constructor function.  */
        !          1034:     return buf;
        !          1035:   }
        !          1036: #else /* NEXT_OBJC_RUNTIME */
        !          1037:   return 0;
        !          1038: #endif /* NEXT_OBJC_RUNTIME */
        !          1039: }
        !          1040: 
        !          1041: /* extern const char _OBJC_STRINGS[]; */
        !          1042: 
        !          1043: static void
        !          1044: generate_forward_declaration_to_string_table ()
        !          1045: {
        !          1046:   tree sc_spec, decl_specs, expr_decl;
        !          1047: 
        !          1048:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_EXTERN], NULLT);
        !          1049:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
        !          1050: 
        !          1051:   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
        !          1052: 
        !          1053:   _OBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
        !          1054: }
        !          1055: 
        !          1056: /* static char _OBJC_STRINGS[] = "..."; */
        !          1057: 
        !          1058: static void
        !          1059: build_message_selector_pool ()
        !          1060: {
        !          1061:   tree sc_spec, decl_specs, expr_decl;
        !          1062:   tree chain, string_expr;
        !          1063:   int goolengthtmp = 0, msg_pool_size = 0;
        !          1064:   char *string_goo;
        !          1065: 
        !          1066:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          1067:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
        !          1068: 
        !          1069:   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
        !          1070: 
        !          1071:   _OBJC_STRINGS_decl = start_decl (expr_decl, decl_specs, 1);
        !          1072: 
        !          1073:   for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
        !          1074:     msg_pool_size += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
        !          1075: 
        !          1076:   msg_pool_size++;
        !          1077: 
        !          1078:   string_goo = (char *)xmalloc (msg_pool_size);
        !          1079:   bzero (string_goo, msg_pool_size);
        !          1080: 
        !          1081:   for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
        !          1082:     {
        !          1083:       strcpy (string_goo + goolengthtmp, IDENTIFIER_POINTER (TREE_VALUE (chain)));
        !          1084:       goolengthtmp += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
        !          1085:     }
        !          1086: 
        !          1087:   string_expr = my_build_string (msg_pool_size, string_goo);
        !          1088: 
        !          1089:   finish_decl (_OBJC_STRINGS_decl, string_expr, NULLT);
        !          1090: }
        !          1091: 
        !          1092: /*
        !          1093:  * synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
        !          1094:  *
        !          1095:  * the cast stops the compiler from issuing the following message:
        !          1096:  *
        !          1097:  * grok.m: warning: initialization of non-const * pointer from const *
        !          1098:  * grok.m: warning: initialization between incompatible pointer types
        !          1099:  */
        !          1100: static tree
        !          1101: build_msg_pool_reference (offset)
        !          1102:      int offset;
        !          1103: {
        !          1104:   tree expr = build_int_2 (offset, 0);
        !          1105:   tree cast;
        !          1106: 
        !          1107:   expr = build_array_ref (_OBJC_STRINGS_decl, expr);
        !          1108:   expr = build_unary_op (ADDR_EXPR, expr, 0);
        !          1109: 
        !          1110:   cast = build_tree_list (build_tree_list (NULLT, ridpointers[(int) RID_CHAR]),
        !          1111:                          build1 (INDIRECT_REF, NULLT, NULLT));
        !          1112:   TREE_TYPE (expr) = groktypename (cast);
        !          1113:   return expr;
        !          1114: }
        !          1115: 
        !          1116: #ifndef OBJC_NONUNIQUE_SELECTORS
        !          1117: static tree
        !          1118: build_selector_reference (idx)
        !          1119:       int idx;
        !          1120: {
        !          1121:   tree ref, decl, name, ident;
        !          1122:   char buf[256];
        !          1123:   struct obstack *save_current_obstack = current_obstack;
        !          1124:   struct obstack *save_rtl_obstack = rtl_obstack;
        !          1125: 
        !          1126:   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
        !          1127: 
        !          1128:   /* new stuff */
        !          1129:   rtl_obstack = current_obstack = &permanent_obstack;
        !          1130:   ident = get_identifier (buf);
        !          1131: 
        !          1132:   if (IDENTIFIER_GLOBAL_VALUE (ident))
        !          1133:     decl = IDENTIFIER_GLOBAL_VALUE (ident); /* set by pushdecl() */
        !          1134:   else 
        !          1135:     {
        !          1136:       decl = build_decl (VAR_DECL, ident, _selector_type);
        !          1137:       TREE_EXTERNAL (decl) = 1;
        !          1138:       TREE_PUBLIC (decl) = 1;
        !          1139:       TREE_USED (decl) = 1;
        !          1140:   
        !          1141:       make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
        !          1142:       pushdecl_top_level (decl);  /* our `extended/custom' pushdecl in c-decl.c */
        !          1143:     }
        !          1144:   current_obstack = save_current_obstack;
        !          1145:   rtl_obstack = save_rtl_obstack;
        !          1146: 
        !          1147:   return decl;
        !          1148: }
        !          1149: #endif
        !          1150: 
        !          1151: static tree
        !          1152: init_selector (offset)
        !          1153:      int offset;
        !          1154: {
        !          1155:   tree expr = build_msg_pool_reference (offset);
        !          1156:   TREE_TYPE (expr) = _selector_type; /* cast */
        !          1157:   return expr;
        !          1158: }
        !          1159: 
        !          1160: static void
        !          1161: build_selector_translation_table ()
        !          1162: {
        !          1163:   tree sc_spec, decl_specs, expr_decl;
        !          1164:   tree chain, initlist = NULLT;
        !          1165:   int offset = 0;
        !          1166: #ifndef OBJC_NONUNIQUE_SELECTORS
        !          1167:   tree decl, var_decl;
        !          1168:   int idx = 0;
        !          1169:   char buf[256];
        !          1170: #else/
        !          1171: 
        !          1172:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          1173: 
        !          1174: #ifdef OBJC_INT_SELECTORS
        !          1175:   /* static unsigned int _OBJC_SELECTOR_REFERENCES[] = { 1, 2, ... }; */
        !          1176:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], sc_spec);
        !          1177:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !          1178:   expr_decl = _OBJC_SELECTOR_REFERENCES_id;
        !          1179: #else /* not OBJC_INT_SELECTORS */
        !          1180:   /* static struct objc_selector *_OBJC_SELECTOR_REFERENCES[] = { 1, 2, .}; */
        !          1181:   decl_specs = build_tree_list (NULLT,
        !          1182:                                xref_tag (RECORD_TYPE,
        !          1183:                                          get_identifier (TAG_SELECTOR)));
        !          1184:   expr_decl = build1 (INDIRECT_REF, NULLT, _OBJC_SELECTOR_REFERENCES_id);
        !          1185: #endif /* not OBJC_INT_SELECTORS */
        !          1186: 
        !          1187:   expr_decl = build_nt (ARRAY_REF, expr_decl, NULLT);
        !          1188:   _OBJC_SELECTOR_REFERENCES_decl = start_decl (expr_decl, decl_specs, 1);
        !          1189: #endif
        !          1190: 
        !          1191:   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
        !          1192:     {
        !          1193:       tree expr;
        !          1194: 
        !          1195: #ifndef OBJC_NONUNIQUE_SELECTORS
        !          1196:       sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
        !          1197:       sc_spec = build_tree_list (NULLT, ridpointers[RID_STATIC]);
        !          1198: 
        !          1199: #ifdef OBJC_INT_SELECTORS
        !          1200:       /* static unsigned int _OBJC_SELECTOR_REFERENCES_n = ...; */
        !          1201:       decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], sc_spec);
        !          1202:       decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !          1203:       var_decl = get_identifier (buf);
        !          1204: #else /* not OBJC_INT_SELECTORS */
        !          1205:       /* static struct objc_selector *_OBJC_SELECTOR_REFERENCES_n = ...; */
        !          1206:       decl_specs = tree_cons (NULLT,
        !          1207:                              xref_tag (RECORD_TYPE,
        !          1208:                                        get_identifier (TAG_SELECTOR)),
        !          1209:                              sc_spec);
        !          1210:       var_decl = build1 (INDIRECT_REF, NULLT, get_identifier (buf));
        !          1211: #endif /* not OBJC_INT_SELECTORS */
        !          1212: 
        !          1213:       /* the `decl' that is returned from start_decl is the one that we
        !          1214:        * forward declared in `build_selector_reference()'
        !          1215:        */
        !          1216:       decl = start_decl (var_decl, decl_specs, 1); 
        !          1217: #endif
        !          1218: 
        !          1219:       expr = init_selector (offset);
        !          1220: 
        !          1221:       /* add one for the '\0' character */
        !          1222:       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
        !          1223: 
        !          1224: #ifndef OBJC_NONUNIQUE_SELECTORS
        !          1225:       finish_decl (decl, expr, NULLT);
        !          1226:       idx++;
        !          1227: #else
        !          1228:       initlist = tree_cons (NULLT, expr, initlist);
        !          1229: #endif
        !          1230:     }
        !          1231: 
        !          1232: #ifdef OBJC_NONUNIQUE_SELECTORS
        !          1233:   initlist = build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          1234:   finish_decl (_OBJC_SELECTOR_REFERENCES_decl, initlist, NULLT);
        !          1235: #endif
        !          1236: }
        !          1237: 
        !          1238: static void
        !          1239: add_class_reference (ident)
        !          1240:      tree ident;
        !          1241: {
        !          1242:   tree chain;
        !          1243: 
        !          1244:   if (chain = cls_ref_chain)
        !          1245:     {
        !          1246:       tree tail;
        !          1247:       do
        !          1248:         {
        !          1249:          if (ident == TREE_VALUE (chain))
        !          1250:            return;
        !          1251: 
        !          1252:          tail = chain;
        !          1253:          chain = TREE_CHAIN (chain);
        !          1254:         }
        !          1255:       while (chain);
        !          1256: 
        !          1257:       /* append to the end of the list */
        !          1258:       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
        !          1259:     }
        !          1260:   else
        !          1261:     cls_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
        !          1262: }
        !          1263: 
        !          1264: /*
        !          1265:  * sel_ref_chain is a list whose "value" fields will be instances of
        !          1266:  * identifier_node that represent the selector.
        !          1267:  */
        !          1268: static int
        !          1269: add_selector_reference (ident)
        !          1270:      tree ident;
        !          1271: {
        !          1272:   tree chain;
        !          1273:   int index = 0;
        !          1274: 
        !          1275:   /* this adds it to sel_refdef_chain, the global pool of selectors */
        !          1276:   add_objc_string (ident);
        !          1277: 
        !          1278:   if (chain = sel_ref_chain)
        !          1279:     {
        !          1280:       tree tail;
        !          1281:       do
        !          1282:         {
        !          1283:          if (ident == TREE_VALUE (chain))
        !          1284:            return index;
        !          1285: 
        !          1286:          index++;
        !          1287:          tail = chain;
        !          1288:          chain = TREE_CHAIN (chain);
        !          1289:         }
        !          1290:       while (chain);
        !          1291: 
        !          1292:       /* append to the end of the list */
        !          1293:       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
        !          1294:     }
        !          1295:   else
        !          1296:     sel_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
        !          1297: 
        !          1298:   max_selector_index++;
        !          1299:   return index;
        !          1300: }
        !          1301: 
        !          1302: /*
        !          1303:  * sel_refdef_chain is a list whose "value" fields will be instances of
        !          1304:  * identifier_node that represent the selector. It returns the offset of
        !          1305:  * the selector from the beginning of the _OBJC_STRINGS pool. This offset
        !          1306:  * is typically used by "init_selector ()" during code generation.
        !          1307:  */
        !          1308: static int
        !          1309: add_objc_string (ident)
        !          1310:      tree ident;
        !          1311: {
        !          1312:   tree chain;
        !          1313:   int offset = 0;
        !          1314: 
        !          1315:   if (chain = sel_refdef_chain)
        !          1316:     {
        !          1317:       tree tail;
        !          1318:       do
        !          1319:         {
        !          1320:          if (ident == TREE_VALUE (chain))
        !          1321:            return offset;
        !          1322: 
        !          1323:          /* add one for the '\0' character */
        !          1324:          offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
        !          1325:          tail = chain;
        !          1326:          chain = TREE_CHAIN (chain);
        !          1327:         }
        !          1328:       while (chain);
        !          1329: 
        !          1330:       /* append to the end of the list */
        !          1331:       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
        !          1332:     }
        !          1333:   else
        !          1334:     sel_refdef_chain = perm_tree_cons (NULLT, ident, NULLT);
        !          1335: 
        !          1336:   return offset;
        !          1337: }
        !          1338: 
        !          1339: tree
        !          1340: lookup_interface (ident)
        !          1341:      tree ident;
        !          1342: {
        !          1343:   tree chain;
        !          1344: 
        !          1345:   for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
        !          1346:     {
        !          1347:       if (ident == CLASS_NAME (chain))
        !          1348:        return chain;
        !          1349:     }
        !          1350:   return NULLT;
        !          1351: }
        !          1352: 
        !          1353: static tree
        !          1354: objc_copy_list (list, head)
        !          1355:      tree list;
        !          1356:      tree *head;
        !          1357: {
        !          1358:   tree newlist = NULL_TREE, tail = NULL_TREE;
        !          1359: 
        !          1360:   while (list)
        !          1361:     {
        !          1362:       tail = copy_node (list);
        !          1363: 
        !          1364:       /* the following statement fixes a bug when inheriting instance
        !          1365:         variables that are declared to be bitfields. finish_struct () expects
        !          1366:         to find the width of the bitfield in DECL_INITIAL (), which it
        !          1367:         nulls out after processing the decl of the super class...rather
        !          1368:         than change the way finish_struct () works (which is risky),
        !          1369:         I create the situation it expects...s.naroff (7/23/89).
        !          1370:         */
        !          1371:       if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
        !          1372:        DECL_INITIAL (tail) = build_int_2 (DECL_FRAME_SIZE (tail), 0);
        !          1373: 
        !          1374:       newlist = chainon (newlist, tail);
        !          1375:       list = TREE_CHAIN (list);
        !          1376:     }
        !          1377:   *head = newlist;
        !          1378:   return tail;
        !          1379: }
        !          1380: 
        !          1381: /* used by:
        !          1382:  * build_private_template (), get_class_ivars (), and get_static_reference ().
        !          1383:  */
        !          1384: static tree
        !          1385: build_ivar_chain (interface)
        !          1386:      tree interface;
        !          1387: {
        !          1388:   tree my_name, super_name, ivar_chain;
        !          1389: 
        !          1390:   my_name = CLASS_NAME (interface);
        !          1391:   super_name = CLASS_SUPER_NAME (interface);
        !          1392: 
        !          1393:   /* "leaf" ivars never get copied...there is no reason to. */
        !          1394:   ivar_chain = CLASS_IVARS (interface);
        !          1395: 
        !          1396:   while (super_name)
        !          1397:     {
        !          1398:       tree op1;
        !          1399:       tree super_interface = lookup_interface (super_name);
        !          1400: 
        !          1401:       if (!super_interface)
        !          1402:         {
        !          1403:          /* fatal did not work with 2 args...should fix */
        !          1404:          error ("Cannot find interface declaration for `%s', superclass of `%s'",
        !          1405:                 IDENTIFIER_POINTER (super_name), IDENTIFIER_POINTER (my_name));
        !          1406:          exit (34);
        !          1407:         }
        !          1408:       if (super_interface == interface)
        !          1409:         {
        !          1410:           fatal ("Circular inheritance in interface declaration for `%s'",
        !          1411:                  IDENTIFIER_POINTER (super_name));
        !          1412:         }
        !          1413:       interface = super_interface;
        !          1414:       my_name = CLASS_NAME (interface);
        !          1415:       super_name = CLASS_SUPER_NAME (interface);
        !          1416: 
        !          1417:       op1 = CLASS_IVARS (interface);
        !          1418:       if (op1)
        !          1419:         {
        !          1420:          tree head, tail = objc_copy_list (op1, &head);
        !          1421: 
        !          1422:          /* prepend super class ivars...make a copy of the list, we
        !          1423:           * do not want to alter the original.
        !          1424:           */
        !          1425:          TREE_CHAIN (tail) = ivar_chain;
        !          1426:          ivar_chain = head;
        !          1427:         }
        !          1428:     }
        !          1429:   return ivar_chain;
        !          1430: }
        !          1431: 
        !          1432: /*
        !          1433:  *  struct <classname> {
        !          1434:  *    struct objc_class *isa;
        !          1435:  *    ...
        !          1436:  *  };
        !          1437:  */
        !          1438: static tree
        !          1439: build_private_template (class)
        !          1440:      tree class;
        !          1441: {
        !          1442:   tree ivar_context;
        !          1443: 
        !          1444:   if (CLASS_STATIC_TEMPLATE (class))
        !          1445:     {
        !          1446:       _PRIVATE_record = CLASS_STATIC_TEMPLATE (class);
        !          1447:       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
        !          1448:     }
        !          1449:   else
        !          1450:     {
        !          1451:       _PRIVATE_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
        !          1452: 
        !          1453:       ivar_context = build_ivar_chain (class);
        !          1454: 
        !          1455:       finish_struct (_PRIVATE_record, ivar_context);
        !          1456: 
        !          1457:       CLASS_STATIC_TEMPLATE (class) = _PRIVATE_record;
        !          1458: 
        !          1459:       /* mark this record as class template - for class type checking */
        !          1460:       TREE_STATIC_TEMPLATE (_PRIVATE_record) = 1;
        !          1461:     }
        !          1462:   instance_type = groktypename (
        !          1463:                                build_tree_list (build_tree_list (NULLT, _PRIVATE_record),
        !          1464:                                                 build1 (INDIRECT_REF, NULLT, NULLT)));
        !          1465:   return ivar_context;
        !          1466: }
        !          1467: 
        !          1468: /*
        !          1469:  *  struct objc_category {
        !          1470:  *    char *category_name;
        !          1471:  *    char *class_name;
        !          1472:  *    struct objc_method_list *instance_methods;
        !          1473:  *    struct objc_method_list *class_methods;
        !          1474:  *  };
        !          1475:  */
        !          1476: static void
        !          1477: build_category_template ()
        !          1478: {
        !          1479:   tree decl_specs, field_decl, field_decl_chain;
        !          1480: 
        !          1481:   objc_category_template = start_struct (RECORD_TYPE,
        !          1482:                                         get_identifier (_TAG_CATEGORY));
        !          1483:   /* char *category_name; */
        !          1484: 
        !          1485:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          1486:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("category_name"));
        !          1487:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1488:   field_decl_chain = field_decl;
        !          1489: 
        !          1490:   /* char *class_name; */
        !          1491: 
        !          1492:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          1493:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_name"));
        !          1494:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1495:   chainon (field_decl_chain, field_decl);
        !          1496: 
        !          1497:   /* struct objc_method_list *instance_methods; */
        !          1498: 
        !          1499:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          1500:                                                 get_identifier (_TAG_METHOD_LIST)));
        !          1501:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
        !          1502:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1503:   chainon (field_decl_chain, field_decl);
        !          1504: 
        !          1505:   /* struct objc_method_list *class_methods; */
        !          1506: 
        !          1507:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          1508:                                                 get_identifier (_TAG_METHOD_LIST)));
        !          1509:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
        !          1510:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1511:   chainon (field_decl_chain, field_decl);
        !          1512: 
        !          1513:   finish_struct (objc_category_template, field_decl_chain);
        !          1514: }
        !          1515: 
        !          1516: /*
        !          1517:  *  struct objc_class {
        !          1518:  *    struct objc_class *isa;
        !          1519:  *    struct objc_class *super_class;
        !          1520:  *    char *name;
        !          1521:  *    long version;
        !          1522:  *    long info;
        !          1523:  *    long instance_size;
        !          1524:  *    struct objc_ivar_list *ivars;
        !          1525:  *    struct objc_method_list *methods;
        !          1526:  *    struct objc_cache *cache;
        !          1527:  *  };
        !          1528:  */
        !          1529: static void
        !          1530: build_class_template ()
        !          1531: {
        !          1532:   tree decl_specs, field_decl, field_decl_chain;
        !          1533: 
        !          1534:   objc_class_template = start_struct (RECORD_TYPE, get_identifier (_TAG_CLASS));
        !          1535: 
        !          1536:   /* struct objc_class *isa; */
        !          1537: 
        !          1538:   decl_specs = build_tree_list (NULLT, objc_class_template);
        !          1539:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
        !          1540:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1541:   field_decl_chain = field_decl;
        !          1542: 
        !          1543:   /* struct objc_class *super_class; */
        !          1544: 
        !          1545:   decl_specs = build_tree_list (NULLT, objc_class_template);
        !          1546:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("super_class"));
        !          1547:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1548:   chainon (field_decl_chain, field_decl);
        !          1549: 
        !          1550:   /* char *name; */
        !          1551: 
        !          1552:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          1553:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
        !          1554:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1555:   chainon (field_decl_chain, field_decl);
        !          1556: 
        !          1557:   /* long version; */
        !          1558: 
        !          1559:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !          1560:   field_decl = get_identifier ("version");
        !          1561:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1562:   chainon (field_decl_chain, field_decl);
        !          1563: 
        !          1564:   /* long info; */
        !          1565: 
        !          1566:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !          1567:   field_decl = get_identifier ("info");
        !          1568:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1569:   chainon (field_decl_chain, field_decl);
        !          1570: 
        !          1571:   /* long instance_size; */
        !          1572: 
        !          1573:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !          1574:   field_decl = get_identifier ("instance_size");
        !          1575:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1576:   chainon (field_decl_chain, field_decl);
        !          1577: 
        !          1578:   /* struct objc_ivar_list *ivars; */
        !          1579: 
        !          1580:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          1581:                                                 get_identifier (_TAG_IVAR_LIST)));
        !          1582:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivars"));
        !          1583:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1584:   chainon (field_decl_chain, field_decl);
        !          1585: 
        !          1586:   /* struct objc_method_list *methods; */
        !          1587: 
        !          1588:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          1589:                                                 get_identifier (_TAG_METHOD_LIST)));
        !          1590:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("methods"));
        !          1591:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1592:   chainon (field_decl_chain, field_decl);
        !          1593: 
        !          1594:   /* struct objc_cache *cache; */
        !          1595: 
        !          1596:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          1597:                                                 get_identifier ("objc_cache")));
        !          1598:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("cache"));
        !          1599:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1600:   chainon (field_decl_chain, field_decl);
        !          1601: 
        !          1602:   finish_struct (objc_class_template, field_decl_chain);
        !          1603: }
        !          1604: 
        !          1605: /*
        !          1606:  * generate appropriate forward declarations for an implementation
        !          1607:  */
        !          1608: static void
        !          1609: synth_forward_declarations ()
        !          1610: {
        !          1611:   tree sc_spec, decl_specs, factory_id, anId;
        !          1612: 
        !          1613:   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
        !          1614: 
        !          1615:   anId = synth_id_with_class_suffix ("_OBJC_CLASS");
        !          1616: 
        !          1617:   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
        !          1618:   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
        !          1619:   _OBJC_CLASS_decl = define_decl (anId, decl_specs);
        !          1620: 
        !          1621:   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
        !          1622: 
        !          1623:   anId = synth_id_with_class_suffix ("_OBJC_METACLASS");
        !          1624: 
        !          1625:   _OBJC_METACLASS_decl = define_decl (anId, decl_specs);
        !          1626: 
        !          1627:   /* pre-build the following entities - for speed/convenience. */
        !          1628: 
        !          1629:   anId = get_identifier ("super_class");
        !          1630:   _clsSuper_ref = build_component_ref (_OBJC_CLASS_decl, anId);
        !          1631:   __clsSuper_ref = build_component_ref (_OBJC_METACLASS_decl, anId);
        !          1632: }
        !          1633: 
        !          1634: static void
        !          1635: error_with_ivar (message, decl, rawdecl)
        !          1636:      char *message;
        !          1637:      tree decl;
        !          1638:      tree rawdecl;
        !          1639: {
        !          1640:   count_error (0);
        !          1641:   fprintf (stderr, "%s:%d: ",
        !          1642:           DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
        !          1643:   bzero (errbuf, BUFSIZE);
        !          1644:   fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
        !          1645: }
        !          1646: 
        !          1647: #define USERTYPE(t)    (TREE_CODE (t) == RECORD_TYPE || \
        !          1648:                         TREE_CODE (t) == UNION_TYPE ||  \
        !          1649:                         TREE_CODE (t) == ENUMERAL_TYPE)
        !          1650: 
        !          1651: static void
        !          1652: check_ivars (inter, imp)
        !          1653:      tree inter;
        !          1654:      tree imp;
        !          1655: {
        !          1656:   tree intdecls = CLASS_IVARS (inter);
        !          1657:   tree impdecls = CLASS_IVARS (imp);
        !          1658:   tree rawintdecls = CLASS_RAW_IVARS (inter);
        !          1659:   tree rawimpdecls = CLASS_RAW_IVARS (imp);
        !          1660: 
        !          1661:   while (1)
        !          1662:     {
        !          1663:       tree t1, t2;
        !          1664: 
        !          1665:       if (intdecls == 0 && impdecls == 0)
        !          1666:        break;
        !          1667:       if (intdecls == 0 || impdecls == 0)
        !          1668:        {
        !          1669:          error ("inconsistent instance variable specification");
        !          1670:          break;
        !          1671:        }
        !          1672:       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
        !          1673: 
        !          1674:       if (!comptypes (t1, t2))
        !          1675:        {
        !          1676:          if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
        !          1677:            {
        !          1678:              error_with_ivar ("conflicting instance variable type",
        !          1679:                               impdecls, rawimpdecls);
        !          1680:              error_with_ivar ("previous declaration of",
        !          1681:                               intdecls, rawintdecls);
        !          1682:            }
        !          1683:          else                  /* both the type and the name don't match */
        !          1684:            {
        !          1685:              error ("inconsistent instance variable specification");
        !          1686:              break;
        !          1687:            }
        !          1688:        }
        !          1689:       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
        !          1690:        {
        !          1691:          error_with_ivar ("conflicting instance variable name",
        !          1692:                           impdecls, rawimpdecls);
        !          1693:          error_with_ivar ("previous declaration of",
        !          1694:                           intdecls, rawintdecls);
        !          1695:        }
        !          1696:       intdecls = TREE_CHAIN (intdecls);
        !          1697:       impdecls = TREE_CHAIN (impdecls);
        !          1698:       rawintdecls = TREE_CHAIN (rawintdecls);
        !          1699:       rawimpdecls = TREE_CHAIN (rawimpdecls);
        !          1700:     }
        !          1701: }
        !          1702: 
        !          1703: /*
        !          1704:  *     struct objc_super {
        !          1705:  *             id self;
        !          1706:  *             struct objc_class *class;
        !          1707:  *     };
        !          1708:  */
        !          1709: static tree
        !          1710: build_super_template ()
        !          1711: {
        !          1712:   tree record, decl_specs, field_decl, field_decl_chain;
        !          1713: 
        !          1714:   record = start_struct (RECORD_TYPE, get_identifier (_TAG_SUPER));
        !          1715: 
        !          1716:   /* struct objc_object *self; */
        !          1717: 
        !          1718:   decl_specs = build_tree_list (NULLT, objc_object_reference);
        !          1719:   field_decl = get_identifier ("self");
        !          1720:   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
        !          1721:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1722:   field_decl_chain = field_decl;
        !          1723: 
        !          1724:   /* struct objc_class *class; */
        !          1725: 
        !          1726:   decl_specs = get_identifier (_TAG_CLASS);
        !          1727:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
        !          1728:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class"));
        !          1729: 
        !          1730:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1731:   chainon (field_decl_chain, field_decl);
        !          1732: 
        !          1733:   finish_struct (record, field_decl_chain);
        !          1734: 
        !          1735:   /* `struct objc_super *' */
        !          1736:   super_type = groktypename (build_tree_list (build_tree_list (NULLT, record),
        !          1737:                                              build1 (INDIRECT_REF, NULLT, NULLT)));
        !          1738:   return record;
        !          1739: }
        !          1740: 
        !          1741: /*
        !          1742:  *     struct objc_ivar {
        !          1743:  *             char *ivar_name;
        !          1744:  *             char *ivar_type;
        !          1745:  *             int ivar_offset;
        !          1746:  *     };
        !          1747:  */
        !          1748: static tree
        !          1749: build_ivar_template ()
        !          1750: {
        !          1751:   tree objc_ivar_id, objc_ivar_record;
        !          1752:   tree decl_specs, field_decl, field_decl_chain;
        !          1753: 
        !          1754:   objc_ivar_id = get_identifier (_TAG_IVAR);
        !          1755:   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
        !          1756: 
        !          1757:   /* char *ivar_name; */
        !          1758: 
        !          1759:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          1760:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_name"));
        !          1761: 
        !          1762:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1763:   field_decl_chain = field_decl;
        !          1764: 
        !          1765:   /* char *ivar_type; */
        !          1766: 
        !          1767:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          1768:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_type"));
        !          1769: 
        !          1770:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1771:   chainon (field_decl_chain, field_decl);
        !          1772: 
        !          1773:   /* int ivar_offset; */
        !          1774: 
        !          1775:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          1776:   field_decl = get_identifier ("ivar_offset");
        !          1777: 
        !          1778:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1779:   chainon (field_decl_chain, field_decl);
        !          1780: 
        !          1781:   finish_struct (objc_ivar_record, field_decl_chain);
        !          1782: 
        !          1783:   return objc_ivar_record;
        !          1784: }
        !          1785: 
        !          1786: /*
        !          1787:  *     struct {
        !          1788:  *             int ivar_count;
        !          1789:  *             struct objc_ivar ivar_list[ivar_count];
        !          1790:  *     };
        !          1791:  */
        !          1792: static tree
        !          1793: build_ivar_list_template (list_type, size)
        !          1794:      tree list_type;
        !          1795:      int size;
        !          1796: {
        !          1797:   tree objc_ivar_list_id, objc_ivar_list_record;
        !          1798:   tree decl_specs, field_decl, field_decl_chain;
        !          1799: 
        !          1800:   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
        !          1801: 
        !          1802:   /* int ivar_count; */
        !          1803: 
        !          1804:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          1805:   field_decl = get_identifier ("ivar_count");
        !          1806: 
        !          1807:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1808:   field_decl_chain = field_decl;
        !          1809: 
        !          1810:   /* struct objc_ivar ivar_list[]; */
        !          1811: 
        !          1812:   decl_specs = build_tree_list (NULLT, list_type);
        !          1813:   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
        !          1814:                         build_int_2 (size, 0));
        !          1815: 
        !          1816:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1817:   chainon (field_decl_chain, field_decl);
        !          1818: 
        !          1819:   finish_struct (objc_ivar_list_record, field_decl_chain);
        !          1820: 
        !          1821:   return objc_ivar_list_record;
        !          1822: }
        !          1823: 
        !          1824: /*
        !          1825:  *     struct {
        !          1826:  *             int method_next;
        !          1827:  *             int method_count;
        !          1828:  *             struct objc_method method_list[method_count];
        !          1829:  *     };
        !          1830:  */
        !          1831: static tree
        !          1832: build_method_list_template (list_type, size)
        !          1833:      tree list_type;
        !          1834:      int size;
        !          1835: {
        !          1836:   tree objc_ivar_list_id, objc_ivar_list_record;
        !          1837:   tree decl_specs, field_decl, field_decl_chain;
        !          1838: 
        !          1839:   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
        !          1840: 
        !          1841:   /* int method_next; */
        !          1842: 
        !          1843:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          1844:   field_decl = get_identifier ("method_next");
        !          1845: 
        !          1846:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1847:   field_decl_chain = field_decl;
        !          1848: 
        !          1849:   /* int method_count; */
        !          1850: 
        !          1851:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          1852:   field_decl = get_identifier ("method_count");
        !          1853: 
        !          1854:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1855:   chainon (field_decl_chain, field_decl);
        !          1856: 
        !          1857:   /* struct objc_method method_list[]; */
        !          1858: 
        !          1859:   decl_specs = build_tree_list (NULLT, list_type);
        !          1860:   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
        !          1861:                         build_int_2 (size, 0));
        !          1862: 
        !          1863:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1864:   chainon (field_decl_chain, field_decl);
        !          1865: 
        !          1866:   finish_struct (objc_ivar_list_record, field_decl_chain);
        !          1867: 
        !          1868:   return objc_ivar_list_record;
        !          1869: }
        !          1870: 
        !          1871: static tree
        !          1872: build_ivar_list_initializer (field_decl, size)
        !          1873:      tree field_decl;
        !          1874:      int *size;
        !          1875: {
        !          1876:   tree initlist = NULLT;
        !          1877: 
        !          1878:   do
        !          1879:     {
        !          1880:       int offset;
        !          1881: 
        !          1882:     /* set name */
        !          1883:     if (DECL_NAME (field_decl))
        !          1884:       {
        !          1885:         offset = add_objc_string (DECL_NAME (field_decl));
        !          1886:         initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
        !          1887:       }
        !          1888:     else
        !          1889:       {
        !          1890:         /* unnamed bit-field ivar (yuck). */
        !          1891:         initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          1892:       }
        !          1893: 
        !          1894:       /* set type */
        !          1895:       bzero (utlbuf, BUFSIZE);
        !          1896:       encode_field_decl (field_decl, utlbuf, OBJC_ENCODE_DONT_INLINE_DEFS);
        !          1897: 
        !          1898:       offset = add_objc_string (get_identifier (utlbuf));
        !          1899:       initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
        !          1900: 
        !          1901:       /* set offset */
        !          1902:       initlist = tree_cons (NULLT,
        !          1903:                            build_int_2 (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)) / BITS_PER_UNIT, 0),
        !          1904:                            
        !          1905:                            initlist);
        !          1906:       (*size)++;
        !          1907:       field_decl = TREE_CHAIN (field_decl);
        !          1908:     }
        !          1909:   while (field_decl);
        !          1910: 
        !          1911:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          1912: }
        !          1913: 
        !          1914: static tree
        !          1915: generate_ivars_list (type, name, size, list)
        !          1916:      tree type;
        !          1917:      char *name;
        !          1918:      int size;
        !          1919:      tree list;
        !          1920: {
        !          1921:   tree sc_spec, decl_specs, decl, initlist;
        !          1922: 
        !          1923:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          1924:   decl_specs = tree_cons (NULLT, type, sc_spec);
        !          1925: 
        !          1926:   decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
        !          1927: 
        !          1928:   initlist = build_tree_list (NULLT, build_int_2 (size, 0));
        !          1929:   initlist = tree_cons (NULLT, list, initlist);
        !          1930: 
        !          1931:   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
        !          1932: 
        !          1933:   return decl;
        !          1934: }
        !          1935: 
        !          1936: static void
        !          1937: generate_ivar_lists ()
        !          1938: {
        !          1939:   tree initlist, ivar_list_template, chain;
        !          1940:   tree cast, variable_length_type;
        !          1941:   int size;
        !          1942: 
        !          1943:   if (!objc_ivar_template)
        !          1944:     objc_ivar_template = build_ivar_template ();
        !          1945: 
        !          1946:   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          1947:                                                            get_identifier (_TAG_IVAR_LIST))), NULLT);
        !          1948:   variable_length_type = groktypename (cast);
        !          1949: 
        !          1950:   /* only generate class variables for the root of the inheritance
        !          1951:      hierarchy since these will be the same for every class */
        !          1952: 
        !          1953:   if (CLASS_SUPER_NAME (implementation_template) == NULLT
        !          1954:       && (chain = TYPE_FIELDS (objc_class_template)))
        !          1955:     {
        !          1956:       size = 0;
        !          1957:       initlist = build_ivar_list_initializer (chain, &size);
        !          1958: 
        !          1959:       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
        !          1960: 
        !          1961:       _OBJC_CLASS_VARIABLES_decl =
        !          1962:        generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
        !          1963:                             size, initlist);
        !          1964:       /* cast! */
        !          1965:       TREE_TYPE (_OBJC_CLASS_VARIABLES_decl) = variable_length_type;
        !          1966:     }
        !          1967:   else
        !          1968:     _OBJC_CLASS_VARIABLES_decl = 0;
        !          1969: 
        !          1970:   chain = CLASS_IVARS (implementation_template);
        !          1971:   if (chain)
        !          1972:     {
        !          1973:       size = 0;
        !          1974:       initlist = build_ivar_list_initializer (chain, &size);
        !          1975: 
        !          1976:       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
        !          1977: 
        !          1978:       _OBJC_INSTANCE_VARIABLES_decl =
        !          1979:        generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
        !          1980:                             size, initlist);
        !          1981:       /* cast! */
        !          1982:       TREE_TYPE (_OBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
        !          1983:     }
        !          1984:   else
        !          1985:     _OBJC_INSTANCE_VARIABLES_decl = 0;
        !          1986: }
        !          1987: 
        !          1988: static tree
        !          1989: build_dispatch_table_initializer (entries, size)
        !          1990:      tree entries;
        !          1991:      int *size;
        !          1992: {
        !          1993:   tree initlist = NULLT;
        !          1994: 
        !          1995:   do
        !          1996:     {
        !          1997:       int offset = add_objc_string (METHOD_SEL_NAME (entries));
        !          1998: 
        !          1999:       initlist = tree_cons (NULLT, init_selector (offset), initlist);
        !          2000: 
        !          2001:       offset = add_objc_string (METHOD_ENCODING (entries));
        !          2002:       initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
        !          2003: 
        !          2004:       initlist = tree_cons (NULLT, METHOD_DEFINITION (entries), initlist);
        !          2005: 
        !          2006:       (*size)++;
        !          2007:       entries = TREE_CHAIN (entries);
        !          2008:     }
        !          2009:   while (entries);
        !          2010: 
        !          2011:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          2012: }
        !          2013: 
        !          2014: /*
        !          2015:  * To accomplish method prototyping without generating all kinds of
        !          2016:  * inane warnings, the definition of the dispatch table entries were
        !          2017:  * changed from:
        !          2018:  *
        !          2019:  *     struct objc_method { SEL _cmd; id (*_imp)(); };
        !          2020:  * to:
        !          2021:  *     struct objc_method { SEL _cmd; void *_imp; };
        !          2022:  */
        !          2023: static tree
        !          2024: build_method_template ()
        !          2025: {
        !          2026:   tree _SLT_record;
        !          2027:   tree decl_specs, field_decl, field_decl_chain, parms;
        !          2028: 
        !          2029:   _SLT_record = start_struct (RECORD_TYPE, get_identifier (_TAG_METHOD));
        !          2030: 
        !          2031: #ifdef OBJC_INT_SELECTORS
        !          2032:   /* unsigned int _cmd; */
        !          2033:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
        !          2034:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !          2035:   field_decl = get_identifier ("_cmd");
        !          2036: #else /* not OBJC_INT_SELECTORS */
        !          2037:   /* struct objc_selector *_cmd; */
        !          2038:   decl_specs = tree_cons (NULLT,
        !          2039:                          xref_tag (RECORD_TYPE,
        !          2040:                                    get_identifier (TAG_SELECTOR)),
        !          2041:                          NULLT);
        !          2042:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
        !          2043: #endif /* not OBJC_INT_SELECTORS */
        !          2044: 
        !          2045:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2046:   field_decl_chain = field_decl;
        !          2047: 
        !          2048:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
        !          2049:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
        !          2050:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2051:   chainon (field_decl_chain, field_decl);
        !          2052: 
        !          2053:   /* void *_imp; */
        !          2054: 
        !          2055:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_VOID], NULLT);
        !          2056:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_imp"));
        !          2057:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2058:   chainon (field_decl_chain, field_decl);
        !          2059: 
        !          2060:   finish_struct (_SLT_record, field_decl_chain);
        !          2061: 
        !          2062:   return _SLT_record;
        !          2063: }
        !          2064: 
        !          2065: 
        !          2066: static tree
        !          2067: generate_dispatch_table (type, name, size, list)
        !          2068:      tree type;
        !          2069:      char *name;
        !          2070:      int size;
        !          2071:      tree list;
        !          2072: {
        !          2073:   tree sc_spec, decl_specs, decl, initlist;
        !          2074: 
        !          2075:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          2076:   decl_specs = tree_cons (NULLT, type, sc_spec);
        !          2077: 
        !          2078:   decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
        !          2079: 
        !          2080:   initlist = build_tree_list (NULLT, build_int_2 (0, 0));
        !          2081:   initlist = tree_cons (NULLT, build_int_2 (size, 0), initlist);
        !          2082:   initlist = tree_cons (NULLT, list, initlist);
        !          2083: 
        !          2084:   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
        !          2085: 
        !          2086:   return decl;
        !          2087: }
        !          2088: 
        !          2089: static void
        !          2090: generate_dispatch_tables ()
        !          2091: {
        !          2092:   tree initlist, chain, method_list_template;
        !          2093:   tree cast, variable_length_type;
        !          2094:   int size;
        !          2095: 
        !          2096:   if (!objc_method_template)
        !          2097:     objc_method_template = build_method_template ();
        !          2098: 
        !          2099:   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2100:                                                            get_identifier (_TAG_METHOD_LIST))), NULLT);
        !          2101:   variable_length_type = groktypename (cast);
        !          2102: 
        !          2103:   chain = CLASS_CLS_METHODS (implementation_context);
        !          2104:   if (chain)
        !          2105:     {
        !          2106:       size = 0;
        !          2107:       initlist = build_dispatch_table_initializer (chain, &size);
        !          2108: 
        !          2109:       method_list_template = build_method_list_template (objc_method_template,
        !          2110:                                                         size);
        !          2111:       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
        !          2112:        _OBJC_CLASS_METHODS_decl = 
        !          2113:            generate_dispatch_table (method_list_template,
        !          2114:                                     "_OBJC_CLASS_METHODS", 
        !          2115:                                     size, initlist);
        !          2116:       else
        !          2117:        /* we have a category */
        !          2118:        _OBJC_CLASS_METHODS_decl = 
        !          2119:            generate_dispatch_table (method_list_template,
        !          2120:                                     "_OBJC_CATEGORY_CLASS_METHODS", 
        !          2121:                                     size, initlist);
        !          2122:       /* cast! */
        !          2123:       TREE_TYPE (_OBJC_CLASS_METHODS_decl) = variable_length_type;
        !          2124:     }
        !          2125:   else
        !          2126:     _OBJC_CLASS_METHODS_decl = 0;
        !          2127: 
        !          2128:   chain = CLASS_NST_METHODS (implementation_context);
        !          2129:   if (chain)
        !          2130:     {
        !          2131:       size = 0;
        !          2132:       initlist = build_dispatch_table_initializer (chain, &size);
        !          2133: 
        !          2134:       method_list_template = build_method_list_template (objc_method_template,
        !          2135:                                                         size);
        !          2136:       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
        !          2137:        _OBJC_INSTANCE_METHODS_decl = 
        !          2138:            generate_dispatch_table (method_list_template,
        !          2139:                                     "_OBJC_INSTANCE_METHODS", 
        !          2140:                                     size, initlist);
        !          2141:       else
        !          2142:        /* we have a category */
        !          2143:        _OBJC_INSTANCE_METHODS_decl = 
        !          2144:            generate_dispatch_table (method_list_template,
        !          2145:                                     "_OBJC_CATEGORY_INSTANCE_METHODS", 
        !          2146:                                     size, initlist);
        !          2147:       /* cast! */
        !          2148:       TREE_TYPE (_OBJC_INSTANCE_METHODS_decl) = variable_length_type;
        !          2149:     }
        !          2150:   else
        !          2151:     _OBJC_INSTANCE_METHODS_decl = 0;
        !          2152: }
        !          2153: 
        !          2154: static tree
        !          2155: build_category_initializer (cat_name, class_name,
        !          2156:                            instance_methods, class_methods)
        !          2157:      tree cat_name;
        !          2158:      tree class_name;
        !          2159:      tree instance_methods;
        !          2160:      tree class_methods;
        !          2161: {
        !          2162:   tree initlist = NULLT, expr;
        !          2163: 
        !          2164:   initlist = tree_cons (NULLT, cat_name, initlist);
        !          2165:   initlist = tree_cons (NULLT, class_name, initlist);
        !          2166: 
        !          2167:   if (!instance_methods)
        !          2168:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          2169:   else
        !          2170:     {
        !          2171:       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
        !          2172:       initlist = tree_cons (NULLT, expr, initlist);
        !          2173:     }
        !          2174:   if (!class_methods)
        !          2175:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          2176:   else
        !          2177:     {
        !          2178:       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
        !          2179:       initlist = tree_cons (NULLT, expr, initlist);
        !          2180:     }
        !          2181:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          2182: }
        !          2183: 
        !          2184: /*
        !          2185:  *  struct objc_class {
        !          2186:  *    struct objc_class *isa;
        !          2187:  *    struct objc_class *super_class;
        !          2188:  *    char *name;
        !          2189:  *    long version;
        !          2190:  *    long info;
        !          2191:  *    long instance_size;
        !          2192:  *    struct objc_ivar_list *ivars;
        !          2193:  *    struct objc_method_list *methods;
        !          2194:  *    struct objc_cache *cache;
        !          2195:  *  };
        !          2196:  */
        !          2197: static tree
        !          2198: build_shared_structure_initializer (isa, super, name, size, status,
        !          2199:                                    dispatch_table, ivar_list)
        !          2200:      tree isa;
        !          2201:      tree super;
        !          2202:      tree name;
        !          2203:      tree size;
        !          2204:      int status;
        !          2205:      tree dispatch_table;
        !          2206:      tree ivar_list;
        !          2207: {
        !          2208:   tree initlist = NULLT, expr;
        !          2209: 
        !          2210:   /* isa = */
        !          2211:   initlist = tree_cons (NULLT, isa, initlist);
        !          2212: 
        !          2213:   /* super_class = */
        !          2214:   initlist = tree_cons (NULLT, super, initlist);
        !          2215: 
        !          2216:   /* name = */
        !          2217:   initlist = tree_cons (NULLT, name, initlist);
        !          2218: 
        !          2219:   /* version = */
        !          2220:   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          2221: 
        !          2222:   /* info = */
        !          2223:   initlist = tree_cons (NULLT, build_int_2 (status), initlist);
        !          2224: 
        !          2225:   /* instance_size = */
        !          2226:   initlist = tree_cons (NULLT, size, initlist);
        !          2227: 
        !          2228:   /* objc_ivar_list = */
        !          2229:   if (!ivar_list)
        !          2230:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          2231:   else
        !          2232:     {
        !          2233:       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
        !          2234:       initlist = tree_cons (NULLT, expr, initlist);
        !          2235:     }
        !          2236: 
        !          2237:   /* objc_method_list = */
        !          2238:   if (!dispatch_table)
        !          2239:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          2240:   else
        !          2241:     {
        !          2242:       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
        !          2243:       initlist = tree_cons (NULLT, expr, initlist);
        !          2244:     }
        !          2245: 
        !          2246:   /* method_cache = */
        !          2247:   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          2248: 
        !          2249:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          2250: }
        !          2251: 
        !          2252: /*
        !          2253:  * static struct objc_category _OBJC_CATEGORY_<name> = { ... };
        !          2254:  */
        !          2255: static void
        !          2256: generate_category (cat)
        !          2257:      tree cat;
        !          2258: {
        !          2259:   tree sc_spec, decl_specs, decl;
        !          2260:   tree initlist, cat_name_expr, class_name_expr;
        !          2261:   int offset;
        !          2262: 
        !          2263:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          2264:   decl_specs = tree_cons (NULLT, objc_category_template, sc_spec);
        !          2265: 
        !          2266:   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY"),
        !          2267:                     decl_specs, 1);
        !          2268: 
        !          2269:   offset = add_objc_string (CLASS_SUPER_NAME (cat));
        !          2270:   cat_name_expr = build_msg_pool_reference (offset);
        !          2271: 
        !          2272:   offset = add_objc_string (CLASS_NAME (cat));
        !          2273:   class_name_expr = build_msg_pool_reference (offset);
        !          2274: 
        !          2275:   initlist = build_category_initializer (
        !          2276:                                         cat_name_expr, class_name_expr,
        !          2277:                                         _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl);
        !          2278: 
        !          2279:   finish_decl (decl, initlist, NULLT);
        !          2280: }
        !          2281: 
        !          2282: /*
        !          2283:  * static struct objc_class _OBJC_METACLASS_Foo={ ... };
        !          2284:  * static struct objc_class _OBJC_CLASS_Foo={ ... };
        !          2285:  */
        !          2286: static void
        !          2287: generate_shared_structures ()
        !          2288: {
        !          2289:   tree sc_spec, decl_specs, expr_decl, decl;
        !          2290:   tree name_expr, super_expr, root_expr;
        !          2291:   tree my_root_id = NULLT, my_super_id = NULLT;
        !          2292:   tree cast_type, initlist;
        !          2293:   int offset;
        !          2294: 
        !          2295:   my_super_id = CLASS_SUPER_NAME (implementation_template);
        !          2296:   if (my_super_id)
        !          2297:     {
        !          2298:       add_class_reference (my_super_id);
        !          2299: 
        !          2300:       /* compute "my_root_id" - this is required for code generation.
        !          2301:        * the "isa" for all meta class structures points to the root of
        !          2302:        * the inheritance hierarchy (e.g. "__Object")...
        !          2303:        */
        !          2304:       my_root_id = my_super_id;
        !          2305:       do
        !          2306:        {
        !          2307:          tree my_root_int = lookup_interface (my_root_id);
        !          2308: 
        !          2309:          if (my_root_int && CLASS_SUPER_NAME (my_root_int))
        !          2310:            my_root_id = CLASS_SUPER_NAME (my_root_int);
        !          2311:          else
        !          2312:            break;
        !          2313:        }
        !          2314:       while (1);
        !          2315:     }
        !          2316:   else                         /* no super class */
        !          2317:     {
        !          2318:       my_root_id = CLASS_NAME (implementation_template);
        !          2319:     }
        !          2320: 
        !          2321:   cast_type = groktypename (build_tree_list (build_tree_list (NULLT,
        !          2322:                                                              objc_class_template), build1 (INDIRECT_REF, NULLT, NULLT)));
        !          2323: 
        !          2324:   offset = add_objc_string (CLASS_NAME (implementation_template));
        !          2325:   name_expr = build_msg_pool_reference (offset);
        !          2326: 
        !          2327:   /* install class `isa' and `super' pointers at runtime */
        !          2328:   if (my_super_id)
        !          2329:     {
        !          2330:       offset = add_objc_string (my_super_id);
        !          2331:       super_expr = build_msg_pool_reference (offset);
        !          2332:       TREE_TYPE (super_expr) = cast_type; /* cast! */
        !          2333:     }
        !          2334:   else
        !          2335:     super_expr = build_int_2 (0, 0);
        !          2336: 
        !          2337:   offset = add_objc_string (my_root_id);
        !          2338:   root_expr = build_msg_pool_reference (offset);
        !          2339:   TREE_TYPE (root_expr) = cast_type; /* cast! */
        !          2340: 
        !          2341:   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
        !          2342: 
        !          2343:   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
        !          2344:   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
        !          2345: 
        !          2346:   decl = start_decl (DECL_NAME (_OBJC_METACLASS_decl), decl_specs, 1);
        !          2347: 
        !          2348:   initlist = build_shared_structure_initializer (
        !          2349:                                                 root_expr, super_expr, name_expr,
        !          2350:                                                 build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) / BITS_PER_UNIT, 0),
        !          2351:                                                 2 /*CLS_META*/,
        !          2352:                                                 _OBJC_CLASS_METHODS_decl, _OBJC_CLASS_VARIABLES_decl);
        !          2353: 
        !          2354:   finish_decl (decl, initlist, NULLT);
        !          2355: 
        !          2356:   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
        !          2357: 
        !          2358:   decl = start_decl (DECL_NAME (_OBJC_CLASS_decl), decl_specs, 1);
        !          2359: 
        !          2360:   initlist = build_shared_structure_initializer (
        !          2361:                                                 build_unary_op (ADDR_EXPR, _OBJC_METACLASS_decl, 0),
        !          2362:                                                 super_expr, name_expr,
        !          2363:                                                 build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) / BITS_PER_UNIT, 0),
        !          2364:                                                 1 /*CLS_FACTORY*/,
        !          2365:                                                 _OBJC_INSTANCE_METHODS_decl, _OBJC_INSTANCE_VARIABLES_decl);
        !          2366: 
        !          2367:   finish_decl (decl, initlist, NULLT);
        !          2368: }
        !          2369: 
        !          2370: static tree
        !          2371: synth_id_with_class_suffix (preamble)
        !          2372:      char *preamble;
        !          2373: {
        !          2374:   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
        !          2375:     sprintf (utlbuf, "%s_%s", preamble,
        !          2376:             IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
        !          2377:   else
        !          2378:     /* we have a category */
        !          2379:     sprintf (utlbuf, "%s_%s_%s", preamble,
        !          2380:             IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
        !          2381:             IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
        !          2382:   return get_identifier (utlbuf);
        !          2383: }
        !          2384: 
        !          2385: /*
        !          2386:  *   usage:
        !          2387:  *             keyworddecl:
        !          2388:  *                     selector ':' '(' typename ')' identifier
        !          2389:  *
        !          2390:  *   purpose:
        !          2391:  *             transform an Objective-C keyword argument into
        !          2392:  *             the C equivalent parameter declarator.
        !          2393:  *
        !          2394:  *   in:       key_name, an "identifier_node" (optional).
        !          2395:  *             arg_type, a  "tree_list" (optional).
        !          2396:  *             arg_name, an "identifier_node".
        !          2397:  *
        !          2398:  *   note:     it would be really nice to strongly type the preceding
        !          2399:  *             arguments in the function prototype; however, then i
        !          2400:  *             could not use the "accessor" macros defined in "tree.h".
        !          2401:  *
        !          2402:  *   out:      an instance of "keyword_decl".
        !          2403:  *
        !          2404:  */
        !          2405: 
        !          2406: tree
        !          2407: build_keyword_decl (key_name, arg_type, arg_name)
        !          2408:      tree key_name;
        !          2409:      tree arg_type;
        !          2410:      tree arg_name;
        !          2411: {
        !          2412:   tree keyword_decl;
        !          2413: 
        !          2414:   /* if no type is specified, default to "id" */
        !          2415:   if (arg_type == NULLT)
        !          2416:     arg_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
        !          2417:                                build1 (INDIRECT_REF, NULLT, NULLT));
        !          2418: 
        !          2419:   keyword_decl = make_node (KEYWORD_DECL);
        !          2420: 
        !          2421:   TREE_TYPE (keyword_decl) = arg_type;
        !          2422:   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
        !          2423:   KEYWORD_KEY_NAME (keyword_decl) = key_name;
        !          2424: 
        !          2425:   return keyword_decl;
        !          2426: }
        !          2427: 
        !          2428: /*
        !          2429:  *  given a chain of keyword_decl's, synthesize the full keyword selector.
        !          2430:  */
        !          2431: static tree
        !          2432: build_keyword_selector (selector)
        !          2433:      tree selector;
        !          2434: {
        !          2435:   int len = 0;
        !          2436:   tree key_chain, key_name;
        !          2437:   char *buf;
        !          2438: 
        !          2439:   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
        !          2440:     {
        !          2441:       if (TREE_CODE (selector) == KEYWORD_DECL)
        !          2442:        key_name = KEYWORD_KEY_NAME (key_chain);
        !          2443:       else if (TREE_CODE (selector) == TREE_LIST)
        !          2444:        key_name = TREE_PURPOSE (key_chain);
        !          2445: 
        !          2446:       if (key_name)
        !          2447:        len += IDENTIFIER_LENGTH (key_name) + 1;
        !          2448:       else                     /* just a ':' arg */
        !          2449:        len++;
        !          2450:     }
        !          2451:   buf = (char *)alloca (len + 1);
        !          2452:   bzero (buf, len + 1);
        !          2453: 
        !          2454:   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
        !          2455:     {
        !          2456:       if (TREE_CODE (selector) == KEYWORD_DECL)
        !          2457:        key_name = KEYWORD_KEY_NAME (key_chain);
        !          2458:       else if (TREE_CODE (selector) == TREE_LIST)
        !          2459:        key_name = TREE_PURPOSE (key_chain);
        !          2460: 
        !          2461:       if (key_name)
        !          2462:        strcat (buf, IDENTIFIER_POINTER (key_name));
        !          2463:       strcat (buf, ":");
        !          2464:     }
        !          2465:   return get_identifier (buf);
        !          2466: }
        !          2467: 
        !          2468: /* used for declarations and definitions */
        !          2469: 
        !          2470: tree
        !          2471: build_method_decl (code, ret_type, selector, add_args)
        !          2472:      enum tree_code code;
        !          2473:      tree ret_type;
        !          2474:      tree selector;
        !          2475:      tree add_args;
        !          2476: {
        !          2477:   tree method_decl;
        !          2478: 
        !          2479:   /* if no type is specified, default to "id" */
        !          2480:   if (ret_type == NULLT)
        !          2481:     ret_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
        !          2482:                                build1 (INDIRECT_REF, NULLT, NULLT));
        !          2483: 
        !          2484:   method_decl = make_node (code);
        !          2485:   TREE_TYPE (method_decl) = ret_type;
        !          2486: 
        !          2487:   /*
        !          2488:    *  if we have a keyword selector, create an identifier_node that
        !          2489:    *  represents the full selector name (`:' included)...
        !          2490:    */
        !          2491:   if (TREE_CODE (selector) == KEYWORD_DECL)
        !          2492:     {
        !          2493:       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
        !          2494:       METHOD_SEL_ARGS (method_decl) = selector;
        !          2495:       METHOD_ADD_ARGS (method_decl) = add_args;
        !          2496:     }
        !          2497:   else
        !          2498:     {
        !          2499:       METHOD_SEL_NAME (method_decl) = selector;
        !          2500:       METHOD_SEL_ARGS (method_decl) = NULLT;
        !          2501:       METHOD_ADD_ARGS (method_decl) = NULLT;
        !          2502:     }
        !          2503: 
        !          2504:   return method_decl;
        !          2505: }
        !          2506: 
        !          2507: #define METHOD_DEF 0
        !          2508: #define METHOD_REF 1
        !          2509: /*
        !          2510:  * used by `build_message_expr' and `comp_method_types'.
        !          2511:  *
        !          2512:  * add_args is a tree_list node the following info on a parameter list:
        !          2513:  *
        !          2514:  *    The TREE_PURPOSE is a chain of decls of those parms.
        !          2515:  *    The TREE_VALUE is a list of structure, union and enum tags defined.
        !          2516:  *    The TREE_CHAIN is a list of argument types to go in the FUNCTION_TYPE.
        !          2517:  *    This tree_list node is later fed to `grokparms'.
        !          2518:  *
        !          2519:  *    VOID_AT_END nonzero means append `void' to the end of the type-list.
        !          2520:  *    Zero means the parmlist ended with an ellipsis so don't append `void'.
        !          2521:  */
        !          2522: static tree
        !          2523: get_arg_type_list (meth, context, superflag)
        !          2524:      tree meth;
        !          2525:      int context;
        !          2526:      int superflag;
        !          2527: {
        !          2528:   tree arglist, akey;
        !          2529: 
        !          2530:   /* receiver type */
        !          2531:   if (superflag)
        !          2532:     arglist = build_tree_list (NULLT, super_type);
        !          2533:   else
        !          2534:     {
        !          2535:       if (context == METHOD_DEF)
        !          2536:        arglist = build_tree_list (NULLT, TREE_TYPE (self_decl));
        !          2537:       else
        !          2538:        arglist = build_tree_list (NULLT, id_type);
        !          2539:     }
        !          2540: 
        !          2541:   /* selector type - will eventually change to `int' */
        !          2542:   chainon (arglist, build_tree_list (NULLT, _selector_type));
        !          2543: 
        !          2544:   /* build a list of argument types */
        !          2545:   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
        !          2546:     {
        !          2547:       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
        !          2548:       chainon (arglist, build_tree_list (NULLT, TREE_TYPE (arg_decl)));
        !          2549:     }
        !          2550: 
        !          2551:   if (METHOD_ADD_ARGS (meth) == (tree)1)
        !          2552:     /*
        !          2553:      * we have a `, ...' immediately following the selector,
        !          2554:      * finalize the arglist...simulate get_parm_info (0)
        !          2555:      */
        !          2556:     ;
        !          2557:   else if (METHOD_ADD_ARGS (meth))
        !          2558:     {
        !          2559:       /* we have a variable length selector */
        !          2560:       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
        !          2561:       chainon (arglist, add_arg_list);
        !          2562:     }
        !          2563:   else                         /* finalize the arglist...simulate get_parm_info (1) */
        !          2564:     chainon (arglist, build_tree_list (NULLT, void_type_node));
        !          2565: 
        !          2566:   return arglist;
        !          2567: }
        !          2568: 
        !          2569: static tree
        !          2570: check_duplicates (hsh)
        !          2571:      hash hsh;
        !          2572: {
        !          2573:   tree meth = NULLT;
        !          2574: 
        !          2575:   if (hsh)
        !          2576:     {
        !          2577:       meth = hsh->key;
        !          2578: 
        !          2579:       if (hsh->list)
        !          2580:         {
        !          2581:          /* we have two methods with the same name and different types */
        !          2582:          attr loop;
        !          2583:          char type;
        !          2584: 
        !          2585:          type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
        !          2586: 
        !          2587:          warning ("multiple declarations for method `%s'",
        !          2588:                   IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
        !          2589: 
        !          2590:          warn_with_method ("using", type, meth);
        !          2591:          for (loop = hsh->list; loop; loop = loop->next)
        !          2592:            warn_with_method ("also found", type, loop->value);
        !          2593:         }
        !          2594:     }
        !          2595:   return meth;
        !          2596: }
        !          2597: 
        !          2598: static tree
        !          2599: receiver_is_class_object (receiver)
        !          2600:       tree receiver;
        !          2601: {
        !          2602:   /* the receiver is a function call that returns an id...
        !          2603:    * ...check if it is a call to objc_getClass, if so, give it
        !          2604:    * special treatment.
        !          2605:    */
        !          2606:   tree exp = 0;
        !          2607: 
        !          2608:   if ((exp = TREE_OPERAND (receiver, 0)) && (TREE_CODE (exp) == ADDR_EXPR))
        !          2609:     {
        !          2610:       if ((exp = TREE_OPERAND (exp, 0)) && 
        !          2611:          (TREE_CODE (exp) == FUNCTION_DECL) && exp == objc_getClass_decl)
        !          2612:        {
        !          2613:          /* we have a call to objc_getClass! */
        !          2614:          tree arg = 0;
        !          2615:     
        !          2616:          if ((arg = TREE_OPERAND (receiver, 1)) &&
        !          2617:              (TREE_CODE (arg) == TREE_LIST) &&
        !          2618:              (arg = TREE_VALUE (arg)) &&
        !          2619:              (TREE_CODE (arg) == NOP_EXPR) &&
        !          2620:              (arg = TREE_OPERAND (arg, 0)) &&
        !          2621:              (TREE_CODE (arg) == ADDR_EXPR) &&
        !          2622:              (arg = TREE_OPERAND (arg, 0)) &&
        !          2623:              (TREE_CODE (arg) == STRING_CST))
        !          2624:            /* finally, we have the class name */
        !          2625:            return get_identifier (TREE_STRING_POINTER (arg));
        !          2626:        }
        !          2627:     }
        !          2628:   return 0;
        !          2629: }
        !          2630: 
        !          2631: /* If we are currently building a message expr, this holds
        !          2632:    the identifier of the selector of the message.  This is
        !          2633:    used when printing warnings about argument mismatches. */
        !          2634: 
        !          2635: static tree building_objc_message_expr = 0;
        !          2636: 
        !          2637: tree
        !          2638: maybe_building_objc_message_expr ()
        !          2639: {
        !          2640:   return building_objc_message_expr;
        !          2641: }
        !          2642: 
        !          2643: /* Construct an expression for sending a message.
        !          2644:    MESS has the object to send to in TREE_PURPOSE
        !          2645:    and the argument list (including selector) in TREE_VALUE.  */
        !          2646: 
        !          2647: tree
        !          2648: build_message_expr (mess)
        !          2649:      tree mess;
        !          2650: {
        !          2651:   tree receiver = TREE_PURPOSE (mess);
        !          2652:   tree selector, self_object;
        !          2653:   tree rtype, sel_name;
        !          2654:   tree args = TREE_VALUE (mess);
        !          2655:   tree method_params = NULLT;
        !          2656:   tree method_prototype = NULLT;
        !          2657:   int selTransTbl_index;
        !          2658:   tree retval;
        !          2659:   int statically_typed = 0, statically_allocated = 0;
        !          2660:   tree class_ident = 0;
        !          2661: 
        !          2662:   /* 1 if this is sending to the superclass.  */
        !          2663:   int super;
        !          2664: 
        !          2665:   if (!doing_objc_thang)
        !          2666:     fatal ("Objective-C text in C source file");
        !          2667: 
        !          2668:   if (TREE_CODE (receiver) == ERROR_MARK)
        !          2669:     return error_mark_node;
        !          2670: 
        !          2671:   /* determine receiver type */
        !          2672:   rtype = TREE_TYPE (receiver);
        !          2673:   super = (TREE_TYPE (receiver) == super_type);
        !          2674: 
        !          2675:   if (! super)
        !          2676:     {
        !          2677:       if (TREE_STATIC_TEMPLATE (rtype))
        !          2678:        statically_allocated = 1;
        !          2679:       else if (TREE_CODE (rtype) == POINTER_TYPE
        !          2680:               && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
        !          2681:        statically_typed = 1;
        !          2682:       /* classfix -smn */
        !          2683:       else if (TREE_CODE (receiver) == CALL_EXPR && rtype == id_type
        !          2684:               && (class_ident = receiver_is_class_object (receiver)))
        !          2685:        ;
        !          2686:       else if (rtype != id_type && rtype != class_type)
        !          2687:        {
        !          2688:          bzero (errbuf, BUFSIZE);
        !          2689:          warning ("invalid receiver type `%s'", gen_declaration (rtype, errbuf));
        !          2690:        }
        !          2691:       if (statically_allocated)
        !          2692:        receiver = build_unary_op (ADDR_EXPR, receiver, 0);
        !          2693: 
        !          2694:       self_object = receiver;
        !          2695:     }
        !          2696:   else
        !          2697:     /* If sending to `super', use current self as the object.  */
        !          2698:     self_object = self_decl;
        !          2699: 
        !          2700:   /* Obtain the full selector name.  */
        !          2701: 
        !          2702:   if (TREE_CODE (args) == IDENTIFIER_NODE)
        !          2703:     /* a unary selector */
        !          2704:     sel_name = args;
        !          2705:   else if (TREE_CODE (args) == TREE_LIST)
        !          2706:     sel_name = build_keyword_selector (args);
        !          2707: 
        !          2708:   selTransTbl_index = add_selector_reference (sel_name);
        !          2709: 
        !          2710:   /* Build the parameters list for looking up the method.
        !          2711:      These are the object itself and the selector.  */
        !          2712:   
        !          2713: #ifndef OBJC_NONUNIQUE_SELECTORS
        !          2714:   selector = build_selector_reference (selTransTbl_index);
        !          2715: #else
        !          2716:   selector = build_array_ref (_OBJC_SELECTOR_REFERENCES_decl,
        !          2717:                              build_int_2 (selTransTbl_index, 0));
        !          2718: #endif
        !          2719: 
        !          2720:   /* Build the parameter list to give to the method.  */
        !          2721: 
        !          2722:   method_params = NULLT;
        !          2723:   if (TREE_CODE (args) == TREE_LIST)
        !          2724:     {
        !          2725:       tree chain = args, prev = NULLT;
        !          2726: 
        !          2727:       /* We have a keyword selector--check for comma expressions.  */
        !          2728:       while (chain)
        !          2729:        {
        !          2730:          tree element = TREE_VALUE (chain);
        !          2731: 
        !          2732:          /* We have a comma expression, must collapse...  */
        !          2733:          if (TREE_CODE (element) == TREE_LIST)
        !          2734:            {
        !          2735:              if (prev)
        !          2736:                TREE_CHAIN (prev) = element;
        !          2737:              else
        !          2738:                args = element;
        !          2739:            }
        !          2740:          prev = chain;
        !          2741:          chain = TREE_CHAIN (chain);
        !          2742:         }
        !          2743:       method_params = args;
        !          2744:     }
        !          2745: 
        !          2746:   /* Determine operation return type.  */
        !          2747: 
        !          2748:   if (rtype == super_type)
        !          2749:     {
        !          2750:       tree iface;
        !          2751: 
        !          2752:       if (CLASS_SUPER_NAME (implementation_template))
        !          2753:        {
        !          2754:          iface = lookup_interface (CLASS_SUPER_NAME (implementation_template));
        !          2755:     
        !          2756:          if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
        !          2757:            method_prototype = lookup_instance_method_static (iface, sel_name);
        !          2758:          else
        !          2759:            method_prototype = lookup_class_method_static (iface, sel_name);
        !          2760:     
        !          2761:          if (iface && !method_prototype)
        !          2762:            warning ("`%s' does not respond to `%s'",
        !          2763:                     IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
        !          2764:                     IDENTIFIER_POINTER (sel_name));
        !          2765:        }
        !          2766:       else
        !          2767:        {
        !          2768:          error ("no super class declared in interface for `%s'",
        !          2769:                 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
        !          2770:          return error_mark_node;
        !          2771:        }
        !          2772: 
        !          2773:     }
        !          2774:   else if (statically_allocated)
        !          2775:     {
        !          2776:       tree iface = lookup_interface (TYPE_NAME (rtype));
        !          2777: 
        !          2778:       if (iface && !(method_prototype = lookup_instance_method_static (iface, sel_name)))
        !          2779:        warning ("`%s' does not respond to `%s'",
        !          2780:                 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
        !          2781:                 IDENTIFIER_POINTER (sel_name));
        !          2782:     }
        !          2783:   else if (statically_typed)
        !          2784:     {
        !          2785:       tree ctype = TREE_TYPE (rtype);
        !          2786: 
        !          2787:       /* `self' is now statically_typed...all methods should be visible
        !          2788:        * within the context of the implementation...
        !          2789:        */
        !          2790:       if (implementation_context
        !          2791:          && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
        !          2792:        {
        !          2793:          method_prototype = lookup_instance_method_static (implementation_template, sel_name);
        !          2794: 
        !          2795:          if (!method_prototype && implementation_template != implementation_context)
        !          2796:            /* the method is not published in the interface...check locally */
        !          2797:            method_prototype = lookup_method (CLASS_NST_METHODS (implementation_context),
        !          2798:                                  sel_name);
        !          2799:        }
        !          2800:       else
        !          2801:        {
        !          2802:          tree iface;
        !          2803: 
        !          2804:          if (iface = lookup_interface (TYPE_NAME (ctype)))
        !          2805:            method_prototype = lookup_instance_method_static (iface, sel_name);
        !          2806:        }
        !          2807: 
        !          2808:       if (!method_prototype)
        !          2809:         warning ("`%s' does not respond to `%s'",
        !          2810:                 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
        !          2811:                 IDENTIFIER_POINTER (sel_name));
        !          2812:     }
        !          2813:   else if (class_ident)
        !          2814:     {
        !          2815:       if (implementation_context
        !          2816:          && CLASS_NAME (implementation_context) == class_ident)
        !          2817:        {
        !          2818:          method_prototype
        !          2819:            = lookup_class_method_static (implementation_template, sel_name);
        !          2820:     
        !          2821:          if (!method_prototype
        !          2822:              && implementation_template != implementation_context)
        !          2823:            /* the method is not published in the interface...check locally */
        !          2824:            method_prototype
        !          2825:              = lookup_method (CLASS_CLS_METHODS (implementation_context),
        !          2826:                               sel_name);
        !          2827:        }
        !          2828:       else
        !          2829:        {
        !          2830:          tree iface;
        !          2831:     
        !          2832:          if (iface = lookup_interface (class_ident))
        !          2833:            method_prototype = lookup_class_method_static (iface, sel_name);
        !          2834:        }
        !          2835:   
        !          2836:       if (!method_prototype)
        !          2837:        {
        !          2838:          warning ("cannot find class (factory) method.");
        !          2839:          warning ("return type for `%s' defaults to id",
        !          2840:                   IDENTIFIER_POINTER (sel_name));
        !          2841:        }
        !          2842:     }
        !          2843:   else
        !          2844:     {
        !          2845:       hash hsh;
        !          2846: 
        !          2847:       /* we think we have an instance...loophole: extern id Object; */
        !          2848:       hsh = hash_lookup (nst_method_hash_list, sel_name);
        !          2849:       if (!hsh)
        !          2850:        /* for various loopholes...like sending messages to self in a
        !          2851:           factory context... */
        !          2852:        hsh = hash_lookup (cls_method_hash_list, sel_name);
        !          2853: 
        !          2854:       method_prototype = check_duplicates (hsh);
        !          2855:       if (!method_prototype)
        !          2856:        {
        !          2857:          warning ("cannot find method.");
        !          2858:          warning ("return type for `%s' defaults to id",
        !          2859:                   IDENTIFIER_POINTER (sel_name));
        !          2860:        }
        !          2861:     }
        !          2862: 
        !          2863:   /* Save the selector name for printing error messages.  */
        !          2864:   building_objc_message_expr = sel_name;
        !          2865: 
        !          2866:   retval = build_objc_method_call (super, method_prototype,
        !          2867:                                   receiver, self_object,
        !          2868:                                   selector, method_params);
        !          2869: 
        !          2870:   building_objc_message_expr = 0;
        !          2871: 
        !          2872:   return retval;
        !          2873: }
        !          2874: 
        !          2875: /* Build a tree expression to send OBJECT the operation SELECTOR,
        !          2876:    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
        !          2877:    assuming the method has prototype METHOD_PROTOTYPE.
        !          2878:    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
        !          2879:    Use METHOD_PARAMS as list of args to pass to the method.
        !          2880:    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
        !          2881: 
        !          2882: static tree
        !          2883: build_objc_method_call (super_flag, method_prototype, lookup_object, object,
        !          2884:                        selector, method_params)
        !          2885:      int super_flag;
        !          2886:      tree method_prototype, lookup_object, object, selector, method_params;
        !          2887: {
        !          2888:   tree sender = (super_flag ? _msgSuper_decl : _msg_decl);
        !          2889: 
        !          2890: #ifdef NEXT_OBJC_RUNTIME
        !          2891:   if (!method_prototype)
        !          2892:     {
        !          2893:       method_params = tree_cons (NULLT, lookup_object,
        !          2894:                                 tree_cons (NULLT, selector, method_params));
        !          2895:       return build_function_call (sender, method_params);
        !          2896:     }
        !          2897:   else
        !          2898:     {
        !          2899:       /* This is a real kludge, but it is used only for the Next.
        !          2900:         Clobber the data type of SENDER temporarily to accept
        !          2901:         all the arguments for this operation, and to return
        !          2902:         whatever this operation returns.  */
        !          2903:       tree arglist = NULLT;
        !          2904:       tree retval;
        !          2905: 
        !          2906:       /* Save the proper contents of SENDER's data type.  */
        !          2907:       tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
        !          2908:       tree savret = TREE_TYPE (TREE_TYPE (sender));
        !          2909: 
        !          2910:       /* Install this method's argument types.  */
        !          2911:       arglist = get_arg_type_list (method_prototype, METHOD_REF, super_flag);
        !          2912:       TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
        !          2913: 
        !          2914:       /* Install this method's return type.  */
        !          2915:       TREE_TYPE (TREE_TYPE (sender))
        !          2916:        = groktypename (TREE_TYPE (method_prototype));
        !          2917: 
        !          2918:       /* Call SENDER with all the parameters.
        !          2919:         This will do type checking using the arg types for this method.  */
        !          2920:       method_params = tree_cons (NULLT, lookup_object,
        !          2921:                                 tree_cons (NULLT, selector, method_params));
        !          2922:       retval = build_function_call (sender, method_params);
        !          2923: 
        !          2924:       /* Restore SENDER's return/argument types.  */
        !          2925:       TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
        !          2926:       TREE_TYPE (TREE_TYPE (sender)) = savret;
        !          2927:       return retval;
        !          2928:     }
        !          2929: #else /* not NEXT_OBJC_RUNTIME */
        !          2930:   /* This is the portable way.
        !          2931:      First call the lookup function to get a pointer to the method, 
        !          2932:      then cast the pointer, then call it with the method arguments.  */
        !          2933:   tree method;
        !          2934: 
        !          2935:   /* Avoid trouble since we may evaluate each of these twice.  */
        !          2936:   object = save_expr (object);
        !          2937:   selector = save_expr (selector);
        !          2938: 
        !          2939:   method
        !          2940:     = build_function_call (sender,
        !          2941:                           tree_cons (NULLT, lookup_object,
        !          2942:                                      tree_cons (NULLT, selector, NULLT)));
        !          2943: 
        !          2944:   /* If we have a method prototype, construct the data type this method needs,
        !          2945:      and cast what we got from SENDER into a pointer to that type.  */
        !          2946:   if (method_prototype)
        !          2947:     {
        !          2948:       tree arglist = get_arg_type_list (method_prototype, METHOD_REF, super_flag);
        !          2949:       tree valtype = groktypename (TREE_TYPE (method_prototype));
        !          2950:       tree fake_function_type = build_function_type (valtype, arglist);
        !          2951:       TREE_TYPE (method) = build_pointer_type (fake_function_type);
        !          2952:     }
        !          2953:   else
        !          2954:     {
        !          2955:       TREE_TYPE (method)
        !          2956:        = build_pointer_type (build_function_type (ptr_type_node, NULLT));
        !          2957:     }
        !          2958:   /* Pass the object to the method.  */
        !          2959:   return build_function_call (method,
        !          2960:                              tree_cons (NULLT, object,
        !          2961:                                         tree_cons (NULLT, selector,
        !          2962:                                                    method_params)));
        !          2963: #endif /* not NEXT_OBJC_RUNTIME */
        !          2964: }
        !          2965: 
        !          2966: tree
        !          2967: build_selector_expr (selnamelist)
        !          2968:      tree selnamelist;
        !          2969: {
        !          2970:   tree selname;
        !          2971:   int selTransTbl_index;
        !          2972: 
        !          2973:   if (!doing_objc_thang)
        !          2974:     fatal ("Objective-C text in C source file");
        !          2975: 
        !          2976:   /* obtain the full selector name */
        !          2977:   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
        !          2978:     /* a unary selector */
        !          2979:     selname = selnamelist;
        !          2980:   else if (TREE_CODE (selnamelist) == TREE_LIST)
        !          2981:     selname = build_keyword_selector (selnamelist);
        !          2982: 
        !          2983:   selTransTbl_index = add_selector_reference (selname);
        !          2984: 
        !          2985: #ifndef OBJC_NONUNIQUE_SELECTORS
        !          2986:   return build_selector_reference (selTransTbl_index);
        !          2987: #else
        !          2988:   /* synthesize a reference into the selector translation table */
        !          2989:   return build_array_ref (_OBJC_SELECTOR_REFERENCES_decl,
        !          2990:                          build_int_2 (selTransTbl_index, 0));
        !          2991: #endif
        !          2992: }
        !          2993: 
        !          2994: tree
        !          2995: build_encode_expr (type)
        !          2996:      tree type;
        !          2997: {
        !          2998:   if (!doing_objc_thang)
        !          2999:     fatal ("Objective-C text in C source file");
        !          3000: 
        !          3001:   if (!utlbuf)
        !          3002:     utlbuf = (char *)xmalloc (BUFSIZE);
        !          3003:   bzero (utlbuf, BUFSIZE);
        !          3004: 
        !          3005:   encode_type (type, utlbuf, OBJC_ENCODE_INLINE_DEFS);
        !          3006: 
        !          3007:   /* synthesize a string that represents the encoded struct/union */
        !          3008:   return my_build_string (strlen (utlbuf) + 1, utlbuf);
        !          3009: }
        !          3010: 
        !          3011: tree
        !          3012: build_ivar_reference (id)
        !          3013:      tree id;
        !          3014: {
        !          3015:   if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
        !          3016:     TREE_TYPE (self_decl) = instance_type; /* cast */
        !          3017: 
        !          3018:   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
        !          3019: }
        !          3020: 
        !          3021: #define HASH_ALLOC_LIST_SIZE   170
        !          3022: #define ATTR_ALLOC_LIST_SIZE   170
        !          3023: #define SIZEHASHTABLE          257
        !          3024: #define HASHFUNCTION(key)      ((int)key >> 2)         /* divide by 4 */
        !          3025: 
        !          3026: static void
        !          3027: hash_init ()
        !          3028: {
        !          3029:   nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
        !          3030:   cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
        !          3031: 
        !          3032:   if (!nst_method_hash_list || !cls_method_hash_list)
        !          3033:     perror ("unable to allocate space in objc-tree.c");
        !          3034:   else
        !          3035:     {
        !          3036:       int i;
        !          3037: 
        !          3038:       for (i = 0; i < SIZEHASHTABLE; i++)
        !          3039:        {
        !          3040:          nst_method_hash_list[i] = 0;
        !          3041:          cls_method_hash_list[i] = 0;
        !          3042:        }
        !          3043:     }
        !          3044: }
        !          3045: 
        !          3046: static void
        !          3047: hash_enter (hashlist, method)
        !          3048:      hash *hashlist;
        !          3049:      tree method;
        !          3050: {
        !          3051:   static hash  hash_alloc_list = 0;
        !          3052:   static int   hash_alloc_index = 0;
        !          3053:   hash obj;
        !          3054:   int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
        !          3055: 
        !          3056:   if (!hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
        !          3057:     {
        !          3058:       hash_alloc_index = 0;
        !          3059:       hash_alloc_list = (hash)xmalloc (sizeof (struct hashedEntry) *
        !          3060:                                      HASH_ALLOC_LIST_SIZE);
        !          3061:       if (!hash_alloc_list)
        !          3062:        perror ("unable to allocate in objc-tree.c");
        !          3063:     }
        !          3064:   obj = &hash_alloc_list[hash_alloc_index++];
        !          3065:   obj->list = 0;
        !          3066:   obj->next = hashlist[slot];
        !          3067:   obj->key = method;
        !          3068: 
        !          3069:   hashlist[slot] = obj;                /* append to front */
        !          3070: }
        !          3071: 
        !          3072: static hash
        !          3073: hash_lookup (hashlist, sel_name)
        !          3074:      hash *hashlist;
        !          3075:      tree sel_name;
        !          3076: {
        !          3077:   hash target;
        !          3078: 
        !          3079:   target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
        !          3080: 
        !          3081:   while (target)
        !          3082:     {
        !          3083:       if (sel_name == METHOD_SEL_NAME (target->key))
        !          3084:        return target;
        !          3085: 
        !          3086:       target = target->next;
        !          3087:     }
        !          3088:   return 0;
        !          3089: }
        !          3090: 
        !          3091: static void
        !          3092: hash_add_attr (entry, value)
        !          3093:      hash entry;
        !          3094:      tree value;
        !          3095: {
        !          3096:   static attr  attr_alloc_list = 0;
        !          3097:   static int   attr_alloc_index = 0;
        !          3098:   attr obj;
        !          3099: 
        !          3100:   if (!attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
        !          3101:     {
        !          3102:       attr_alloc_index = 0;
        !          3103:       attr_alloc_list = (attr)xmalloc (sizeof (struct hashedAttribute) *
        !          3104:                                      ATTR_ALLOC_LIST_SIZE);
        !          3105:       if (!attr_alloc_list)
        !          3106:        perror ("unable to allocate in objc-tree.c");
        !          3107:     }
        !          3108:   obj = &attr_alloc_list[attr_alloc_index++];
        !          3109:   obj->next = entry->list;
        !          3110:   obj->value = value;
        !          3111: 
        !          3112:   entry->list = obj;           /* append to front */
        !          3113: }
        !          3114: 
        !          3115: static tree
        !          3116: lookup_method (mchain, method)
        !          3117:      tree mchain;
        !          3118:      tree method;
        !          3119: {
        !          3120:   tree key;
        !          3121: 
        !          3122:   if (TREE_CODE (method) == IDENTIFIER_NODE)
        !          3123:     key = method;
        !          3124:   else
        !          3125:     key = METHOD_SEL_NAME (method);
        !          3126: 
        !          3127:   while (mchain)
        !          3128:     {
        !          3129:       if (METHOD_SEL_NAME (mchain) == key)
        !          3130:        return mchain;
        !          3131:       mchain = TREE_CHAIN (mchain);
        !          3132:     }
        !          3133:   return NULLT;
        !          3134: }
        !          3135: 
        !          3136: static tree
        !          3137: lookup_instance_method_static (interface, ident)
        !          3138:      tree interface;
        !          3139:      tree ident;
        !          3140: {
        !          3141:   tree inter = interface;
        !          3142:   tree chain = CLASS_NST_METHODS (inter);
        !          3143:   tree meth = NULLT;
        !          3144: 
        !          3145:   do
        !          3146:     {
        !          3147:       if (meth = lookup_method (chain, ident))
        !          3148:        return meth;
        !          3149: 
        !          3150:       if (CLASS_CATEGORY_LIST (inter))
        !          3151:        {
        !          3152:          tree category = CLASS_CATEGORY_LIST (inter);
        !          3153:          chain = CLASS_NST_METHODS (category);
        !          3154:     
        !          3155:          do 
        !          3156:            {
        !          3157:              if (meth = lookup_method (chain, ident))
        !          3158:                return meth;
        !          3159:       
        !          3160:              if (category = CLASS_CATEGORY_LIST (category))
        !          3161:                chain = CLASS_NST_METHODS (category);
        !          3162:            }
        !          3163:          while (category);
        !          3164:        }
        !          3165: 
        !          3166:       if (inter = lookup_interface (CLASS_SUPER_NAME (inter)))
        !          3167:        chain = CLASS_NST_METHODS (inter);
        !          3168:     }
        !          3169:   while (inter);
        !          3170: 
        !          3171:   return meth;
        !          3172: }
        !          3173: 
        !          3174: static tree
        !          3175: lookup_class_method_static (interface, ident)
        !          3176:      tree interface;
        !          3177:      tree ident;
        !          3178: {
        !          3179:   tree inter = interface;
        !          3180:   tree chain = CLASS_CLS_METHODS (inter);
        !          3181:   tree meth = NULLT;
        !          3182: 
        !          3183:   do
        !          3184:     {
        !          3185:       if (meth = lookup_method (chain, ident))
        !          3186:        return meth;
        !          3187: 
        !          3188:       if (CLASS_CATEGORY_LIST (inter))
        !          3189:        {
        !          3190:          tree category = CLASS_CATEGORY_LIST (inter);
        !          3191:          chain = CLASS_CLS_METHODS (category);
        !          3192:     
        !          3193:          do 
        !          3194:            {
        !          3195:              if (meth = lookup_method (chain, ident))
        !          3196:                return meth;
        !          3197:       
        !          3198:              if (category = CLASS_CATEGORY_LIST (category))
        !          3199:                chain = CLASS_CLS_METHODS (category);
        !          3200:            }
        !          3201:          while (category);
        !          3202:        }
        !          3203: 
        !          3204:       if (inter = lookup_interface (CLASS_SUPER_NAME (inter)))
        !          3205:        chain = CLASS_CLS_METHODS (inter);
        !          3206:     }
        !          3207:   while (inter);
        !          3208: 
        !          3209:   return meth;
        !          3210: }
        !          3211: 
        !          3212: tree
        !          3213: add_class_method (class, method)
        !          3214:      tree class;
        !          3215:      tree method;
        !          3216: {
        !          3217:   tree mth;
        !          3218:   hash hsh;
        !          3219: 
        !          3220:   if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
        !          3221:     {
        !          3222:       /* put method on list in reverse order */
        !          3223:       TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
        !          3224:       CLASS_CLS_METHODS (class) = method;
        !          3225:     }
        !          3226:   else
        !          3227:     {
        !          3228:       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
        !          3229:        error ("duplicate definition of class method `%s'.",
        !          3230:               IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
        !          3231:       else
        !          3232:         {
        !          3233:          /* check types, if different complain */
        !          3234:          if (!comp_proto_with_proto (method, mth))
        !          3235:            error ("duplicate declaration of class method `%s'.",
        !          3236:                   IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
        !          3237:         }
        !          3238:     }
        !          3239: 
        !          3240:   if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
        !          3241:     {
        !          3242:       /* install on a global chain */
        !          3243:       hash_enter (cls_method_hash_list, method);
        !          3244:     }
        !          3245:   else
        !          3246:     {
        !          3247:       /* check types, if different add to a list */
        !          3248:       if (!comp_proto_with_proto (method, hsh->key))
        !          3249:         hash_add_attr (hsh, method);
        !          3250:     }
        !          3251:   return method;
        !          3252: }
        !          3253: 
        !          3254: tree
        !          3255: add_instance_method (class, method)
        !          3256:      tree class;
        !          3257:      tree method;
        !          3258: {
        !          3259:   tree mth;
        !          3260:   hash hsh;
        !          3261: 
        !          3262:   if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
        !          3263:     {
        !          3264:       /* put method on list in reverse order */
        !          3265:       TREE_CHAIN (method) = CLASS_NST_METHODS (class);
        !          3266:       CLASS_NST_METHODS (class) = method;
        !          3267:     }
        !          3268:   else
        !          3269:     {
        !          3270:       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
        !          3271:        error ("duplicate definition of instance method `%s'.",
        !          3272:               IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
        !          3273:       else
        !          3274:         {
        !          3275:          /* check types, if different complain */
        !          3276:          if (!comp_proto_with_proto (method, mth))
        !          3277:            error ("duplicate declaration of instance method `%s'.",
        !          3278:                   IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
        !          3279:         }
        !          3280:     }
        !          3281: 
        !          3282:   if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
        !          3283:     {
        !          3284:       /* install on a global chain */
        !          3285:       hash_enter (nst_method_hash_list, method);
        !          3286:     }
        !          3287:   else
        !          3288:     {
        !          3289:       /* check types, if different add to a list */
        !          3290:       if (!comp_proto_with_proto (method, hsh->key))
        !          3291:         hash_add_attr (hsh, method);
        !          3292:     }
        !          3293:   return method;
        !          3294: }
        !          3295: 
        !          3296: static tree
        !          3297: add_class (class)
        !          3298:      tree class;
        !          3299: {
        !          3300:   /* put interfaces on list in reverse order */
        !          3301:   TREE_CHAIN (class) = interface_chain;
        !          3302:   interface_chain = class;
        !          3303:   return interface_chain;
        !          3304: }
        !          3305: 
        !          3306: static void
        !          3307: add_category (class, category)
        !          3308:       tree class;
        !          3309:       tree category;
        !          3310: {
        !          3311:   /* put categories on list in reverse order */
        !          3312:   CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
        !          3313:   CLASS_CATEGORY_LIST (class) = category;
        !          3314: }
        !          3315: 
        !          3316: /* called after parsing each instance variable declaration. Necessary to
        !          3317:  * preserve typedefs and implement public/private...
        !          3318:  */
        !          3319: tree
        !          3320: add_instance_variable (class, public, declarator, declspecs, width)
        !          3321:      tree class;
        !          3322:      int public;
        !          3323:      tree declarator;
        !          3324:      tree declspecs;
        !          3325:      tree width;
        !          3326: {
        !          3327:   tree field_decl, raw_decl;
        !          3328: 
        !          3329:   raw_decl = build_tree_list (declspecs        /*purpose*/, declarator/*value*/);
        !          3330: 
        !          3331:   if (CLASS_RAW_IVARS (class))
        !          3332:     chainon (CLASS_RAW_IVARS (class), raw_decl);
        !          3333:   else
        !          3334:     CLASS_RAW_IVARS (class) = raw_decl;
        !          3335: 
        !          3336:   field_decl = grokfield (input_filename, lineno,
        !          3337:                          declarator, declspecs, width);
        !          3338: 
        !          3339:   /* overload the public attribute, it is not used for FIELD_DECL's */
        !          3340:   if (public)
        !          3341:     TREE_PUBLIC (field_decl) = 1;
        !          3342: 
        !          3343:   if (CLASS_IVARS (class))
        !          3344:     chainon (CLASS_IVARS (class), field_decl);
        !          3345:   else
        !          3346:     CLASS_IVARS (class) = field_decl;
        !          3347: 
        !          3348:   return class;
        !          3349: }
        !          3350: 
        !          3351: tree
        !          3352: is_ivar (decl_chain, ident)
        !          3353:      tree decl_chain;
        !          3354:      tree ident;
        !          3355: {
        !          3356:   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
        !          3357:     if (DECL_NAME (decl_chain) == ident)
        !          3358:       return decl_chain;
        !          3359:   return NULL_TREE;
        !          3360: }
        !          3361: 
        !          3362: /* we have an instance variable reference, check to see if it is public...*/
        !          3363: 
        !          3364: int
        !          3365: is_public (expr, identifier)
        !          3366:      tree expr;
        !          3367:      tree identifier;
        !          3368: {
        !          3369:   tree basetype = TREE_TYPE (expr);
        !          3370:   enum tree_code code = TREE_CODE (basetype);
        !          3371:   tree decl;
        !          3372: 
        !          3373:   if (code == RECORD_TYPE)
        !          3374:     {
        !          3375:       if (TREE_STATIC_TEMPLATE (basetype))
        !          3376:        {
        !          3377:          if (decl = is_ivar (TYPE_FIELDS (basetype), identifier))
        !          3378:            {
        !          3379:              /* important diffence between the Stepstone translator:
        !          3380:                 
        !          3381:                 all instance variables should be public within the context
        !          3382:                 of the implementation...
        !          3383:                 */
        !          3384:              if (implementation_context)
        !          3385:                {
        !          3386:                  if ((TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE
        !          3387:                       && CLASS_NAME (implementation_context) == TYPE_NAME (basetype))
        !          3388:                      || (TREE_CODE (implementation_context) == CATEGORY_TYPE
        !          3389:                          && CLASS_NAME (implementation_context) == TYPE_NAME (basetype)))
        !          3390:                    return 1;
        !          3391:                }
        !          3392: 
        !          3393:              if (TREE_PUBLIC (decl))
        !          3394:                return 1;
        !          3395: 
        !          3396:              error ("instance variable `%s' is declared private",
        !          3397:                     IDENTIFIER_POINTER (identifier));
        !          3398:              return 0;
        !          3399:            }
        !          3400:        }
        !          3401:       else if (implementation_context && (basetype == objc_object_reference))
        !          3402:        {
        !          3403:          TREE_TYPE (expr) = _PRIVATE_record;
        !          3404:          if (extra_warnings)
        !          3405:            {
        !          3406:              warning ("static access to object of type `id'");
        !          3407:              warning ("please change to type `%s *'",
        !          3408:                       IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
        !          3409:            }
        !          3410:        }
        !          3411:     }
        !          3412:   return 1;
        !          3413: }
        !          3414: 
        !          3415: /* implement @defs (<classname>) within struct bodies. */
        !          3416: 
        !          3417: tree
        !          3418: get_class_ivars (interface)
        !          3419:      tree interface;
        !          3420: {
        !          3421:   if (!doing_objc_thang)
        !          3422:     fatal ("Objective-C text in C source file");
        !          3423: 
        !          3424:   return build_ivar_chain (interface);
        !          3425: }
        !          3426: 
        !          3427: tree
        !          3428: get_class_reference (interface)
        !          3429:      tree interface;
        !          3430: {
        !          3431:   tree params;
        !          3432: 
        !          3433:   add_class_reference (CLASS_NAME (interface));
        !          3434: 
        !          3435:   params = build_tree_list (NULLT,
        !          3436:                            my_build_string (IDENTIFIER_LENGTH (CLASS_NAME (interface)) + 1,
        !          3437:                                             IDENTIFIER_POINTER (CLASS_NAME (interface))));
        !          3438: 
        !          3439:   return build_function_call (objc_getClass_decl, params);
        !          3440: }
        !          3441: 
        !          3442: /* make sure all entries in "chain" are also in "list" */
        !          3443: 
        !          3444: static void
        !          3445: check_methods (chain, list, mtype)
        !          3446:      tree chain;
        !          3447:      tree list;
        !          3448:      int mtype;
        !          3449: {
        !          3450:   int first = 1;
        !          3451: 
        !          3452:   while (chain)
        !          3453:     {
        !          3454:       if (!lookup_method (list, chain))
        !          3455:        {
        !          3456:          if (first)
        !          3457:            {
        !          3458:              if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
        !          3459:                warning ("incomplete implementation of class `%s'",
        !          3460:                         IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
        !          3461:              else if (TREE_CODE (implementation_context) == CATEGORY_TYPE)
        !          3462:                warning ("incomplete implementation of category `%s'",
        !          3463:                         IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
        !          3464:              first = 0;
        !          3465:            }
        !          3466:          warning ("method definition for `%c%s' not found",
        !          3467:                   mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
        !          3468:        }
        !          3469:       chain = TREE_CHAIN (chain);
        !          3470:     }
        !          3471: }
        !          3472: 
        !          3473: tree
        !          3474: start_class (code, class_name, super_name)
        !          3475:      enum tree_code code;
        !          3476:      tree class_name;
        !          3477:      tree super_name;
        !          3478: {
        !          3479:   tree class;
        !          3480: 
        !          3481:   if (!doing_objc_thang)
        !          3482:      fatal ("Objective-C text in C source file");
        !          3483: 
        !          3484:   class = make_node (code);
        !          3485: 
        !          3486:   CLASS_NAME (class) = class_name;
        !          3487:   CLASS_SUPER_NAME (class) = super_name;
        !          3488:   CLASS_CLS_METHODS (class) = NULL_TREE;
        !          3489: 
        !          3490:   if (code == IMPLEMENTATION_TYPE)
        !          3491:     {
        !          3492:       /* pre-build the following entities - for speed/convenience. */
        !          3493:       if (!self_id)
        !          3494:         self_id = get_identifier ("self");
        !          3495:       if (!_cmd_id)
        !          3496:         _cmd_id = get_identifier ("_cmd");
        !          3497: 
        !          3498:       if (!objc_super_template)
        !          3499:        objc_super_template = build_super_template ();
        !          3500: 
        !          3501:       method_slot = 0;         /* reset for multiple classes per file */
        !          3502: 
        !          3503:       implementation_context = class;
        !          3504: 
        !          3505:       /* lookup the interface for this implementation. */
        !          3506: 
        !          3507:       if (!(implementation_template = lookup_interface (class_name)))
        !          3508:         {
        !          3509:          warning ("Cannot find interface declaration for `%s'",
        !          3510:                   IDENTIFIER_POINTER (class_name));
        !          3511:          add_class (implementation_template = implementation_context);
        !          3512:         }
        !          3513: 
        !          3514:       /* if a super class has been specified in the implementation,
        !          3515:         insure it conforms to the one specified in the interface */
        !          3516: 
        !          3517:       if (super_name
        !          3518:          && (super_name != CLASS_SUPER_NAME (implementation_template)))
        !          3519:         {
        !          3520:          error ("conflicting super class name `%s'",
        !          3521:                 IDENTIFIER_POINTER (super_name));
        !          3522:          error ("previous declaration of `%s'",
        !          3523:                 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)));
        !          3524:         }
        !          3525:     }
        !          3526:   else if (code == INTERFACE_TYPE)
        !          3527:     {
        !          3528:       if (lookup_interface (class_name))
        !          3529:         warning ("duplicate interface declaration for class `%s'",
        !          3530:                  IDENTIFIER_POINTER (class_name));
        !          3531:       else
        !          3532:         add_class (class);
        !          3533:     }
        !          3534:   else if (code == PROTOCOL_TYPE)
        !          3535:     {
        !          3536:       tree class_category_is_assoc_with;
        !          3537: 
        !          3538:       /* for a category, class_name is really the name of the class that
        !          3539:         the following set of methods will be associated with...we must
        !          3540:         find the interface so that can derive the objects template */
        !          3541: 
        !          3542:       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
        !          3543:        {
        !          3544:          error ("Cannot find interface declaration for `%s'",
        !          3545:                 IDENTIFIER_POINTER (class_name));
        !          3546:          exit (1);
        !          3547:        }
        !          3548:       else
        !          3549:         add_category (class_category_is_assoc_with, class);
        !          3550:     }
        !          3551:   else if (code == CATEGORY_TYPE)
        !          3552:     {
        !          3553:       /* pre-build the following entities - for speed/convenience. */
        !          3554:       if (!self_id)
        !          3555:         self_id = get_identifier ("self");
        !          3556:       if (!_cmd_id)
        !          3557:         _cmd_id = get_identifier ("_cmd");
        !          3558: 
        !          3559:       if (!objc_super_template)
        !          3560:        objc_super_template = build_super_template ();
        !          3561: 
        !          3562:       method_slot = 0;         /* reset for multiple classes per file */
        !          3563: 
        !          3564:       implementation_context = class;
        !          3565: 
        !          3566:       /* for a category, class_name is really the name of the class that
        !          3567:         the following set of methods will be associated with...we must
        !          3568:         find the interface so that can derive the objects template */
        !          3569: 
        !          3570:       if (!(implementation_template = lookup_interface (class_name)))
        !          3571:         {
        !          3572:          error ("Cannot find interface declaration for `%s'",
        !          3573:                 IDENTIFIER_POINTER (class_name));
        !          3574:          exit (1);
        !          3575:         }
        !          3576:     }
        !          3577:   return class;
        !          3578: }
        !          3579: 
        !          3580: tree
        !          3581: continue_class (class)
        !          3582:      tree class;
        !          3583: {
        !          3584:   if (TREE_CODE (class) == IMPLEMENTATION_TYPE
        !          3585:       || TREE_CODE (class) == CATEGORY_TYPE)
        !          3586:     {
        !          3587:       struct imp_entry *impEntry;
        !          3588:       tree ivar_context;
        !          3589: 
        !          3590:       /* check consistency of the instance variables. */
        !          3591: 
        !          3592:       if (CLASS_IVARS (class))
        !          3593:        check_ivars (implementation_template, class);
        !          3594: 
        !          3595:       /* code generation */
        !          3596: 
        !          3597:       ivar_context = build_private_template (implementation_template);
        !          3598: 
        !          3599:       if (!objc_class_template)
        !          3600:        build_class_template ();
        !          3601: 
        !          3602:       if (!(impEntry = (struct imp_entry *)xmalloc (sizeof (struct imp_entry))))
        !          3603:        perror ("unable to allocate in objc-tree.c");
        !          3604: 
        !          3605:       impEntry->next = imp_list;
        !          3606:       impEntry->imp_context = class;
        !          3607:       impEntry->imp_template = implementation_template;
        !          3608: 
        !          3609:       synth_forward_declarations ();
        !          3610:       impEntry->class_decl = _OBJC_CLASS_decl;
        !          3611:       impEntry->meta_decl = _OBJC_METACLASS_decl;
        !          3612: 
        !          3613:       /* append to front and increment count */
        !          3614:       imp_list = impEntry;
        !          3615:       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
        !          3616:        imp_count++;
        !          3617:       else
        !          3618:        cat_count++;
        !          3619: 
        !          3620:       return ivar_context;
        !          3621:     }
        !          3622:   else if (TREE_CODE (class) == INTERFACE_TYPE)
        !          3623:     {
        !          3624:       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
        !          3625: 
        !          3626:       if (!TYPE_FIELDS (record))
        !          3627:        {
        !          3628:          finish_struct (record, build_ivar_chain (class));
        !          3629:          CLASS_STATIC_TEMPLATE (class) = record;
        !          3630: 
        !          3631:          /* mark this record as a class template - for static typing */
        !          3632:          TREE_STATIC_TEMPLATE (record) = 1;
        !          3633:        }
        !          3634:       return NULLT;
        !          3635:     }
        !          3636:   else
        !          3637:     return error_mark_node;
        !          3638: }
        !          3639: 
        !          3640: /*
        !          3641:  * this is called once we see the "@end" in an interface/implementation.
        !          3642:  */
        !          3643: void
        !          3644: finish_class (class)
        !          3645:      tree class;
        !          3646: {
        !          3647:   if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
        !          3648:     {
        !          3649:       /* all code generation is done in finish_objc */
        !          3650: 
        !          3651:       if (implementation_template != implementation_context)
        !          3652:        {
        !          3653:          /* ensure that all method listed in the interface contain bodies! */
        !          3654:          check_methods (CLASS_CLS_METHODS (implementation_template),
        !          3655:                         CLASS_CLS_METHODS (implementation_context), '+');
        !          3656:          check_methods (CLASS_NST_METHODS (implementation_template),
        !          3657:                         CLASS_NST_METHODS (implementation_context), '-');
        !          3658:        }
        !          3659:     }
        !          3660:   else if (TREE_CODE (class) == CATEGORY_TYPE)
        !          3661:     {
        !          3662:       tree category = CLASS_CATEGORY_LIST (implementation_template);
        !          3663:   
        !          3664:       /* find the category interface from the class it is associated with */
        !          3665:       while (category)
        !          3666:        {
        !          3667:          if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
        !          3668:            break;
        !          3669:          category = CLASS_CATEGORY_LIST (category);
        !          3670:        }
        !          3671:   
        !          3672:       if (category)
        !          3673:        {
        !          3674:          /* ensure that all method listed in the interface contain bodies! */
        !          3675:          check_methods (CLASS_CLS_METHODS (category),
        !          3676:                         CLASS_CLS_METHODS (implementation_context), '+');
        !          3677:          check_methods (CLASS_NST_METHODS (category),
        !          3678:                         CLASS_NST_METHODS (implementation_context), '-');
        !          3679:        }
        !          3680:     } 
        !          3681:   else if (TREE_CODE (class) == INTERFACE_TYPE)
        !          3682:     {
        !          3683:       tree decl_specs;
        !          3684: 
        !          3685:       /* extern struct objc_object *_<my_name>; */
        !          3686: 
        !          3687:       sprintf (utlbuf, "_%s", IDENTIFIER_POINTER (CLASS_NAME (class)));
        !          3688: 
        !          3689:       decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
        !          3690:       decl_specs = tree_cons (NULLT, objc_object_reference, decl_specs);
        !          3691:       define_decl (build1 (INDIRECT_REF, NULLT, get_identifier (utlbuf)), decl_specs);
        !          3692:     }
        !          3693: }
        !          3694: 
        !          3695: static void
        !          3696: encode_pointer (type, str, format)
        !          3697:      tree type;
        !          3698:      char *str;
        !          3699:      int format;
        !          3700: {
        !          3701:   tree pointer_to = TREE_TYPE (type);
        !          3702: 
        !          3703:   if (TREE_CODE (pointer_to) == RECORD_TYPE)
        !          3704:     {
        !          3705:       if (TYPE_NAME (pointer_to)
        !          3706:          && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
        !          3707:        {
        !          3708:          char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
        !          3709: 
        !          3710:          if ((strcmp (name, TAG_OBJECT) == 0) || /* '@' */
        !          3711:              (TREE_STATIC_TEMPLATE (pointer_to)))
        !          3712:            {
        !          3713:              strcat (str, "@");
        !          3714:              return;
        !          3715:            }
        !          3716:          else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
        !          3717:            {
        !          3718:              strcat (str, "#");
        !          3719:              return;
        !          3720:            }
        !          3721: #ifndef OBJC_INT_SELECTORS
        !          3722:          else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
        !          3723:            {
        !          3724:              strcat (str, ":");
        !          3725:              return;
        !          3726:            }
        !          3727: #endif /* OBJC_INT_SELECTORS */
        !          3728:        }
        !          3729:     }
        !          3730:   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
        !          3731:           && TYPE_MODE (pointer_to) == QImode)
        !          3732:     {
        !          3733:       strcat (str, "*");
        !          3734:       return;
        !          3735:     }
        !          3736: 
        !          3737:   /* we have a type that does not get special treatment... */
        !          3738: 
        !          3739:   /* NeXT extension */
        !          3740:   strcat (str, "^");
        !          3741:   encode_type (pointer_to, str, format);
        !          3742: }
        !          3743: 
        !          3744: static void
        !          3745: encode_array (type, str, format)
        !          3746:      tree type;
        !          3747:      char *str;
        !          3748:      int format;
        !          3749: {
        !          3750:   tree anIntCst = TYPE_SIZE (type);
        !          3751:   tree array_of = TREE_TYPE (type);
        !          3752: 
        !          3753:   /* An incomplete array is treated like a pointer.  */
        !          3754:   if (anIntCst == NULL)
        !          3755:     {
        !          3756:       /* split for obvious reasons.  North-Keys 30 Mar 1991 */
        !          3757:       encode_pointer (type, str, format);
        !          3758:       return;
        !          3759:     }
        !          3760:   
        !          3761:   sprintf (str + strlen (str), "[%d",
        !          3762:           TREE_INT_CST_LOW (anIntCst)
        !          3763:           / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
        !          3764:   encode_type (array_of, str, format);
        !          3765:   strcat (str, "]");
        !          3766:   return;
        !          3767: }
        !          3768: 
        !          3769: static void
        !          3770: encode_aggregate (type, str, format)
        !          3771:      tree type;
        !          3772:      char *str;
        !          3773:      int format;
        !          3774: {
        !          3775:   enum tree_code code = TREE_CODE (type);
        !          3776: 
        !          3777:   switch (code)
        !          3778:     {
        !          3779:     case RECORD_TYPE:
        !          3780:       {
        !          3781:        if (str[strlen (str)-1] == '^')
        !          3782:          {
        !          3783:            /* we have a reference - this is a NeXT extension */
        !          3784:             if (TYPE_NAME (type)
        !          3785:                && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE))
        !          3786:              sprintf (str + strlen (str), "{%s}",
        !          3787:                       IDENTIFIER_POINTER (TYPE_NAME (type)));
        !          3788:            else                /* we have an untagged structure or a typedef */
        !          3789:              sprintf (str + strlen (str), "{?}");
        !          3790:          }
        !          3791:        else
        !          3792:          {
        !          3793:            tree fields = TYPE_FIELDS (type);
        !          3794: 
        !          3795:             if (format == OBJC_ENCODE_INLINE_DEFS)
        !          3796:               {
        !          3797:                strcat (str, "{");
        !          3798:                for ( ; fields; fields = TREE_CHAIN (fields))
        !          3799:                  encode_field_decl (fields, str, format);
        !          3800:                strcat (str, "}");
        !          3801:               }
        !          3802:             else
        !          3803:               {
        !          3804:                if (TYPE_NAME (type)
        !          3805:                    && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE))
        !          3806:                  sprintf (str + strlen (str), "{%s}",
        !          3807:                           IDENTIFIER_POINTER (TYPE_NAME (type)));
        !          3808:                else            /* we have an untagged structure or a typedef */
        !          3809:                  sprintf (str + strlen (str), "{?}");
        !          3810:               }
        !          3811:          }
        !          3812:        break;
        !          3813:       }
        !          3814:     case UNION_TYPE:
        !          3815:       {
        !          3816:        if (str[strlen (str)-1] == '^')
        !          3817:          {
        !          3818:             if (TYPE_NAME (type)
        !          3819:                && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE))
        !          3820:              /* we have a reference - this is a NeXT extension */
        !          3821:              sprintf (str + strlen (str), "(%s)",
        !          3822:                       IDENTIFIER_POINTER (TYPE_NAME (type)));
        !          3823:            else                /* we have an untagged structure */
        !          3824:              sprintf (str + strlen (str), "(?)");
        !          3825:          }
        !          3826:        else
        !          3827:          {
        !          3828:            tree fields = TYPE_FIELDS (type);
        !          3829: 
        !          3830:             if (format == OBJC_ENCODE_INLINE_DEFS)
        !          3831:               {
        !          3832:                strcat (str, "(");
        !          3833:                for ( ; fields; fields = TREE_CHAIN (fields))
        !          3834:                  encode_field_decl (fields, str, format);
        !          3835:                strcat (str, ")");
        !          3836:               }
        !          3837:             else
        !          3838:               {
        !          3839:                if (TYPE_NAME (type) &&
        !          3840:                    (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE))
        !          3841:                  /* we have a reference - this is a NeXT extension */
        !          3842:                  sprintf (str + strlen (str), "(%s)",
        !          3843:                           IDENTIFIER_POINTER (TYPE_NAME (type)));
        !          3844:                else            /* we have an untagged structure */
        !          3845:                  sprintf (str + strlen (str), "(?)");
        !          3846:               }
        !          3847:          }
        !          3848:        break;
        !          3849:       }
        !          3850:     case ENUMERAL_TYPE:
        !          3851:       strcat (str, "i");
        !          3852:       break;
        !          3853:     }
        !          3854: }
        !          3855: 
        !          3856: /*
        !          3857:  *  support bitfields, the current version of Objective-C does not support
        !          3858:  *  them. the string will consist of one or more "b:n"'s where n is an
        !          3859:  *  integer describing the width of the bitfield. Currently, classes in
        !          3860:  *  the kit implement a method "-(char *)describeBitfieldStruct:" that
        !          3861:  *  simulates this...if they do not implement this method, the archiver
        !          3862:  *  assumes the bitfield is 16 bits wide (padded if necessary) and packed
        !          3863:  *  according to the GNU compiler. After looking at the "kit", it appears
        !          3864:  *  that all classes currently rely on this default behavior, rather than
        !          3865:  *  hand generating this string (which is tedious).
        !          3866:  */
        !          3867: static void
        !          3868: encode_bitfield (width, str, format)
        !          3869:      int width;
        !          3870:      char *str;
        !          3871:      int format;
        !          3872: {
        !          3873:   sprintf (str + strlen (str), "b%d", width);
        !          3874: }
        !          3875: 
        !          3876: /*
        !          3877:  *     format will be:
        !          3878:  *
        !          3879:  *     OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS
        !          3880:  */
        !          3881: static void
        !          3882: encode_type (type, str, format)
        !          3883:      tree type;
        !          3884:      char *str;
        !          3885:      int format;
        !          3886: {
        !          3887:   enum tree_code code = TREE_CODE (type);
        !          3888: 
        !          3889:   if (code == INTEGER_TYPE)
        !          3890:     {
        !          3891:       if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0)
        !          3892:        {
        !          3893:          /* unsigned integer types */
        !          3894: 
        !          3895:          if (TYPE_MODE (type) == QImode) /* 'C' */
        !          3896:            strcat (str, "C");
        !          3897:          else if (TYPE_MODE (type) == HImode) /* 'S' */
        !          3898:            strcat (str, "S");
        !          3899:          else if (TYPE_MODE (type) == SImode)
        !          3900:            {
        !          3901:              if (type == long_unsigned_type_node)
        !          3902:                strcat (str, "L"); /* 'L' */
        !          3903:              else
        !          3904:                strcat (str, "I"); /* 'I' */
        !          3905:            }
        !          3906:        }
        !          3907:       else                     /* signed integer types */
        !          3908:        {
        !          3909:          if (TYPE_MODE (type) == QImode) /* 'c' */
        !          3910:            strcat (str, "c");
        !          3911:          else if (TYPE_MODE (type) == HImode) /* 's' */
        !          3912:            strcat (str, "s");
        !          3913:          else if (TYPE_MODE (type) == SImode) /* 'i' */
        !          3914:            {
        !          3915:              if (type == long_integer_type_node)
        !          3916:                strcat (str, "l"); /* 'l' */
        !          3917:              else
        !          3918:                strcat (str, "i"); /* 'i' */
        !          3919:            }
        !          3920:        }
        !          3921:     }
        !          3922:   else if (code == REAL_TYPE)
        !          3923:     {
        !          3924:       /* floating point types */
        !          3925: 
        !          3926:       if (TYPE_MODE (type) == SFmode) /* 'f' */
        !          3927:        strcat (str, "f");
        !          3928:       else if (TYPE_MODE (type) == DFmode
        !          3929:               || TYPE_MODE (type) == TFmode) /* 'd' */
        !          3930:        strcat (str, "d");
        !          3931:     }
        !          3932: 
        !          3933:   else if (code == VOID_TYPE)  /* 'v' */
        !          3934:     strcat (str, "v");
        !          3935: 
        !          3936:   else if (code == ARRAY_TYPE)
        !          3937:     encode_array (type, str, format);
        !          3938: 
        !          3939:   else if (code == POINTER_TYPE)
        !          3940:     encode_pointer (type, str, format);
        !          3941: 
        !          3942:   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
        !          3943:     encode_aggregate (type, str, format);
        !          3944: 
        !          3945:   else if (code == FUNCTION_TYPE) /* '?' */
        !          3946:     strcat (str, "?");
        !          3947: }
        !          3948: 
        !          3949: static void
        !          3950: encode_field_decl (field_decl, str, format)
        !          3951:      tree field_decl;
        !          3952:      char *str;
        !          3953:      int format;
        !          3954: {
        !          3955:   if (DECL_BIT_FIELD (field_decl))
        !          3956:     encode_bitfield (DECL_FRAME_SIZE (field_decl), str, format);
        !          3957:   else
        !          3958:     encode_type (TREE_TYPE (field_decl), str, format);
        !          3959: }
        !          3960: 
        !          3961: static tree
        !          3962: expr_last (complex_expr)
        !          3963:      tree complex_expr;
        !          3964: {
        !          3965:   tree next;
        !          3966: 
        !          3967:   if (complex_expr)
        !          3968:     while (next = TREE_OPERAND (complex_expr, 0))
        !          3969:       complex_expr = next;
        !          3970:   return complex_expr;
        !          3971: }
        !          3972: 
        !          3973: /* The selector of the current method,
        !          3974:    or NULL if we aren't compiling a method.  */
        !          3975: 
        !          3976: tree
        !          3977: maybe_objc_method_name (decl)
        !          3978:       tree decl;
        !          3979: {
        !          3980:   if (method_context)
        !          3981:     return METHOD_SEL_NAME (method_context);
        !          3982:   else
        !          3983:     return 0;
        !          3984: }
        !          3985: 
        !          3986: /*
        !          3987:  *  Transform a method definition into a function definition as follows:
        !          3988:  *
        !          3989:  *  - synthesize the first two arguments, "self" and "_cmd".
        !          3990:  */
        !          3991: 
        !          3992: void
        !          3993: start_method_def (method)
        !          3994:      tree method;
        !          3995: {
        !          3996:   tree decl_specs;
        !          3997: 
        !          3998:   /* required to implement _msgSuper () */
        !          3999:   method_context = method;
        !          4000:   _OBJC_SUPER_decl = NULLT;
        !          4001: 
        !          4002:   pushlevel (0);               /* must be called BEFORE "start_function ()" */
        !          4003: 
        !          4004:   /* generate prototype declarations for arguments..."new-style" */
        !          4005: 
        !          4006:   if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
        !          4007:     decl_specs = build_tree_list (NULLT, _PRIVATE_record);
        !          4008:   else
        !          4009:     /* really a `struct objc_class *'...however we allow people to
        !          4010:        assign to self...which changes its type midstream.
        !          4011:        */
        !          4012:     decl_specs = build_tree_list (NULLT, objc_object_reference);
        !          4013: 
        !          4014:   push_parm_decl (build_tree_list (decl_specs,
        !          4015:                                   build1 (INDIRECT_REF, NULLT, self_id)));
        !          4016: 
        !          4017: #ifdef OBJC_INT_SELECTORS
        !          4018:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
        !          4019:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !          4020:   push_parm_decl (build_tree_list (decl_specs, _cmd_id));
        !          4021: #else /* not OBJC_INT_SELECTORS */
        !          4022:   decl_specs = build_tree_list (NULLT,
        !          4023:                                xref_tag (RECORD_TYPE,
        !          4024:                                          get_identifier (TAG_SELECTOR)));
        !          4025:   push_parm_decl (build_tree_list (decl_specs, 
        !          4026:                                   build1 (INDIRECT_REF, NULLT, _cmd_id)));
        !          4027: #endif /* not OBJC_INT_SELECTORS */
        !          4028: 
        !          4029:   /* generate argument delclarations if a keyword_decl */
        !          4030:   if (METHOD_SEL_ARGS (method))
        !          4031:     {
        !          4032:       tree arglist = METHOD_SEL_ARGS (method);
        !          4033:       do
        !          4034:        {
        !          4035:          tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
        !          4036:          tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
        !          4037: 
        !          4038:          if (arg_decl)
        !          4039:            {
        !          4040:              tree last_expr = expr_last (arg_decl);
        !          4041: 
        !          4042:              /* unite the abstract decl with its name */
        !          4043:              TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
        !          4044:              push_parm_decl (build_tree_list (arg_spec, arg_decl));
        !          4045:              /* unhook...restore the abstract declarator */
        !          4046:              TREE_OPERAND (last_expr, 0) = NULLT;
        !          4047:            }
        !          4048:          else
        !          4049:            push_parm_decl (build_tree_list (arg_spec, KEYWORD_ARG_NAME (arglist)));
        !          4050: 
        !          4051:          arglist = TREE_CHAIN (arglist);
        !          4052:        }
        !          4053:       while (arglist);
        !          4054:     }
        !          4055: 
        !          4056:   if (METHOD_ADD_ARGS (method) > (tree)1)
        !          4057:     {
        !          4058:       /* we have a variable length selector - in "prototype" format */
        !          4059:       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
        !          4060:       while (akey)
        !          4061:        {
        !          4062:          /* this must be done prior to calling pushdecl (). pushdecl () is
        !          4063:           * going to change our chain on us...
        !          4064:           */
        !          4065:          tree nextkey = TREE_CHAIN (akey);
        !          4066:          pushdecl (akey);
        !          4067:          akey = nextkey;
        !          4068:        }
        !          4069:     }
        !          4070: }
        !          4071: 
        !          4072: static void
        !          4073: error_with_method (message, mtype, method)
        !          4074:      char *message;
        !          4075:      char mtype;
        !          4076:      tree method;
        !          4077: {
        !          4078:   count_error (0);
        !          4079:   fprintf (stderr, "%s:%d: ",
        !          4080:           DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
        !          4081:   bzero (errbuf, BUFSIZE);
        !          4082:   fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
        !          4083: }
        !          4084: 
        !          4085: static void
        !          4086: warn_with_method (message, mtype, method)
        !          4087:      char *message;
        !          4088:      char mtype;
        !          4089:      tree method;
        !          4090: {
        !          4091:   count_error (1);
        !          4092:   fprintf (stderr, "%s:%d: ",
        !          4093:           DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
        !          4094:   bzero (errbuf, BUFSIZE);
        !          4095:   fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
        !          4096: }
        !          4097: 
        !          4098: /* return 1 if `method' is consistent with `proto' */
        !          4099: 
        !          4100: static int
        !          4101: comp_method_with_proto (method, proto)
        !          4102:      tree method, proto;
        !          4103: {
        !          4104:   static tree function_type = 0;
        !          4105: 
        !          4106:   /* create a function_type node once */
        !          4107:   if (!function_type)
        !          4108:     {
        !          4109:       struct obstack *ambient_obstack = current_obstack;
        !          4110:       
        !          4111:       current_obstack = &permanent_obstack;
        !          4112:       function_type = make_node (FUNCTION_TYPE);
        !          4113:       current_obstack = ambient_obstack;
        !          4114:     }
        !          4115: 
        !          4116:   /* install argument types - normally set by "build_function_type ()". */
        !          4117:   TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
        !          4118: 
        !          4119:   /* install return type */
        !          4120:   TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
        !          4121: 
        !          4122:   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
        !          4123: }
        !          4124: 
        !          4125: /* return 1 if `proto1' is consistent with `proto2' */
        !          4126: 
        !          4127: static int
        !          4128: comp_proto_with_proto (proto1, proto2)
        !          4129:      tree proto1, proto2;
        !          4130: {
        !          4131:   static tree function_type1 = 0, function_type2 = 0;
        !          4132: 
        !          4133:   /* create a couple function_type node's once */
        !          4134:   if (!function_type1)
        !          4135:     {
        !          4136:       struct obstack *ambient_obstack = current_obstack;
        !          4137:       
        !          4138:       current_obstack = &permanent_obstack;
        !          4139:       function_type1 = make_node (FUNCTION_TYPE);
        !          4140:       function_type2 = make_node (FUNCTION_TYPE);
        !          4141:       current_obstack = ambient_obstack;
        !          4142:     }
        !          4143: 
        !          4144:   /* install argument types - normally set by "build_function_type ()". */
        !          4145:   TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
        !          4146:   TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
        !          4147: 
        !          4148:   /* install return type */
        !          4149:   TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
        !          4150:   TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
        !          4151: 
        !          4152:   return comptypes (function_type1, function_type2);
        !          4153: }
        !          4154: 
        !          4155: /*
        !          4156:  *  - generate an identifier for the function. the format is "_n_cls",
        !          4157:  *    where 1 <= n <= nMethods, and cls is the name the implementation we
        !          4158:  *    are processing.
        !          4159:  *  - install the return type from the method declaration.
        !          4160:  *  - if we have a prototype, check for type consistency.
        !          4161:  */
        !          4162: static void
        !          4163: really_start_method (method, parmlist)
        !          4164:      tree method, parmlist;
        !          4165: {
        !          4166:   tree sc_spec, ret_spec, ret_decl, decl_specs;
        !          4167:   tree method_decl, method_id;
        !          4168:   char buf[256];
        !          4169: 
        !          4170:   /* synth the storage class & assemble the return type */
        !          4171:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          4172:   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
        !          4173:   decl_specs = chainon (sc_spec, ret_spec);
        !          4174: 
        !          4175:   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
        !          4176: #ifdef OBJC_GEN_METHOD_LABEL
        !          4177:     OBJC_GEN_METHOD_LABEL (buf,
        !          4178:       TREE_CODE (method) == INSTANCE_METHOD_DECL,
        !          4179:       IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
        !          4180:       NULL,
        !          4181:       IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
        !          4182: #else
        !          4183:     sprintf (buf, "_%d_%s", ++method_slot,
        !          4184:             IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
        !          4185: #endif
        !          4186:   else                         /* we have a category */
        !          4187: #ifdef OBJC_GEN_METHOD_LABEL
        !          4188:     OBJC_GEN_METHOD_LABEL (buf,
        !          4189:       TREE_CODE (method) == INSTANCE_METHOD_DECL,
        !          4190:       IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
        !          4191:       IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)),
        !          4192:       IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
        !          4193: #else
        !          4194:     sprintf (buf, "_%d_%s_%s", ++method_slot,
        !          4195:             IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
        !          4196:             IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
        !          4197: #endif
        !          4198: 
        !          4199:   method_id = get_identifier (buf);
        !          4200: 
        !          4201:   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULLT);
        !          4202: 
        !          4203:   /* check the delclarator portion of the return type for the method */
        !          4204:   if (ret_decl = TREE_VALUE (TREE_TYPE (method)))
        !          4205:     {
        !          4206:       /*
        !          4207:        * unite the complex decl (specified in the abstract decl) with the
        !          4208:        * function decl just synthesized...(int *), (int (*)()), (int (*)[]).
        !          4209:        */
        !          4210:       tree save_expr = expr_last (ret_decl);
        !          4211: 
        !          4212:       TREE_OPERAND (save_expr, 0) = method_decl;
        !          4213:       method_decl = ret_decl;
        !          4214:       /* fool the parser into thinking it is starting a function */
        !          4215:       start_function (decl_specs, method_decl, 0);
        !          4216:       /* unhook...this has the effect of restoring the abstract declarator */
        !          4217:       TREE_OPERAND (save_expr, 0) = NULLT;
        !          4218:     }
        !          4219:   else
        !          4220:     {
        !          4221:       TREE_VALUE (TREE_TYPE (method)) = method_decl;
        !          4222:       /* fool the parser into thinking it is starting a function */
        !          4223:       start_function (decl_specs, method_decl, 0);
        !          4224:       /* unhook...this has the effect of restoring the abstract declarator */
        !          4225:       TREE_VALUE (TREE_TYPE (method)) = NULLT;
        !          4226:     }
        !          4227: 
        !          4228:   METHOD_DEFINITION (method) = current_function_decl;
        !          4229: 
        !          4230:   /* check consistency...start_function (), pushdecl (), duplicate_decls (). */
        !          4231: 
        !          4232:   if (implementation_template != implementation_context)
        !          4233:     {
        !          4234:       tree chain, proto;
        !          4235: 
        !          4236:       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
        !          4237:        chain = CLASS_NST_METHODS (implementation_template);
        !          4238:       else
        !          4239:        chain = CLASS_CLS_METHODS (implementation_template);
        !          4240: 
        !          4241:       if (proto = lookup_method (chain, METHOD_SEL_NAME (method)))
        !          4242:        {
        !          4243:          if (!comp_method_with_proto (method, proto))
        !          4244:            {
        !          4245:              fprintf (stderr, "%s: In method `%s'\n", input_filename,
        !          4246:                       IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
        !          4247:              if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
        !          4248:                {
        !          4249:                  error_with_method ("conflicting types for", '-', method);
        !          4250:                  error_with_method ("previous declaration of", '-', proto);
        !          4251:                }
        !          4252:              else
        !          4253:                {
        !          4254:                  error_with_method ("conflicting types for", '+', method);
        !          4255:                  error_with_method ("previous declaration of", '+', proto);
        !          4256:                }
        !          4257:            }
        !          4258:        }
        !          4259:     }
        !          4260: }
        !          4261: 
        !          4262: /*
        !          4263:  * the following routine is always called...this "architecture" is to
        !          4264:  * accommodate "old-style" variable length selectors.
        !          4265:  *
        !          4266:  *     - a:a b:b // prototype  ; id c; id d; // old-style
        !          4267:  */
        !          4268: void
        !          4269: continue_method_def ()
        !          4270: {
        !          4271:   tree parmlist;
        !          4272: 
        !          4273:   if (METHOD_ADD_ARGS (method_context) == (tree)1)
        !          4274:     /*
        !          4275:      * we have a `, ...' immediately following the selector.
        !          4276:      */
        !          4277:     parmlist = get_parm_info (0);
        !          4278:   else
        !          4279:     parmlist = get_parm_info (1); /* place a `void_at_end' */
        !          4280: 
        !          4281:   /* set self_decl from the first argument...this global is used by
        !          4282:    * build_ivar_reference ().build_indirect_ref ().
        !          4283:    */
        !          4284:   self_decl = TREE_PURPOSE (parmlist);
        !          4285: 
        !          4286:   poplevel (0, 0, 0);          /* must be called BEFORE "start_function ()" */
        !          4287: 
        !          4288:   really_start_method (method_context, parmlist);
        !          4289: 
        !          4290:   store_parm_decls ();         /* must be called AFTER "start_function ()" */
        !          4291: }
        !          4292: 
        !          4293: void
        !          4294: add_objc_decls ()
        !          4295: {
        !          4296:   if (!_OBJC_SUPER_decl)
        !          4297:     _OBJC_SUPER_decl = start_decl (get_identifier (_TAG_SUPER),
        !          4298:                                   build_tree_list (NULLT, objc_super_template), 0);
        !          4299: 
        !          4300:   /* this prevents `unused variable' warnings when compiling with `-Wall' */
        !          4301:   TREE_USED (_OBJC_SUPER_decl) = 1;
        !          4302: }
        !          4303: 
        !          4304: /*
        !          4305:  *     _n_Method (id self, SEL sel, ...)
        !          4306:  *     {
        !          4307:  *             struct objc_super _S;
        !          4308:  *
        !          4309:  *             _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
        !          4310:  *     }
        !          4311:  */
        !          4312: tree
        !          4313: get_super_receiver ()
        !          4314: {
        !          4315:   if (method_context)
        !          4316:     {
        !          4317:       tree super_expr, super_expr_list;
        !          4318: 
        !          4319:       /* set receiver to self */
        !          4320:       super_expr = build_component_ref (_OBJC_SUPER_decl, self_id);
        !          4321:       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
        !          4322:       super_expr_list = build_tree_list (NULLT, super_expr);
        !          4323: 
        !          4324:       /* set class to begin searching */
        !          4325:       super_expr = build_component_ref (_OBJC_SUPER_decl, get_identifier ("class"));
        !          4326: 
        !          4327:       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
        !          4328:        {
        !          4329:          /* [_cls, __cls]Super are "pre-built" in synth_foward_declarations () */
        !          4330: 
        !          4331:          if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
        !          4332:            super_expr = build_modify_expr (super_expr, NOP_EXPR, _clsSuper_ref);
        !          4333:          else
        !          4334:            super_expr = build_modify_expr (super_expr, NOP_EXPR, __clsSuper_ref);
        !          4335:        }
        !          4336:       else                     /* we have a category... */
        !          4337:        {
        !          4338:          tree params, super_name = CLASS_SUPER_NAME (implementation_template);
        !          4339:          tree funcCall;
        !          4340: 
        !          4341:          if (!super_name)  /* Barf if super used in a category of Object. */
        !          4342:            {
        !          4343:              error("no super class declared in interface for `%s'",
        !          4344:                    IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
        !          4345:              return error_mark_node;
        !          4346:            }
        !          4347: 
        !          4348:          add_class_reference (super_name);
        !          4349: 
        !          4350:          params = build_tree_list (NULLT,
        !          4351:                                    my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
        !          4352:                                                     IDENTIFIER_POINTER (super_name)));
        !          4353: 
        !          4354:          if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
        !          4355:            funcCall = build_function_call (objc_getClass_decl, params);
        !          4356:          else
        !          4357:            funcCall = build_function_call (objc_getMetaClass_decl, params);
        !          4358: 
        !          4359:          /* cast! */
        !          4360:          TREE_TYPE (funcCall) = TREE_TYPE (_clsSuper_ref);
        !          4361:          super_expr = build_modify_expr (super_expr, NOP_EXPR, funcCall);
        !          4362:        }
        !          4363:       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
        !          4364: 
        !          4365:       super_expr = build_unary_op (ADDR_EXPR, _OBJC_SUPER_decl, 0);
        !          4366:       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
        !          4367: 
        !          4368:       return build_compound_expr (super_expr_list);
        !          4369:     }
        !          4370:   else
        !          4371:     {
        !          4372:       error ("[super ...] must appear in a method context");
        !          4373:       return error_mark_node;
        !          4374:     }
        !          4375: }
        !          4376: 
        !          4377: static tree
        !          4378: encode_method_def (func_decl)
        !          4379:       tree func_decl;
        !          4380: {
        !          4381:   tree parms;
        !          4382:   int stack_size = 0;
        !          4383: 
        !          4384:   bzero (utlbuf, BUFSIZE);
        !          4385: 
        !          4386:   /* return type */
        !          4387:   encode_type (TREE_TYPE (TREE_TYPE (func_decl)), utlbuf, 
        !          4388:               OBJC_ENCODE_DONT_INLINE_DEFS);
        !          4389:   /* stack size */
        !          4390:   for (parms = DECL_ARGUMENTS (func_decl); parms;
        !          4391:        parms = TREE_CHAIN (parms))
        !          4392:     stack_size += TREE_INT_CST_LOW (TYPE_SIZE (DECL_ARG_TYPE (parms)))
        !          4393:                  / BITS_PER_UNIT;
        !          4394: 
        !          4395:   sprintf (&utlbuf[strlen (utlbuf)], "%d", stack_size);
        !          4396: 
        !          4397:   /* argument types */
        !          4398:   for (parms = DECL_ARGUMENTS (func_decl); parms;
        !          4399:        parms = TREE_CHAIN (parms))
        !          4400:     {
        !          4401:       int offset_in_bytes;
        !          4402:   
        !          4403:       /* type */ 
        !          4404:       encode_type (TREE_TYPE (parms), utlbuf, OBJC_ENCODE_DONT_INLINE_DEFS);
        !          4405:   
        !          4406:       /* compute offset */
        !          4407:       if (GET_CODE (DECL_INCOMING_RTL (parms)) == MEM)
        !          4408:         {
        !          4409:          rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
        !          4410:          
        !          4411:          /* ??? Here we assume that the parm address is indexed
        !          4412:              off the frame pointer or arg pointer.
        !          4413:              If that is not true, we produce meaningless results,
        !          4414:              but do not crash.  */
        !          4415:          if (GET_CODE (addr) == PLUS
        !          4416:              && GET_CODE (XEXP (addr, 1)) == CONST_INT)
        !          4417:            offset_in_bytes = INTVAL (XEXP (addr, 1));
        !          4418:          else
        !          4419:            offset_in_bytes = 0;
        !          4420:          
        !          4421:          /* This is the case where the parm is passed as an int or double
        !          4422:              and it is converted to a char, short or float and stored back
        !          4423:              in the parmlist.  In this case, describe the parm
        !          4424:              with the variable's declared type, and adjust the address
        !          4425:              if the least significant bytes (which we are using) are not
        !          4426:              the first ones.  */
        !          4427: #if BYTES_BIG_ENDIAN
        !          4428:          if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
        !          4429:            offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
        !          4430:                                - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
        !          4431: #endif
        !          4432:        }
        !          4433:       else
        !          4434:         offset_in_bytes = 0;
        !          4435:       
        !          4436:       /* The "+ 4" is a total hack to account for the return pc and
        !          4437:          saved fp on the 68k.  We should redefine this format! */
        !          4438:       sprintf (&utlbuf[strlen (utlbuf)], "%d", offset_in_bytes + 8);
        !          4439:     }
        !          4440: 
        !          4441:   return get_identifier (utlbuf);
        !          4442: }
        !          4443: 
        !          4444: void
        !          4445: finish_method_def ()
        !          4446: {
        !          4447:   METHOD_ENCODING (method_context) =
        !          4448:     encode_method_def (current_function_decl);
        !          4449: 
        !          4450:   finish_function (0);
        !          4451: 
        !          4452:   /* this must be done AFTER finish_function, since the optimizer may
        !          4453:      find "may be used before set" errors.  */
        !          4454:   method_context = NULLT;      /* required to implement _msgSuper () */
        !          4455: }
        !          4456: 
        !          4457: int
        !          4458: lang_report_error_function (decl)
        !          4459:       tree decl;
        !          4460: {
        !          4461:   if (method_context)
        !          4462:     {
        !          4463:       fprintf (stderr, "In method `%s'\n",
        !          4464:               IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
        !          4465:       return 1;
        !          4466:     }
        !          4467:   else
        !          4468:     return 0;
        !          4469: }
        !          4470: 
        !          4471: static int
        !          4472: is_complex_decl (type)
        !          4473:      tree type;
        !          4474: {
        !          4475:   return (TREE_CODE (type) == ARRAY_TYPE
        !          4476:          || TREE_CODE (type) == FUNCTION_TYPE
        !          4477:          || TREE_CODE (type) == POINTER_TYPE);
        !          4478: }
        !          4479: 
        !          4480: 
        !          4481: /* Code to convert a decl node into text for a declaration in C.  */
        !          4482: 
        !          4483: static char tmpbuf[256];
        !          4484: 
        !          4485: static void
        !          4486: adorn_decl (decl, str)
        !          4487:      tree decl;
        !          4488:      char *str;
        !          4489: {
        !          4490:   enum tree_code code = TREE_CODE (decl);
        !          4491: 
        !          4492:   if (code == ARRAY_REF)
        !          4493:     {
        !          4494:       tree anIntCst = TREE_OPERAND (decl, 1);
        !          4495: 
        !          4496:       sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (anIntCst));
        !          4497:     }
        !          4498:   else if (code == ARRAY_TYPE)
        !          4499:     {
        !          4500:       tree anIntCst = TYPE_SIZE (decl);
        !          4501:       tree array_of = TREE_TYPE (decl);
        !          4502: 
        !          4503:       sprintf (str + strlen (str), "[%d]",
        !          4504:               TREE_INT_CST_LOW (anIntCst)/TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
        !          4505:     }
        !          4506:   else if (code == CALL_EXPR)
        !          4507:     strcat (str, "()");
        !          4508:   else if (code == FUNCTION_TYPE)
        !          4509:     {
        !          4510:       tree chain  = TYPE_ARG_TYPES (decl); /* a list of types */
        !          4511:       strcat (str, "(");
        !          4512:       while (chain && TREE_VALUE (chain) != void_type_node)
        !          4513:        {
        !          4514:          gen_declaration (TREE_VALUE (chain), str);
        !          4515:          chain = TREE_CHAIN (chain);
        !          4516:          if (chain && TREE_VALUE (chain) != void_type_node)
        !          4517:            strcat (str, ",");
        !          4518:        }
        !          4519:       strcat (str, ")");
        !          4520:     }
        !          4521:   else
        !          4522:     {
        !          4523:       strcpy (tmpbuf, "*"); strcat (tmpbuf, str);
        !          4524:       strcpy (str, tmpbuf);
        !          4525:     }
        !          4526: }
        !          4527: 
        !          4528: static char *
        !          4529: gen_declarator (decl, buf, name)
        !          4530:      tree decl;
        !          4531:      char *buf;
        !          4532:      char *name;
        !          4533: {
        !          4534:   if (decl)
        !          4535:     {
        !          4536:       enum tree_code code = TREE_CODE (decl);
        !          4537:       char *str;
        !          4538:       tree op;
        !          4539:       int wrap = 0;
        !          4540: 
        !          4541:       switch (code)
        !          4542:        {
        !          4543:        case ARRAY_REF: case INDIRECT_REF: case CALL_EXPR:
        !          4544:          {
        !          4545:            op = TREE_OPERAND (decl, 0);
        !          4546: 
        !          4547:            /* we have a pointer to a function or array...(*)(), (*)[] */
        !          4548:            if ((code == ARRAY_REF || code == CALL_EXPR) &&
        !          4549:                (op && TREE_CODE (op) == INDIRECT_REF))
        !          4550:              wrap = 1;
        !          4551: 
        !          4552:            str = gen_declarator (op, buf, name);
        !          4553: 
        !          4554:            if (wrap)
        !          4555:              {
        !          4556:                strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
        !          4557:                strcpy (str, tmpbuf);
        !          4558:              }
        !          4559: 
        !          4560:            adorn_decl (decl, str);
        !          4561:            break;
        !          4562:          }
        !          4563:        case ARRAY_TYPE: case FUNCTION_TYPE: case POINTER_TYPE:
        !          4564:          {
        !          4565:            str = strcpy (buf, name);
        !          4566: 
        !          4567:            /* this clause is done iteratively...rather than recursively */
        !          4568:            do
        !          4569:              {
        !          4570:                op = is_complex_decl (TREE_TYPE (decl))
        !          4571:                  ? TREE_TYPE (decl)
        !          4572:                    : NULLT;
        !          4573: 
        !          4574:                adorn_decl (decl, str);
        !          4575: 
        !          4576:                /* we have a pointer to a function or array...(*)(), (*)[] */
        !          4577:                if ((code == POINTER_TYPE) &&
        !          4578:                    (op && (TREE_CODE (op) == FUNCTION_TYPE
        !          4579:                            || TREE_CODE (op) == ARRAY_TYPE)))
        !          4580:                  {
        !          4581:                    strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
        !          4582:                    strcpy (str, tmpbuf);
        !          4583:                  }
        !          4584: 
        !          4585:                decl = is_complex_decl (TREE_TYPE (decl))
        !          4586:                  ? TREE_TYPE (decl)
        !          4587:                    : NULLT;
        !          4588:              }
        !          4589:            while (decl && (code = TREE_CODE (decl)));
        !          4590: 
        !          4591:            break;
        !          4592:          }
        !          4593:        case IDENTIFIER_NODE:
        !          4594:          /* will only happen if we are processing a "raw" expr-decl. */
        !          4595:          return strcpy (buf, IDENTIFIER_POINTER (decl));
        !          4596:        }
        !          4597: 
        !          4598:       return str;
        !          4599:     }
        !          4600:   else                         /* we have an abstract declarator or a _DECL node */
        !          4601:     {
        !          4602:       return strcpy (buf, name);
        !          4603:     }
        !          4604: }
        !          4605: 
        !          4606: static void
        !          4607: gen_declspecs (declspecs, buf, raw)
        !          4608:      tree declspecs;
        !          4609:      char *buf;
        !          4610:      int raw;
        !          4611: {
        !          4612:   if (raw)
        !          4613:     {
        !          4614:       tree chain;
        !          4615: 
        !          4616:       for (chain = declspecs; chain; chain = TREE_CHAIN (chain))
        !          4617:        {
        !          4618:          tree aspec = TREE_VALUE (chain);
        !          4619: 
        !          4620:          if (TREE_CODE (aspec) == IDENTIFIER_NODE)
        !          4621:            strcat (buf, IDENTIFIER_POINTER (aspec));
        !          4622:          else if (TREE_CODE (aspec) == RECORD_TYPE)
        !          4623:            {
        !          4624:              if (TYPE_NAME (aspec))
        !          4625:                {
        !          4626:                  if (!TREE_STATIC_TEMPLATE (aspec))
        !          4627:                    strcat (buf, "struct ");
        !          4628:                  strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
        !          4629:                }
        !          4630:              else
        !          4631:                strcat (buf, "untagged struct");
        !          4632:            }
        !          4633:          else if (TREE_CODE (aspec) == UNION_TYPE)
        !          4634:            {
        !          4635:              if (TYPE_NAME (aspec))
        !          4636:                {
        !          4637:                  if (!TREE_STATIC_TEMPLATE (aspec))
        !          4638:                    strcat (buf, "union ");
        !          4639:                  strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
        !          4640:                }
        !          4641:              else
        !          4642:                strcat (buf, "untagged union");
        !          4643:            }
        !          4644:          else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
        !          4645:            {
        !          4646:              if (TYPE_NAME (aspec))
        !          4647:                {
        !          4648:                  if (!TREE_STATIC_TEMPLATE (aspec))
        !          4649:                    strcat (buf, "enum ");
        !          4650:                  strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
        !          4651:                }
        !          4652:              else
        !          4653:                strcat (buf, "untagged enum");
        !          4654:            }
        !          4655:          strcat (buf, " ");
        !          4656:        }
        !          4657:     }
        !          4658:   else
        !          4659:     switch (TREE_CODE (declspecs))
        !          4660:       {
        !          4661:        /* type specifiers */
        !          4662: 
        !          4663:       case INTEGER_TYPE:       /* signed integer types */
        !          4664: 
        !          4665:         if (declspecs == short_integer_type_node) /* 's' */
        !          4666:           strcat (buf, "short int ");
        !          4667:         else if (declspecs == integer_type_node) /* 'i' */
        !          4668:           strcat (buf, "int ");
        !          4669:         else if (declspecs == long_integer_type_node) /* 'l' */
        !          4670:           strcat (buf, "long int ");
        !          4671:         else if (declspecs == signed_char_type_node || /* 'c' */
        !          4672:                 declspecs == char_type_node)
        !          4673:           strcat (buf, "char ");
        !          4674: 
        !          4675:         /* unsigned integer types */
        !          4676: 
        !          4677:         else if (declspecs == short_unsigned_type_node)        /* 'S' */
        !          4678:           strcat (buf, "unsigned short ");
        !          4679:         else if (declspecs == unsigned_type_node) /* 'I' */
        !          4680:           strcat (buf, "unsigned int ");
        !          4681:         else if (declspecs == long_unsigned_type_node) /* 'L' */
        !          4682:           strcat (buf, "unsigned long ");
        !          4683:         else if (declspecs == unsigned_char_type_node) /* 'C' */
        !          4684:           strcat (buf, "unsigned char ");
        !          4685:        break;
        !          4686: 
        !          4687:       case REAL_TYPE:          /* floating point types */
        !          4688: 
        !          4689:         if (declspecs == float_type_node) /* 'f' */
        !          4690:           strcat (buf, "float ");
        !          4691:         else if (declspecs == double_type_node)        /* 'd' */
        !          4692:           strcat (buf, "double ");
        !          4693:        else if (declspecs == long_double_type_node) /* 'd' */
        !          4694:           strcat (buf, "long double ");
        !          4695:        break;
        !          4696: 
        !          4697:       case RECORD_TYPE:
        !          4698:        if (!TREE_STATIC_TEMPLATE (declspecs))
        !          4699:          strcat (buf, "struct ");
        !          4700:        if (TYPE_NAME (declspecs) &&
        !          4701:            (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
        !          4702:          {
        !          4703:            strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
        !          4704:            strcat (buf, " ");
        !          4705:          }
        !          4706:        break;
        !          4707:       case UNION_TYPE:
        !          4708:        strcat (buf, "union ");
        !          4709:        if (TYPE_NAME (declspecs) &&
        !          4710:            (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
        !          4711:          {
        !          4712:            strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
        !          4713:            strcat (buf, " ");
        !          4714:          }
        !          4715:        break;
        !          4716:       case ENUMERAL_TYPE:
        !          4717:        strcat (buf, "enum ");
        !          4718:        if (TYPE_NAME (declspecs) &&
        !          4719:            (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
        !          4720:          {
        !          4721:            strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
        !          4722:            strcat (buf, " ");
        !          4723:          }
        !          4724:        break;
        !          4725:       case VOID_TYPE:
        !          4726:        strcat (buf, "void ");
        !          4727:       }
        !          4728: }
        !          4729: 
        !          4730: static char *
        !          4731: gen_declaration (atype_or_adecl, buf)
        !          4732:      tree atype_or_adecl;
        !          4733:      char *buf;
        !          4734: {
        !          4735:   char declbuf[256];
        !          4736: 
        !          4737:   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
        !          4738:     {
        !          4739:       tree declspecs;          /* "identifier_node", "record_type" */
        !          4740:       tree declarator;         /* "array_ref", "indirect_ref", "call_expr"... */
        !          4741: 
        !          4742:       /* we have a "raw", abstract delclarator (typename) */
        !          4743:       declarator = TREE_VALUE (atype_or_adecl);
        !          4744:       declspecs  = TREE_PURPOSE (atype_or_adecl);
        !          4745: 
        !          4746:       gen_declspecs (declspecs, buf, 1);
        !          4747:       strcat (buf, gen_declarator (declarator, declbuf, ""));
        !          4748:     }
        !          4749:   else
        !          4750:     {
        !          4751:       tree atype;
        !          4752:       tree declspecs;          /* "integer_type", "real_type", "record_type"... */
        !          4753:       tree declarator;         /* "array_type", "function_type", "pointer_type". */
        !          4754: 
        !          4755:       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
        !          4756:          || TREE_CODE (atype_or_adecl) == PARM_DECL
        !          4757:          || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
        !          4758:        atype = TREE_TYPE (atype_or_adecl);
        !          4759:       else
        !          4760:        atype = atype_or_adecl; /* assume we have a *_type node */
        !          4761: 
        !          4762:       if (is_complex_decl (atype))
        !          4763:        {
        !          4764:          tree chain;
        !          4765: 
        !          4766:          /* get the declaration specifier...it is at the end of the list */
        !          4767:          declarator = chain = atype;
        !          4768:          do
        !          4769:            chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
        !          4770:          while (is_complex_decl (chain));
        !          4771:          declspecs = chain;
        !          4772:        }
        !          4773:       else
        !          4774:        {
        !          4775:          declspecs = atype;
        !          4776:          declarator = NULLT;
        !          4777:        }
        !          4778: 
        !          4779:       gen_declspecs (declspecs, buf, 0);
        !          4780: 
        !          4781:       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
        !          4782:          || TREE_CODE (atype_or_adecl) == PARM_DECL
        !          4783:          || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
        !          4784:        {
        !          4785:          if (declarator)
        !          4786:            {
        !          4787:              strcat (buf, gen_declarator (declarator, declbuf,
        !          4788:                                           IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))));
        !          4789:            }
        !          4790:          else
        !          4791:            strcat (buf, IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)));
        !          4792:        }
        !          4793:       else
        !          4794:        {
        !          4795:          strcat (buf, gen_declarator (declarator, declbuf, ""));
        !          4796:        }
        !          4797:     }
        !          4798:   return buf;
        !          4799: }
        !          4800: 
        !          4801: #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
        !          4802: 
        !          4803: static char *
        !          4804: gen_method_decl (method, buf)
        !          4805:      tree method;
        !          4806:      char *buf;
        !          4807: {
        !          4808:   tree chain;
        !          4809: 
        !          4810:   if (RAW_TYPESPEC (method) != objc_object_reference)
        !          4811:     {
        !          4812:       strcpy (buf, "(");
        !          4813:       gen_declaration (TREE_TYPE (method), buf);
        !          4814:       strcat (buf, ")");
        !          4815:     }
        !          4816: 
        !          4817:   chain = METHOD_SEL_ARGS (method);
        !          4818:   if (chain)
        !          4819:     {                          /* we have a chain of keyword_decls */
        !          4820:       do
        !          4821:         {
        !          4822:          if (KEYWORD_KEY_NAME (chain))
        !          4823:            strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
        !          4824: 
        !          4825:          strcat (buf, ":");
        !          4826:          if (RAW_TYPESPEC (chain) != objc_object_reference)
        !          4827:            {
        !          4828:              strcat (buf, "(");
        !          4829:              gen_declaration (TREE_TYPE (chain), buf);
        !          4830:              strcat (buf, ")");
        !          4831:            }
        !          4832:          strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
        !          4833:          if (chain = TREE_CHAIN (chain))
        !          4834:            strcat (buf, " ");
        !          4835:         }
        !          4836:       while (chain);
        !          4837: 
        !          4838:       if (METHOD_ADD_ARGS (method) == (tree)1)
        !          4839:         strcat (buf, ", ...");
        !          4840:       else if (METHOD_ADD_ARGS (method))
        !          4841:         {                      /* we have a tree list node as generate by `get_parm_info ()' */
        !          4842:          chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
        !          4843:           /* know we have a chain of parm_decls */
        !          4844:           while (chain)
        !          4845:             {
        !          4846:              strcat (buf, ", ");
        !          4847:              gen_declaration (chain, buf);
        !          4848:              chain = TREE_CHAIN (chain);
        !          4849:             }
        !          4850:        }
        !          4851:     }
        !          4852:   else                         /* we have a unary selector */
        !          4853:     {
        !          4854:       strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
        !          4855:     }
        !          4856: 
        !          4857:   return buf;
        !          4858: }
        !          4859: 
        !          4860: void
        !          4861: gen_prototype (fp, decl)
        !          4862:      FILE *fp;
        !          4863:      tree decl;
        !          4864: {
        !          4865:   /* we have a function definition - generate prototype */
        !          4866:   bzero (errbuf, BUFSIZE);
        !          4867:   gen_declaration (decl, errbuf);
        !          4868:   fprintf (fp, "%s;\n", errbuf);
        !          4869: }
        !          4870: /*
        !          4871:  *  debug info...
        !          4872:  */
        !          4873: static void
        !          4874: dump_interface (fp, chain)
        !          4875:      FILE *fp;
        !          4876:      tree chain;
        !          4877: {
        !          4878:   char *buf = (char *)xmalloc (256);
        !          4879:   char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
        !          4880:   tree ivar_decls = CLASS_RAW_IVARS (chain);
        !          4881:   tree nst_methods = CLASS_NST_METHODS (chain);
        !          4882:   tree cls_methods = CLASS_CLS_METHODS (chain);
        !          4883: 
        !          4884:   fprintf (fp, "\n@interface %s", my_name);
        !          4885: 
        !          4886:   if (CLASS_SUPER_NAME (chain))
        !          4887:     {
        !          4888:       char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
        !          4889:       fprintf (fp, " : %s\n", super_name);
        !          4890:     }
        !          4891:   else
        !          4892:     fprintf (fp, "\n");
        !          4893: 
        !          4894:   if (ivar_decls)
        !          4895:     {
        !          4896:       fprintf (fp, "{\n");
        !          4897:       do
        !          4898:        {
        !          4899:          bzero (buf, 256);
        !          4900:          fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
        !          4901:          ivar_decls = TREE_CHAIN (ivar_decls);
        !          4902:        }
        !          4903:       while (ivar_decls);
        !          4904:       fprintf (fp, "}\n");
        !          4905:     }
        !          4906: 
        !          4907:   while (nst_methods)
        !          4908:     {
        !          4909:       bzero (buf, 256);
        !          4910:       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
        !          4911:       nst_methods = TREE_CHAIN (nst_methods);
        !          4912:     }
        !          4913: 
        !          4914:   while (cls_methods)
        !          4915:     {
        !          4916:       bzero (buf, 256);
        !          4917:       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
        !          4918:       cls_methods = TREE_CHAIN (cls_methods);
        !          4919:     }
        !          4920:   fprintf (fp, "\n@end");
        !          4921: }
        !          4922: 
        !          4923: void
        !          4924: init_objc ()
        !          4925: {
        !          4926:   /* Add the special tree codes of Objective C to the tables.  */
        !          4927: 
        !          4928:   tree_code_type
        !          4929:     = (char **) realloc (tree_code_type,
        !          4930:                         sizeof (char *) * LAST_OBJC_TREE_CODE);
        !          4931:   tree_code_length
        !          4932:     = (int *) realloc (tree_code_length,
        !          4933:                       sizeof (int) * LAST_OBJC_TREE_CODE);
        !          4934:   tree_code_name
        !          4935:     = (char **) realloc (tree_code_name,
        !          4936:                         sizeof (char *) * LAST_OBJC_TREE_CODE);
        !          4937:   bcopy (objc_tree_code_type,
        !          4938:         tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
        !          4939:         (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
        !          4940:          * sizeof (char *)));
        !          4941:   bcopy (objc_tree_code_length,
        !          4942:         tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
        !          4943:         (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
        !          4944:          * sizeof (int)));
        !          4945:   bcopy (objc_tree_code_name,
        !          4946:         tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
        !          4947:         (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
        !          4948:          * sizeof (char *)));
        !          4949: 
        !          4950:   errbuf = (char *)xmalloc (BUFSIZE);
        !          4951:   utlbuf = (char *)xmalloc (BUFSIZE);
        !          4952:   hash_init ();
        !          4953:   synth_module_prologue ();
        !          4954: }
        !          4955: 
        !          4956: void
        !          4957: finish_objc ()
        !          4958: {
        !          4959:   struct imp_entry *impent;
        !          4960:   tree chain;
        !          4961: 
        !          4962:   generate_forward_declaration_to_string_table ();
        !          4963: 
        !          4964: #ifdef OBJC_PROLOGUE
        !          4965:   OBJC_PROLOGUE;
        !          4966: #endif
        !          4967: 
        !          4968:   if (implementation_context || sel_refdef_chain)
        !          4969:     generate_objc_symtab_decl ();
        !          4970: 
        !          4971:   for (impent = imp_list; impent; impent = impent->next)
        !          4972:     {
        !          4973:       implementation_context = impent->imp_context;
        !          4974:       implementation_template = impent->imp_template;
        !          4975: 
        !          4976:       _OBJC_CLASS_decl = impent->class_decl;
        !          4977:       _OBJC_METACLASS_decl = impent->meta_decl;
        !          4978: 
        !          4979:       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
        !          4980:        {
        !          4981:          /* all of the following reference the string pool...  */
        !          4982:          generate_ivar_lists ();
        !          4983:          generate_dispatch_tables ();
        !          4984:          generate_shared_structures ();
        !          4985:        }
        !          4986:       else
        !          4987:        {
        !          4988:          generate_dispatch_tables ();
        !          4989:          generate_category (implementation_context);
        !          4990:        }
        !          4991:     }
        !          4992: 
        !          4993:   if (sel_ref_chain)
        !          4994:     build_selector_translation_table ();
        !          4995: 
        !          4996:   if (implementation_context || sel_refdef_chain)
        !          4997:     {
        !          4998:       /* Arrange for Objc data structures to be initialized at run time.  */
        !          4999: 
        !          5000:       char *init_name = build_module_descriptor ();
        !          5001:       if (init_name)
        !          5002:        assemble_constructor (init_name);
        !          5003:     }
        !          5004: 
        !          5005:   /* dump the string table last */
        !          5006: 
        !          5007:   if (sel_refdef_chain)
        !          5008:     {
        !          5009:       build_message_selector_pool ();
        !          5010:     }
        !          5011: 
        !          5012:   /* dump the class references...this forces the appropriate classes
        !          5013:      to be linked into the executable image, preserving unix archive
        !          5014:      semantics...this can be removed when we move to a more dynamically
        !          5015:      linked environment
        !          5016:      */
        !          5017:   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
        !          5018:     {
        !          5019:       tree decl;
        !          5020: 
        !          5021: #if 0 /* Grossly unportable.  */
        !          5022:       sprintf (utlbuf, ".reference .objc_class_name_%s",
        !          5023:               IDENTIFIER_POINTER (TREE_VALUE (chain)));
        !          5024:       assemble_asm (my_build_string (strlen (utlbuf) + 1, utlbuf));
        !          5025: #else
        !          5026:       sprintf (utlbuf, ".objc_class_name_%s",
        !          5027:               IDENTIFIER_POINTER (TREE_VALUE (chain)));
        !          5028: #endif
        !          5029:       /* Make a decl for this name, so we can use its address in a tree.  */
        !          5030:       decl = build_decl (VAR_DECL, get_identifier (utlbuf), char_type_node);
        !          5031:       TREE_EXTERNAL (decl) = 1;
        !          5032:       TREE_PUBLIC (decl) = 1;
        !          5033:       
        !          5034:       pushdecl (decl);
        !          5035:       rest_of_decl_compilation (decl, 0, 0, 0);
        !          5036: 
        !          5037:       /* Make following constant read-only (why not)?  */
        !          5038:       text_section ();
        !          5039: 
        !          5040:       /* Output a constant to reference this address.  */
        !          5041:       output_constant (build1 (ADDR_EXPR, string_type_node, decl),
        !          5042:                       int_size_in_bytes (string_type_node));
        !          5043:     }
        !          5044: 
        !          5045:   for (impent = imp_list; impent; impent = impent->next)
        !          5046:     {
        !          5047:       implementation_context = impent->imp_context;
        !          5048:       implementation_template = impent->imp_template;
        !          5049: 
        !          5050:       if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
        !          5051:        {
        !          5052: #if 0 /* Grossly unportable.
        !          5053:                            People should know better than to assume
        !          5054:                            such things about assembler syntax!  */
        !          5055:          sprintf (utlbuf, ".objc_class_name_%s=0",
        !          5056:                   IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
        !          5057:          assemble_asm (my_build_string (strlen (utlbuf) + 1, utlbuf));
        !          5058: #endif
        !          5059:          sprintf (utlbuf, ".objc_class_name_%s",
        !          5060:                   IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
        !          5061:          assemble_global (utlbuf);
        !          5062:          assemble_label (utlbuf);
        !          5063:        }
        !          5064:       else if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
        !          5065:        {
        !          5066:          /* Do the same for categories.  Even though no references to these
        !          5067:              symbols are generated automatically by the compiler, it gives
        !          5068:              you a handle to pull them into an archive by hand. */
        !          5069: #if 0 /* Grossly unportable.  */
        !          5070:          sprintf (utlbuf, ".objc_category_name_%s_%s=0",
        !          5071:                   IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
        !          5072:                   IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
        !          5073:          assemble_asm (my_build_string (strlen (utlbuf) + 1, utlbuf));
        !          5074: #endif
        !          5075:          sprintf (utlbuf, ".objc_category_name_%s_%s",
        !          5076:                   IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
        !          5077:                   IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
        !          5078:          assemble_global (utlbuf);
        !          5079:          assemble_label (utlbuf);
        !          5080:        }
        !          5081:     }
        !          5082: #if 0 /* If GAS has such a bug, let's fix it.  */
        !          5083:   /*** this fixes a gross bug in the assembler...it `expects' #APP to have
        !          5084:    *** a matching #NO_APP, or it crashes (sometimes). app_disable () will
        !          5085:    *** insure this is the case. 5/19/89, s.naroff.
        !          5086:    ***/
        !          5087:   if (cls_ref_chain || imp_list)
        !          5088:     app_disable ();
        !          5089: #endif
        !          5090: 
        !          5091:   if (flag_gen_declaration)
        !          5092:     {
        !          5093:       add_class (implementation_context);
        !          5094:       dump_interface (gen_declaration_file, implementation_context);
        !          5095:     }
        !          5096:   if (warn_selector)
        !          5097:     {
        !          5098:       int slot;
        !          5099:       
        !          5100:       /* Run through the selector hash tables and print a warning for any
        !          5101:          selector which has multiple methods. */
        !          5102:       
        !          5103:       for (slot = 0; slot < SIZEHASHTABLE; slot++)
        !          5104:         {
        !          5105:          hash hsh;
        !          5106:          
        !          5107:          for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
        !          5108:            {
        !          5109:              if (hsh->list)
        !          5110:                {
        !          5111:                  tree meth = hsh->key;
        !          5112:                  char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
        !          5113:                              ? '-' : '+';
        !          5114:                  attr loop;
        !          5115:              
        !          5116:                  warning ("potential selector conflict for method `%s'",
        !          5117:                           IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
        !          5118:                  warn_with_method ("found", type, meth);
        !          5119:                  for (loop = hsh->list; loop; loop = loop->next)
        !          5120:                    warn_with_method ("found", type, loop->value);
        !          5121:                }
        !          5122:            }
        !          5123:        }
        !          5124:     
        !          5125:       for (slot = 0; slot < SIZEHASHTABLE; slot++)
        !          5126:         {
        !          5127:          hash hsh;
        !          5128:          
        !          5129:          for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
        !          5130:            {
        !          5131:              if (hsh->list)
        !          5132:                {
        !          5133:                  tree meth = hsh->key;
        !          5134:                  char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
        !          5135:                              ? '-' : '+';
        !          5136:                  attr loop;
        !          5137:              
        !          5138:                  warning ("potential selector conflict for method `%s'",
        !          5139:                           IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
        !          5140:                  warn_with_method ("found", type, meth);
        !          5141:                  for (loop = hsh->list; loop; loop = loop->next)
        !          5142:                    warn_with_method ("found", type, loop->value);
        !          5143:                }
        !          5144:            }
        !          5145:        }
        !          5146:     }
        !          5147: }
        !          5148: 
        !          5149: #ifdef DEBUG
        !          5150: 
        !          5151: static void
        !          5152: objc_debug (fp)
        !          5153:      FILE *fp;
        !          5154: {
        !          5155:   char *buf = (char *)xmalloc (256);
        !          5156: 
        !          5157:   {                            /* dump function prototypes */
        !          5158:     tree loop = _OBJC_MODULES_decl;
        !          5159: 
        !          5160:     fprintf (fp, "\n\nfunction prototypes:\n");
        !          5161:     while (loop)
        !          5162:       {
        !          5163:        if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
        !          5164:          {
        !          5165:            /* we have a function definition - generate prototype */
        !          5166:             bzero (errbuf, BUFSIZE);
        !          5167:            gen_declaration (loop, errbuf);
        !          5168:            fprintf (fp, "%s;\n", errbuf);
        !          5169:          }
        !          5170:        loop = TREE_CHAIN (loop);
        !          5171:       }
        !          5172:   }
        !          5173:   {                            /* dump global chains */
        !          5174:     tree loop;
        !          5175:     int i, index = 0, offset = 0;
        !          5176:     hash hashlist;
        !          5177: 
        !          5178:     for (i = 0; i < SIZEHASHTABLE; i++)
        !          5179:       {
        !          5180:        if (hashlist = nst_method_hash_list[i])
        !          5181:          {
        !          5182:            fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
        !          5183:            do
        !          5184:              {
        !          5185:                bzero (buf, 256);
        !          5186:                fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
        !          5187:                hashlist = hashlist->next;
        !          5188:              }
        !          5189:            while (hashlist);
        !          5190:          }
        !          5191:       }
        !          5192:     for (i = 0; i < SIZEHASHTABLE; i++)
        !          5193:       {
        !          5194:        if (hashlist = cls_method_hash_list[i])
        !          5195:          {
        !          5196:            fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
        !          5197:            do
        !          5198:              {
        !          5199:                bzero (buf, 256);
        !          5200:                fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
        !          5201:                hashlist = hashlist->next;
        !          5202:              }
        !          5203:            while (hashlist);
        !          5204:          }
        !          5205:       }
        !          5206:     fprintf (fp, "\nsel_refdef_chain:\n");
        !          5207:     for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
        !          5208:       {
        !          5209:        fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
        !          5210:                 IDENTIFIER_POINTER (TREE_VALUE (loop)));
        !          5211:        index++;
        !          5212:        /* add one for the '\0' character */
        !          5213:        offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
        !          5214:       }
        !          5215:     fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
        !          5216:   }
        !          5217: }
        !          5218: #endif
        !          5219: 
        !          5220: void
        !          5221: print_lang_statistics ()
        !          5222: {
        !          5223: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.