Annotation of gcc/objc-actions.c, revision 1.1.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.