OSDN Git Service

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