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

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

unix.superglobalmegacorp.com

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