home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / objc-actions.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  144KB  |  5,232 lines

  1. /* Implement classes and message passing for Objective C.
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.    Author: Steve Naroff.
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /*
  22.  *      Purpose: This module implements the Objective-C 4.0 language.
  23.  *
  24.  *      compatibility issues (with the Stepstone translator):
  25.  *
  26.  *    - does not recognize the following 3.3 constructs.
  27.  *      @requires, @classes, @messages, = (...)
  28.  *    - methods with variable arguments must conform to ANSI standard.
  29.  *    - tagged structure definitions that appear in BOTH the interface
  30.  *      and implementation are not allowed.
  31.  *      - public/private: all instance variables are public within the
  32.  *        context of the implementation...I consider this to be a bug in
  33.  *        the translator.
  34.  *      - statically allocated objects are not supported. the user will
  35.  *        receive an error if this service is requested.
  36.  *
  37.  *      code generation `options':
  38.  *
  39.  *      - OBJC_INT_SELECTORS, OBJC_SELECTORS_WITHOUT_LABELS, NEXT_OBJC_RUNTIME
  40.  */
  41.  
  42. #include <stdio.h>
  43. #include "config.h"
  44. #include "tree.h"
  45. #include "c-tree.h"
  46. #include "c-lex.h"
  47. #include "flags.h"
  48. #include "objc-actions.h"
  49. #include "input.h"
  50.  
  51. /* 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
  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.  
  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.  
  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.  
  225. static tree self_id, _cmd_id;
  226.  
  227. static tree self_decl, _msg_decl, _msgSuper_decl;
  228. static tree objc_getClass_decl, objc_getMetaClass_decl;
  229.  
  230. static tree super_type, selector_type, id_type, class_type;
  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;
  260. #ifdef OBJC_SELECTORS_WITHOUT_LABELS
  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.  
  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;
  500.      char *name;
  501. {
  502.   tree decl = build_decl (code, get_identifier (name), type);
  503.   if (code == VAR_DECL)
  504.     {
  505.       TREE_STATIC (decl) = 1;
  506.       make_decl_rtl (decl, 0, 1);
  507.       pushdecl (decl);
  508.     }
  509.   return decl;
  510. }
  511.  
  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. {
  527.   tree expr_decl, temp_type;
  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.  
  534.   id_type = build_pointer_type (objc_object_reference);
  535.  
  536.   objc_class_id = get_identifier (TAG_CLASS);
  537.   
  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.  */
  541.  
  542. #ifdef OBJC_INT_SELECTORS
  543.   /* `unsigned int' */
  544.   selector_type = unsigned_type_node;
  545. #else
  546.   /* `struct objc_selector *' */
  547.   selector_type
  548.     = build_pointer_type (xref_tag (RECORD_TYPE,
  549.                     get_identifier (TAG_SELECTOR)));
  550. #endif /* not OBJC_INT_SELECTORS */
  551.  
  552.   /* struct objc_object *objc_msgSend (id, SEL, ...); */
  553.  
  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)));
  567.  
  568.   _msgSuper_decl = builtin_function ("objc_msgSendSuper",
  569.                      temp_type, NOT_BUILT_IN, 0);
  570.  
  571.   /* id objc_getClass (); */
  572.   
  573.   temp_type = build_function_type (id_type, NULLT);
  574.  
  575.   objc_getClass_decl
  576.     = builtin_function ("objc_getClass", temp_type, NOT_BUILT_IN, 0);
  577.  
  578.   /* id objc_getMetaClass (); */
  579.  
  580.   objc_getMetaClass_decl
  581.     = builtin_function ("objc_getMetaClass", temp_type, NOT_BUILT_IN, 0);
  582.  
  583.   /* extern SEL _OBJC_SELECTOR_REFERENCES[]; */
  584.  
  585. #ifdef OBJC_SELECTORS_WITHOUT_LABELS
  586.   _OBJC_SELECTOR_REFERENCES_decl
  587.     = create_builtin_decl (VAR_DECL, build_array_type (selector_type, NULLT),
  588.                "_OBJC_SELECTOR_REFERENCES");
  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. }
  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.     }; */
  629.  
  630. static void
  631. build_objc_symtab_template ()
  632. {
  633.   tree field_decl, field_decl_chain, index;
  634.  
  635.   objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (_TAG_SYMTAB));
  636.  
  637.   /* long sel_ref_cnt; */
  638.  
  639.   field_decl = create_builtin_decl (FIELD_DECL,
  640.                     long_integer_type_node,
  641.                     "sel_ref_cnt");
  642.   field_decl_chain = field_decl;
  643.  
  644.   /* SEL *refs; */
  645.  
  646.   field_decl = create_builtin_decl (FIELD_DECL,
  647.                     build_pointer_type (selector_type),
  648.                     "refs");
  649.   chainon (field_decl_chain, field_decl);
  650.  
  651.   /* short cls_def_cnt; */
  652.  
  653.   field_decl = create_builtin_decl (FIELD_DECL,
  654.                     short_integer_type_node,
  655.                     "cls_def_cnt");
  656.   chainon (field_decl_chain, field_decl);
  657.  
  658.   /* short cat_def_cnt; */
  659.  
  660.   field_decl = create_builtin_decl (FIELD_DECL,
  661.                     short_integer_type_node,
  662.                     "cat_def_cnt");
  663.   chainon (field_decl_chain, field_decl);
  664.  
  665.   /* void *defs[cls_def_cnt + cat_def_cnt]; */
  666.  
  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");
  671.   chainon (field_decl_chain, field_decl);
  672.  
  673.   finish_struct (objc_symtab_template, field_decl_chain);
  674. }
  675.  
  676. /* Create the initial value for the `defs' field of _objc_symtab.
  677.    This is a CONSTRUCTOR.  */
  678.  
  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.  
  707. /* Construct the initial value for all of _objc_symtab.  */
  708.  
  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.  
  723. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  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.  
  748. /* Push forward-declarations of all the categories
  749.    so that init_def_list can use them in a CONSTRUCTOR.  */
  750.  
  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.     {
  760.       /* Set an invisible arg to synth_id_with_class_suffix.  */
  761.       implementation_context = impent->imp_context;
  762.       impent->class_decl
  763.         = create_builtin_decl (VAR_DECL, objc_category_template,
  764.                    IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY")));
  765.     }
  766.     }
  767.   implementation_context = sav;
  768. }
  769.  
  770. /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
  771.    and initialized appropriately.  */
  772.  
  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. }
  795.  
  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.  
  890.   /* Mark the decl to avoid "defined but not used" warning. */
  891.   DECL_IN_SYSTEM_HEADER (_OBJC_MODULES_decl) = 1;
  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).  -- Raeburn@MIT.EDU, 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))
  911.       if (TREE_PUBLIC (t) && !DECL_EXTERNAL (t) && DECL_INITIAL (t) != 0)
  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);
  953.     DECL_EXTERNAL (function_decl) = 1;
  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.  
  1070. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  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.     {
  1090.       decl = build_decl (VAR_DECL, ident, selector_type);
  1091.       DECL_EXTERNAL (decl) = 1;
  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);
  1110.   TREE_TYPE (expr) = selector_type; /* cast */
  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;
  1120. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  1121.   tree decl, var_decl;
  1122.   int idx = 0;
  1123.   char buf[256];
  1124. #else
  1125.   /* The corresponding pop_obstacks is in finish_decl,
  1126.      called at the end of this function.  */
  1127.   push_obstacks_nochange ();
  1128. #endif
  1129.  
  1130.   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
  1131.     {
  1132.       tree expr;
  1133.  
  1134. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  1135.       sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
  1136.       sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
  1137.  
  1138.       /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
  1139.       decl_specs = tree_cons (NULLT, selector_type, sc_spec);
  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.  
  1153. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  1154.       finish_decl (decl, expr, NULLT);
  1155.       idx++;
  1156. #else
  1157.       initlist = tree_cons (NULLT, expr, initlist);
  1158. #endif
  1159.     }
  1160.  
  1161. #ifdef OBJC_SELECTORS_WITHOUT_LABELS
  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);
  1167.   DECL_INITIAL (_OBJC_SELECTOR_REFERENCES_decl) = (tree) 1;
  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)
  1307.     DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
  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.  
  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.  
  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 */
  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);
  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 = */
  2156.   initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist);
  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. {
  2307.   char *string;
  2308.   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
  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.     }
  2316.   else
  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);
  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
  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.  
  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.  
  2470. #ifdef NEXT_OBJC_RUNTIME
  2471.   /* receiver type */
  2472.   if (superflag)
  2473.     {
  2474.       arglist = build_tree_list (NULLT, super_type);
  2475.     }
  2476.   else
  2477. #endif
  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' */
  2486.   chainon (arglist, build_tree_list (NULLT, selector_type));
  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.    */
  2550.   tree exp = TREE_OPERAND (receiver, 0);
  2551.  
  2552.   if (exp != 0 && (TREE_CODE (exp) == ADDR_EXPR))
  2553.     {
  2554.       exp = TREE_OPERAND (exp, 0);
  2555.       if (exp != 0
  2556.       && TREE_CODE (exp) == FUNCTION_DECL && exp == objc_getClass_decl)
  2557.     {
  2558.       /* we have a call to objc_getClass! */
  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)
  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.     ;
  2631.       else if (TYPE_MAIN_VARIANT (rtype) != TYPE_MAIN_VARIANT (id_type)
  2632.            && TYPE_MAIN_VARIANT (rtype) != TYPE_MAIN_VARIANT (class_type))
  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.  
  2640.       /* Don't evaluate the receiver twice. */
  2641.       receiver = save_expr (receiver);
  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.   
  2661. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  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.  
  2696.   if (super_type != 0
  2697.       && TYPE_MAIN_VARIANT (rtype) == TYPE_MAIN_VARIANT (super_type))
  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.  
  2934. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  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. {
  2947.   tree result;
  2948.   char *string;
  2949.  
  2950.   if (!doing_objc_thang)
  2951.     fatal ("Objective-C text in C source file");
  2952.  
  2953.   encode_type (type, OBJC_ENCODE_INLINE_DEFS);
  2954.   obstack_1grow (&util_obstack, 0);    /* null terminate string */
  2955.   string = obstack_finish (&util_obstack);
  2956.  
  2957.   /* synthesize a string that represents the encoded struct/union */
  2958.   result = my_build_string (strlen (string) + 1, string);
  2959.   obstack_free (&util_obstack, util_firstobj);
  2960.   return result;
  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.         {
  3331.           /* important difference between the Stepstone translator:
  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.  
  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.  
  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.  
  3441.   if (code == INTERFACE_TYPE)
  3442.     {
  3443.       push_obstacks_nochange ();
  3444.       end_temporary_allocation ();
  3445.     }
  3446.  
  3447.   if (!doing_objc_thang)
  3448.     fatal ("Objective-C text in C source file");
  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;
  3650.       char *string = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (class))) + 3);
  3651.  
  3652.       /* extern struct objc_object *_<my_name>; */
  3653.  
  3654.       sprintf (string, "_%s", IDENTIFIER_POINTER (CLASS_NAME (class)));
  3655.  
  3656.       decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
  3657.       decl_specs = tree_cons (NULLT, objc_object_reference, decl_specs);
  3658.       define_decl (build1 (INDIRECT_REF, NULLT, get_identifier (string)),
  3659.            decl_specs);
  3660.     }
  3661. }
  3662.  
  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.  
  3668. static void
  3669. encode_pointer (type, format)
  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.  
  3682.       if ((strcmp (name, TAG_OBJECT) == 0) /* '@' */
  3683.           || TREE_STATIC_TEMPLATE (pointer_to))
  3684.         {
  3685.           obstack_1grow (&util_obstack, '@');
  3686.           return;
  3687.         }
  3688.       else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
  3689.         {
  3690.           obstack_1grow (&util_obstack, '#');
  3691.           return;
  3692.         }
  3693. #ifndef OBJC_INT_SELECTORS
  3694.       else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
  3695.         {
  3696.           obstack_1grow (&util_obstack, ':');
  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.     {
  3705.       obstack_1grow (&util_obstack, '*');
  3706.       return;
  3707.     }
  3708.  
  3709.   /* we have a type that does not get special treatment... */
  3710.  
  3711.   /* NeXT extension */
  3712.   obstack_1grow (&util_obstack, '^');
  3713.   encode_type (pointer_to, format);
  3714. }
  3715.  
  3716. static void
  3717. encode_array (type, format)
  3718.      tree type;
  3719.      int format;
  3720. {
  3721.   tree anIntCst = TYPE_SIZE (type);
  3722.   tree array_of = TREE_TYPE (type);
  3723.   char buffer[40];
  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 */
  3729.       encode_pointer (type, format);
  3730.       return;
  3731.     }
  3732.   
  3733.   sprintf (buffer, "[%d",
  3734.        TREE_INT_CST_LOW (anIntCst)
  3735.        / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
  3736.   obstack_grow (&util_obstack, buffer, strlen (buffer));
  3737.   encode_type (array_of, format);
  3738.   obstack_1grow (&util_obstack, ']');
  3739.   return;
  3740. }
  3741.  
  3742. static void
  3743. encode_aggregate (type, format)
  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.       {
  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))
  3761.       {
  3762.         if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
  3763.           {
  3764.             obstack_grow (&util_obstack,
  3765.                   IDENTIFIER_POINTER (TYPE_NAME (type)),
  3766.                   strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
  3767.           }
  3768.         else /* we have an untagged structure or a typedef */
  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, '}');
  3780.       }
  3781.     else
  3782.       {
  3783.         tree fields = TYPE_FIELDS (type);
  3784.         obstack_1grow (&util_obstack, '=');
  3785.         for ( ; fields; fields = TREE_CHAIN (fields))
  3786.           encode_field_decl (fields, format);
  3787.         obstack_1grow (&util_obstack, '}');
  3788.       }
  3789.     break;
  3790.       }
  3791.  
  3792.     case UNION_TYPE:
  3793.       {
  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))
  3802.       {
  3803.         if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
  3804.           {
  3805.             obstack_grow (&util_obstack,
  3806.                   IDENTIFIER_POINTER (TYPE_NAME (type)),
  3807.                   strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
  3808.           }
  3809.         else /* we have an untagged structure or a typedef */
  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, ')');
  3821.       }
  3822.     else
  3823.       {
  3824.         tree fields = TYPE_FIELDS (type);
  3825.         for ( ; fields; fields = TREE_CHAIN (fields))
  3826.           encode_field_decl (fields, format);
  3827.         obstack_1grow (&util_obstack, ')');
  3828.       }
  3829.     break;
  3830.       }
  3831.  
  3832.  
  3833.     case ENUMERAL_TYPE:
  3834.       obstack_1grow (&util_obstack, 'i');
  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
  3851. encode_bitfield (width, format)
  3852.      int width;
  3853.      int format;
  3854. {
  3855.   char buffer[40];
  3856.   sprintf (buffer, "b%d", width);
  3857.   obstack_grow (&util_obstack, buffer, strlen (buffer));
  3858. }
  3859.  
  3860. /*
  3861.  *    format will be:
  3862.  *
  3863.  *    OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS
  3864.  */
  3865. static void
  3866. encode_type (type, format)
  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' */
  3879.         obstack_1grow (&util_obstack, 'C');
  3880.       else if (TYPE_MODE (type) == HImode) /* 'S' */
  3881.         obstack_1grow (&util_obstack, 'S');
  3882.       else if (TYPE_MODE (type) == SImode)
  3883.         {
  3884.           if (type == long_unsigned_type_node)
  3885.         obstack_1grow (&util_obstack, 'L'); /* 'L' */
  3886.           else
  3887.         obstack_1grow (&util_obstack, 'I'); /* 'I' */
  3888.         }
  3889.     }
  3890.       else            /* signed integer types */
  3891.     {
  3892.       if (TYPE_MODE (type) == QImode) /* 'c' */
  3893.         obstack_1grow (&util_obstack, 'c');
  3894.       else if (TYPE_MODE (type) == HImode) /* 's' */
  3895.         obstack_1grow (&util_obstack, 's');
  3896.       else if (TYPE_MODE (type) == SImode) /* 'i' */
  3897.         {
  3898.           if (type == long_integer_type_node)
  3899.         obstack_1grow (&util_obstack, 'l'); /* 'l' */
  3900.           else
  3901.         obstack_1grow (&util_obstack, 'i'); /* 'i' */
  3902.         }
  3903.     }
  3904.     }
  3905.   else if (code == REAL_TYPE)
  3906.     {
  3907.       /* floating point types */
  3908.  
  3909.       if (TYPE_MODE (type) == SFmode) /* 'f' */
  3910.     obstack_1grow (&util_obstack, 'f');
  3911.       else if (TYPE_MODE (type) == DFmode
  3912.            || TYPE_MODE (type) == TFmode) /* 'd' */
  3913.     obstack_1grow (&util_obstack, 'd');
  3914.     }
  3915.  
  3916.   else if (code == VOID_TYPE)    /* 'v' */
  3917.     obstack_1grow (&util_obstack, 'v');
  3918.  
  3919.   else if (code == ARRAY_TYPE)
  3920.     encode_array (type, format);
  3921.  
  3922.   else if (code == POINTER_TYPE)
  3923.     encode_pointer (type, format);
  3924.  
  3925.   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
  3926.     encode_aggregate (type, format);
  3927.  
  3928.   else if (code == FUNCTION_TYPE) /* '?' */
  3929.     obstack_1grow (&util_obstack, '?');
  3930. }
  3931.  
  3932. static void
  3933. encode_field_decl (field_decl, format)
  3934.      tree field_decl;
  3935.      int format;
  3936. {
  3937.   if (DECL_BIT_FIELD (field_decl))
  3938.     encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
  3939.   else
  3940.     encode_type (TREE_TYPE (field_decl), format);
  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.  
  4011.   /* generate argument declarations if a keyword_decl */
  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;
  4150.   char *buf;
  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)
  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))));
  4163. #ifdef OBJC_GEN_METHOD_LABEL
  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)));
  4169. #else
  4170.       sprintf (buf, "_%d_%s", ++method_slot,
  4171.            IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
  4172. #endif
  4173.     }
  4174.   else                /* we have a category */
  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))));
  4181. #ifdef OBJC_GEN_METHOD_LABEL
  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)));
  4187. #else
  4188.       sprintf (buf, "_%d_%s_%s", ++method_slot,
  4189.            IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
  4190.            IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
  4191. #endif
  4192.     }
  4193.  
  4194.   method_id = get_identifier (buf);
  4195.  
  4196.   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULLT);
  4197.  
  4198.   /* check the declarator portion of the return type for the method */
  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' */
  4296.   DECL_IN_SYSTEM_HEADER (_OBJC_SUPER_decl) = 1;
  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;
  4378.   char buffer[40];
  4379.   tree result;
  4380.  
  4381.   /* return type */
  4382.   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
  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.  
  4390.   sprintf (buffer, "%d", stack_size);
  4391.   obstack_grow (&util_obstack, buffer, strlen (buffer));
  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 */ 
  4400.       encode_type (TREE_TYPE (parms), OBJC_ENCODE_DONT_INLINE_DEFS);
  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! */
  4434.       sprintf (buffer, "%d", offset_in_bytes + 8);
  4435.       obstack_grow (&util_obstack, buffer, strlen (buffer));
  4436.     }
  4437.  
  4438.   result = get_identifier (obstack_finish (&util_obstack));
  4439.   obstack_free (&util_obstack, util_firstobj);
  4440.   return result;
  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.  
  4741.       /* we have a "raw", abstract declarator (typename) */
  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.  
  4927.   gcc_obstack_init (&util_obstack);
  4928.   util_firstobj = (char *) obstack_finish (&util_obstack);
  4929.  
  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. }
  4956.  
  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.  
  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
  4997.   if (sel_ref_chain)
  4998. #endif
  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))
  5023.     handle_class_ref (chain);
  5024.  
  5025.   for (impent = imp_list; impent; impent = impent->next)
  5026.     handle_impent (impent);
  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. }
  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.  
  5104.   sprintf (string, "__objc_class_name_%s",
  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);
  5109.   DECL_EXTERNAL (decl) = 1;
  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. }
  5122.  
  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.  
  5134.       sprintf (string, "__objc_class_name_%s",
  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. */
  5149.       sprintf (string, "__objc_category_name_%s_%s",
  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.  
  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. }
  5232.