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

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

unix.superglobalmegacorp.com

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