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

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

unix.superglobalmegacorp.com

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