OSDN Git Service

(build_selector_translation_table): NULL-terminate the
[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       DECL_EXTERNAL (decl) = 1;
500       TREE_PUBLIC (decl) = 1;
501       make_decl_rtl (decl, 0, 1);
502       pushdecl (decl);
503     }
504   return decl;
505 }
506
507 /*
508  *      purpose: "play" parser, creating/installing representations
509  *               of the declarations that are required by Objective-C.
510  *
511  *      model:
512  *
513  *              type_spec--------->sc_spec
514  *              (tree_list)        (tree_list)
515  *                  |                  |
516  *                  |                  |
517  *              identifier_node    identifier_node
518  */
519 static void
520 synth_module_prologue ()
521 {
522   tree expr_decl, temp_type;
523
524   /* defined in `objc.h' */
525   objc_object_id = get_identifier (TAG_OBJECT);
526
527   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
528
529   id_type = build_pointer_type (objc_object_reference);
530
531   objc_class_id = get_identifier (TAG_CLASS);
532   
533   class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
534
535   /* Declare type of selector-objects that represent an operation name.  */
536
537 #ifdef OBJC_INT_SELECTORS
538   /* `unsigned int' */
539   selector_type = unsigned_type_node;
540 #else
541   /* `struct objc_selector *' */
542   selector_type
543     = build_pointer_type (xref_tag (RECORD_TYPE,
544                                     get_identifier (TAG_SELECTOR)));
545 #endif /* not OBJC_INT_SELECTORS */
546
547   /* struct objc_object *objc_msgSend (id, SEL, ...); */
548
549   temp_type
550     = build_function_type (id_type,
551                            tree_cons (NULL_TREE, id_type,
552                                       tree_cons (NULLT, selector_type, NULLT)));
553
554   _msg_decl = builtin_function ("objc_msgSend", temp_type, NOT_BUILT_IN, 0);
555
556   /* struct objc_object *objc_msgSendSuper (void *, SEL, ...); */
557
558   temp_type
559     = build_function_type (id_type,
560                            tree_cons (NULL_TREE, ptr_type_node,
561                                       tree_cons (NULLT, selector_type, NULLT)));
562
563   _msgSuper_decl = builtin_function ("objc_msgSendSuper",
564                                      temp_type, NOT_BUILT_IN, 0);
565
566   /* id objc_getClass (); */
567   
568   temp_type = build_function_type (id_type, NULLT);
569
570   objc_getClass_decl
571     = builtin_function ("objc_getClass", temp_type, NOT_BUILT_IN, 0);
572
573   /* id objc_getMetaClass (); */
574
575   objc_getMetaClass_decl
576     = builtin_function ("objc_getMetaClass", temp_type, NOT_BUILT_IN, 0);
577
578   /* extern SEL _OBJC_SELECTOR_REFERENCES[]; */
579
580 #ifdef OBJC_SELECTORS_WITHOUT_LABELS
581   _OBJC_SELECTOR_REFERENCES_decl
582     = create_builtin_decl (VAR_DECL, build_array_type (selector_type, NULLT),
583                            "_OBJC_SELECTOR_REFERENCES");
584 #endif
585 }
586
587 /*
588  * custom "build_string ()" which sets TREE_TYPE!
589  */
590 static tree
591 my_build_string (len, str)
592      int len;
593      char *str;
594 {
595   int wide_flag = 0;
596   tree aString = build_string (len, str);
597   /*
598    *  some code from "combine_strings ()", which is local to c-parse.y.
599    */
600   if (TREE_TYPE (aString) == int_array_type_node)
601     wide_flag = 1;
602
603   TREE_TYPE (aString) =
604     build_array_type (wide_flag ? integer_type_node : char_type_node,
605                       build_index_type (build_int_2 (len - 1, 0)));
606
607   TREE_CONSTANT (aString) = 1;  /* puts string in the ".text" segment */
608   TREE_STATIC (aString) = 1;
609
610   return aString;
611 }
612 \f
613 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
614
615 /* Predefine the following data type:
616
617         struct _objc_symtab {
618                 long sel_ref_cnt;
619                 SEL *refs;
620                 short cls_def_cnt;
621                 short cat_def_cnt;
622                 void *defs[cls_def_cnt + cat_def_cnt];
623         }; */
624
625 static void
626 build_objc_symtab_template ()
627 {
628   tree field_decl, field_decl_chain, index;
629
630   objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (_TAG_SYMTAB));
631
632   /* long sel_ref_cnt; */
633
634   field_decl = create_builtin_decl (FIELD_DECL,
635                                     long_integer_type_node,
636                                     "sel_ref_cnt");
637   field_decl_chain = field_decl;
638
639   /* SEL *refs; */
640
641   field_decl = create_builtin_decl (FIELD_DECL,
642                                     build_pointer_type (selector_type),
643                                     "refs");
644   chainon (field_decl_chain, field_decl);
645
646   /* short cls_def_cnt; */
647
648   field_decl = create_builtin_decl (FIELD_DECL,
649                                     short_integer_type_node,
650                                     "cls_def_cnt");
651   chainon (field_decl_chain, field_decl);
652
653   /* short cat_def_cnt; */
654
655   field_decl = create_builtin_decl (FIELD_DECL,
656                                     short_integer_type_node,
657                                     "cat_def_cnt");
658   chainon (field_decl_chain, field_decl);
659
660   /* void *defs[cls_def_cnt + cat_def_cnt]; */
661
662   index = build_index_type (build_int_2 (imp_count + cat_count - 1, 0));
663   field_decl = create_builtin_decl (FIELD_DECL,
664                                     build_array_type (ptr_type_node, index),
665                                     "defs");
666   chainon (field_decl_chain, field_decl);
667
668   finish_struct (objc_symtab_template, field_decl_chain);
669 }
670
671 /* Create the initial value for the `defs' field of _objc_symtab.
672    This is a CONSTRUCTOR.  */
673
674 static tree
675 init_def_list ()
676 {
677   tree expr, initlist = NULLT;
678   struct imp_entry *impent;
679
680   if (imp_count)
681     for (impent = imp_list; impent; impent = impent->next)
682       {
683         if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
684           {
685             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
686             initlist = tree_cons (NULLT, expr, initlist);
687           }
688       }
689
690   if (cat_count)
691     for (impent = imp_list; impent; impent = impent->next)
692       {
693         if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
694           {
695             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
696             initlist = tree_cons (NULLT, expr, initlist);
697           }
698       }
699   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
700 }
701
702 /* Construct the initial value for all of _objc_symtab.  */
703
704 static tree
705 init_objc_symtab ()
706 {
707   tree initlist;
708
709   /* sel_ref_cnt = { ..., 5, ... } */
710
711   if (sel_ref_chain)
712     initlist = build_tree_list (NULLT, build_int_2 (max_selector_index, 0));
713   else
714     initlist = build_tree_list (NULLT, build_int_2 (0, 0));
715
716   /* refs = { ..., _OBJC_SELECTOR_REFERENCES, ... } */
717
718 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
719   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
720 #else
721   if (sel_ref_chain)
722     initlist = tree_cons (NULLT, _OBJC_SELECTOR_REFERENCES_decl, initlist);
723   else
724     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
725 #endif
726
727   /* cls_def_cnt = { ..., 5, ... } */
728
729   initlist = tree_cons (NULLT, build_int_2 (imp_count, 0), initlist);
730
731   /* cat_def_cnt = { ..., 5, ... } */
732
733   initlist = tree_cons (NULLT, build_int_2 (cat_count, 0), initlist);
734
735   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
736
737   if (imp_count || cat_count)
738     initlist = tree_cons (NULLT, init_def_list (), initlist);
739
740   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
741 }
742
743 /* Push forward-declarations of all the categories
744    so that init_def_list can use them in a CONSTRUCTOR.  */
745
746 static void
747 forward_declare_categories ()
748 {
749   struct imp_entry *impent;
750   tree sav = implementation_context;
751   for (impent = imp_list; impent; impent = impent->next)
752     {
753       if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
754         {
755           /* Set an invisible arg to synth_id_with_class_suffix.  */
756           implementation_context = impent->imp_context;
757           impent->class_decl
758             = create_builtin_decl (VAR_DECL, objc_category_template,
759                                    IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY")));
760         }
761     }
762   implementation_context = sav;
763 }
764
765 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
766    and initialized appropriately.  */
767
768 static void
769 generate_objc_symtab_decl ()
770 {
771   tree sc_spec;
772
773   if (!objc_category_template)
774     build_category_template ();
775
776   /* forward declare categories */
777   if (cat_count)
778     forward_declare_categories ();
779
780   if (!objc_symtab_template)
781     build_objc_symtab_template ();
782
783   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
784
785   _OBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
786                                    tree_cons (NULLT, objc_symtab_template, sc_spec), 1);
787
788   finish_decl (_OBJC_SYMBOLS_decl, init_objc_symtab (), NULLT);
789 }
790 \f
791 /*
792  *      tree_node------->tree_node----->...
793  *          |                |
794  *          | (value)        | (value)
795  *          |                |
796  *        expr             expr
797  */
798 static tree
799 init_module_descriptor ()
800 {
801   tree initlist, expr;
802
803   /* version = { 1, ... } */
804
805   expr = build_int_2 (OBJC_VERSION, 0);
806   initlist = build_tree_list (NULLT, expr);
807
808   /* size = { ..., sizeof (struct objc_module), ... } */
809
810   expr = build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_module_template)) /
811                       BITS_PER_UNIT, 0);
812   initlist = tree_cons (NULLT, expr, initlist);
813
814   /* name = { ..., "foo.m", ... } */
815
816   expr = build_msg_pool_reference (
817                                    add_objc_string (get_identifier (input_filename)));
818   initlist = tree_cons (NULLT, expr, initlist);
819
820   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
821
822   if (_OBJC_SYMBOLS_decl)
823     expr = build_unary_op (ADDR_EXPR, _OBJC_SYMBOLS_decl, 0);
824   else
825     expr = build_int_2 (0, 0);
826   initlist = tree_cons (NULLT, expr, initlist);
827
828   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
829 }
830
831 /* Write out the data structures to describe Objective C classes defined.
832    If appropriate, compile and output a setup function to initialize them.
833    Return a string which is the name of a function to call to initialize
834    the Objective C data structures for this file (and perhaps for other files
835    also).  */
836
837 static char *
838 build_module_descriptor ()
839 {
840   tree decl_specs, field_decl, field_decl_chain;
841
842   objc_module_template = start_struct (RECORD_TYPE, get_identifier (_TAG_MODULE));
843
844   /* long version; */
845
846   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
847   field_decl = get_identifier ("version");
848   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
849   field_decl_chain = field_decl;
850
851   /* long  size; */
852
853   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
854   field_decl = get_identifier ("size");
855   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
856   chainon (field_decl_chain, field_decl);
857
858   /* char  *name; */
859
860   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
861   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
862   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
863   chainon (field_decl_chain, field_decl);
864
865   /* struct objc_symtab *symtab; */
866
867   decl_specs = get_identifier (_TAG_SYMTAB);
868   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
869   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("symtab"));
870   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
871   chainon (field_decl_chain, field_decl);
872
873   finish_struct (objc_module_template, field_decl_chain);
874
875   /* create an instance of "objc_module" */
876
877   decl_specs = tree_cons (NULLT, objc_module_template,
878                           build_tree_list (NULLT, ridpointers[(int) RID_STATIC]));
879
880   _OBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
881                                    decl_specs, 1);
882
883   finish_decl (_OBJC_MODULES_decl, init_module_descriptor (), NULLT);
884
885   /* Mark the decl to avoid "defined but not used" warning. */
886   DECL_IN_SYSTEM_HEADER (_OBJC_MODULES_decl) = 1;
887
888   /* Generate a constructor call for the module descriptor. 
889      This code was generated by reading the grammar rules
890      of c-parse.y;  Therefore, it may not be the most efficient
891      way of generating the requisite code. */
892 #ifndef NEXT_OBJC_RUNTIME
893   {
894     tree parms, function_decl, decelerator, void_list_node;
895     tree function_type;
896     char *buf;
897     char *global_object_name = 0;
898     tree t;
899
900     /* Use a global object (which is already required to be unique over
901        the program) rather than the file name (which imposes extra
902        constraints).  -- Raeburn@MIT.EDU, 10 Jan 1990.  */
903
904     /* Find the name of some global object defined in this file.  */
905     for (t = getdecls (); t; t = TREE_CHAIN (t))
906       if (TREE_PUBLIC (t) && !DECL_EXTERNAL (t) && DECL_INITIAL (t) != 0)
907         {
908           global_object_name = IDENTIFIER_POINTER (DECL_NAME (t));
909           break;
910         }
911
912     /* If none, use the name of the file.  */
913     if (!global_object_name)
914       {
915         char *p, *q;
916         global_object_name
917           = (char *) alloca (strlen (main_input_filename) + 1);
918
919         p = main_input_filename;
920         q = global_object_name;
921
922         /* Replace any weird characters in the file name.  */
923         for (; *p; p++)
924           if (! ((*p >= '0' && *p <= '9')
925                  || (*p >= 'A' && *p <= 'Z')
926                  || (*p >= 'a' && *p <= 'z')))
927             *q++ = '_';
928           else
929             *q++ = *p;
930         *q = 0;
931       }
932
933     /* Make the constructor name from the name we have found.  */
934     buf = (char *) xmalloc (sizeof (CONSTRUCTOR_NAME_FORMAT)
935                             + strlen (global_object_name));
936     sprintf (buf, CONSTRUCTOR_NAME_FORMAT, global_object_name);
937
938     /* Declare void __objc_execClass (void*); */
939
940     void_list_node = build_tree_list (NULL_TREE, void_type_node);
941     function_type
942       = build_function_type (void_type_node,  
943                              tree_cons (NULL_TREE, ptr_type_node,  
944                                         void_list_node));
945     function_decl = build_decl (FUNCTION_DECL,  
946                                 get_identifier ("__objc_execClass"),  
947                                 function_type);
948     DECL_EXTERNAL (function_decl) = 1;
949     TREE_PUBLIC (function_decl) = 1;
950     pushdecl (function_decl);
951     rest_of_decl_compilation (function_decl, 0, 0, 0);
952
953     parms
954       = build_tree_list (NULLT,
955                          build_unary_op (ADDR_EXPR, _OBJC_MODULES_decl, 0));
956     decelerator = build_function_call (function_decl, parms);
957
958     /* void __objc_file_init () {objc_execClass(&L_OBJC_MODULES);}  */
959
960     start_function (void_list_node,
961                     build_parse_node (CALL_EXPR, get_identifier (buf),
962                                       /* This has the format of the output
963                                          of get_parm_info.  */
964                                       tree_cons (NULL_TREE, NULL_TREE,
965                                                  void_list_node),
966                                       NULL_TREE),
967                     0, 0);
968 #if 0 /* This should be turned back on later
969          for the systems where collect is not needed.  */
970     /* Make these functions nonglobal
971        so each file can use the same name.  */
972     TREE_PUBLIC (current_function_decl) = 0;
973 #endif
974     TREE_USED (current_function_decl) = 1;
975     store_parm_decls ();
976
977     assemble_external (function_decl);
978     c_expand_expr_stmt (decelerator);
979
980     finish_function (0);
981
982     /* Return the name of the constructor function.  */
983     return buf;
984   }
985 #else /* NEXT_OBJC_RUNTIME */
986   return 0;
987 #endif /* NEXT_OBJC_RUNTIME */
988 }
989
990 /* extern const char _OBJC_STRINGS[]; */
991
992 static void
993 generate_forward_declaration_to_string_table ()
994 {
995   tree sc_spec, decl_specs, expr_decl;
996
997   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_EXTERN], NULLT);
998   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
999
1000   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
1001
1002   _OBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1003 }
1004
1005 /* static char _OBJC_STRINGS[] = "..."; */
1006
1007 static void
1008 build_message_selector_pool ()
1009 {
1010   tree sc_spec, decl_specs, expr_decl;
1011   tree chain, string_expr;
1012   int goolengthtmp = 0, msg_pool_size = 0;
1013   char *string_goo;
1014
1015   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1016   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1017
1018   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
1019
1020   _OBJC_STRINGS_decl = start_decl (expr_decl, decl_specs, 1);
1021
1022   for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
1023     msg_pool_size += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1024
1025   msg_pool_size++;
1026
1027   string_goo = (char *)xmalloc (msg_pool_size);
1028   bzero (string_goo, msg_pool_size);
1029
1030   for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
1031     {
1032       strcpy (string_goo + goolengthtmp, IDENTIFIER_POINTER (TREE_VALUE (chain)));
1033       goolengthtmp += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1034     }
1035
1036   string_expr = my_build_string (msg_pool_size, string_goo);
1037
1038   finish_decl (_OBJC_STRINGS_decl, string_expr, NULLT);
1039 }
1040
1041 /*
1042  * synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
1043  *
1044  * the cast stops the compiler from issuing the following message:
1045  *
1046  * grok.m: warning: initialization of non-const * pointer from const *
1047  * grok.m: warning: initialization between incompatible pointer types
1048  */
1049 static tree
1050 build_msg_pool_reference (offset)
1051      int offset;
1052 {
1053   tree expr = build_int_2 (offset, 0);
1054   tree cast;
1055
1056   expr = build_array_ref (_OBJC_STRINGS_decl, expr);
1057   expr = build_unary_op (ADDR_EXPR, expr, 0);
1058
1059   cast = build_tree_list (build_tree_list (NULLT, ridpointers[(int) RID_CHAR]),
1060                           build1 (INDIRECT_REF, NULLT, NULLT));
1061   TREE_TYPE (expr) = groktypename (cast);
1062   return expr;
1063 }
1064
1065 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1066 static tree
1067 build_selector_reference (idx)
1068       int idx;
1069 {
1070   tree ref, decl, name, ident;
1071   char buf[256];
1072   struct obstack *save_current_obstack = current_obstack;
1073   struct obstack *save_rtl_obstack = rtl_obstack;
1074
1075   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
1076
1077   /* new stuff */
1078   rtl_obstack = current_obstack = &permanent_obstack;
1079   ident = get_identifier (buf);
1080
1081   if (IDENTIFIER_GLOBAL_VALUE (ident))
1082     decl = IDENTIFIER_GLOBAL_VALUE (ident); /* set by pushdecl() */
1083   else 
1084     {
1085       decl = build_decl (VAR_DECL, ident, selector_type);
1086       DECL_EXTERNAL (decl) = 1;
1087       TREE_PUBLIC (decl) = 1;
1088       TREE_USED (decl) = 1;
1089   
1090       make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
1091       pushdecl_top_level (decl);  /* our `extended/custom' pushdecl in c-decl.c */
1092     }
1093   current_obstack = save_current_obstack;
1094   rtl_obstack = save_rtl_obstack;
1095
1096   return decl;
1097 }
1098 #endif
1099
1100 static tree
1101 init_selector (offset)
1102      int offset;
1103 {
1104   tree expr = build_msg_pool_reference (offset);
1105   TREE_TYPE (expr) = selector_type; /* cast */
1106   return expr;
1107 }
1108
1109 static void
1110 build_selector_translation_table ()
1111 {
1112   tree sc_spec, decl_specs, expr_decl;
1113   tree chain, initlist = NULLT;
1114   int offset = 0;
1115 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1116   tree decl, var_decl;
1117   int idx = 0;
1118   char buf[256];
1119 #else
1120   /* The corresponding pop_obstacks is in finish_decl,
1121      called at the end of this function.  */
1122   push_obstacks_nochange ();
1123 #endif
1124
1125   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1126     {
1127       tree expr;
1128
1129 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1130       sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
1131       sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
1132
1133       /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
1134       decl_specs = tree_cons (NULLT, selector_type, sc_spec);
1135       var_decl = get_identifier (buf);
1136
1137       /* the `decl' that is returned from start_decl is the one that we
1138         * forward declared in `build_selector_reference()'
1139         */
1140       decl = start_decl (var_decl, decl_specs, 1); 
1141 #endif
1142
1143       expr = init_selector (offset);
1144
1145       /* add one for the '\0' character */
1146       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1147
1148 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1149       finish_decl (decl, expr, NULLT);
1150       idx++;
1151 #else
1152       initlist = tree_cons (NULLT, expr, initlist);
1153 #endif
1154     }
1155
1156 #ifdef OBJC_SELECTORS_WITHOUT_LABELS
1157   /* Cause the variable and its initial value to be actually output.  */
1158   DECL_EXTERNAL (_OBJC_SELECTOR_REFERENCES_decl) = 0;
1159   TREE_STATIC (_OBJC_SELECTOR_REFERENCES_decl) = 1;
1160   /* NULL terminate the list and fix the decl for output. */
1161   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
1162   DECL_INITIAL (_OBJC_SELECTOR_REFERENCES_decl) = (tree) 1;
1163   initlist = build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1164   finish_decl (_OBJC_SELECTOR_REFERENCES_decl, initlist, NULLT);
1165 #endif
1166 }
1167
1168 static void
1169 add_class_reference (ident)
1170      tree ident;
1171 {
1172   tree chain;
1173
1174   if (chain = cls_ref_chain)
1175     {
1176       tree tail;
1177       do
1178         {
1179           if (ident == TREE_VALUE (chain))
1180             return;
1181
1182           tail = chain;
1183           chain = TREE_CHAIN (chain);
1184         }
1185       while (chain);
1186
1187       /* append to the end of the list */
1188       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1189     }
1190   else
1191     cls_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
1192 }
1193
1194 /*
1195  * sel_ref_chain is a list whose "value" fields will be instances of
1196  * identifier_node that represent the selector.
1197  */
1198 static int
1199 add_selector_reference (ident)
1200      tree ident;
1201 {
1202   tree chain;
1203   int index = 0;
1204
1205   /* this adds it to sel_refdef_chain, the global pool of selectors */
1206   add_objc_string (ident);
1207
1208   if (chain = sel_ref_chain)
1209     {
1210       tree tail;
1211       do
1212         {
1213           if (ident == TREE_VALUE (chain))
1214             return index;
1215
1216           index++;
1217           tail = chain;
1218           chain = TREE_CHAIN (chain);
1219         }
1220       while (chain);
1221
1222       /* append to the end of the list */
1223       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1224     }
1225   else
1226     sel_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
1227
1228   max_selector_index++;
1229   return index;
1230 }
1231
1232 /*
1233  * sel_refdef_chain is a list whose "value" fields will be instances of
1234  * identifier_node that represent the selector. It returns the offset of
1235  * the selector from the beginning of the _OBJC_STRINGS pool. This offset
1236  * is typically used by "init_selector ()" during code generation.
1237  */
1238 static int
1239 add_objc_string (ident)
1240      tree ident;
1241 {
1242   tree chain;
1243   int offset = 0;
1244
1245   if (chain = sel_refdef_chain)
1246     {
1247       tree tail;
1248       do
1249         {
1250           if (ident == TREE_VALUE (chain))
1251             return offset;
1252
1253           /* add one for the '\0' character */
1254           offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1255           tail = chain;
1256           chain = TREE_CHAIN (chain);
1257         }
1258       while (chain);
1259
1260       /* append to the end of the list */
1261       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1262     }
1263   else
1264     sel_refdef_chain = perm_tree_cons (NULLT, ident, NULLT);
1265
1266   return offset;
1267 }
1268
1269 tree
1270 lookup_interface (ident)
1271      tree ident;
1272 {
1273   tree chain;
1274
1275   for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
1276     {
1277       if (ident == CLASS_NAME (chain))
1278         return chain;
1279     }
1280   return NULLT;
1281 }
1282
1283 static tree
1284 objc_copy_list (list, head)
1285      tree list;
1286      tree *head;
1287 {
1288   tree newlist = NULL_TREE, tail = NULL_TREE;
1289
1290   while (list)
1291     {
1292       tail = copy_node (list);
1293
1294       /* the following statement fixes a bug when inheriting instance
1295          variables that are declared to be bitfields. finish_struct () expects
1296          to find the width of the bitfield in DECL_INITIAL (), which it
1297          nulls out after processing the decl of the super class...rather
1298          than change the way finish_struct () works (which is risky),
1299          I create the situation it expects...s.naroff (7/23/89).
1300          */
1301       if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
1302         DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
1303
1304       newlist = chainon (newlist, tail);
1305       list = TREE_CHAIN (list);
1306     }
1307   *head = newlist;
1308   return tail;
1309 }
1310
1311 /* used by:
1312  * build_private_template (), get_class_ivars (), and get_static_reference ().
1313  */
1314 static tree
1315 build_ivar_chain (interface)
1316      tree interface;
1317 {
1318   tree my_name, super_name, ivar_chain;
1319
1320   my_name = CLASS_NAME (interface);
1321   super_name = CLASS_SUPER_NAME (interface);
1322
1323   /* "leaf" ivars never get copied...there is no reason to. */
1324   ivar_chain = CLASS_IVARS (interface);
1325
1326   while (super_name)
1327     {
1328       tree op1;
1329       tree super_interface = lookup_interface (super_name);
1330
1331       if (!super_interface)
1332         {
1333           /* fatal did not work with 2 args...should fix */
1334           error ("Cannot find interface declaration for `%s', superclass of `%s'",
1335                  IDENTIFIER_POINTER (super_name), IDENTIFIER_POINTER (my_name));
1336           exit (34);
1337         }
1338       if (super_interface == interface)
1339         {
1340           fatal ("Circular inheritance in interface declaration for `%s'",
1341                  IDENTIFIER_POINTER (super_name));
1342         }
1343       interface = super_interface;
1344       my_name = CLASS_NAME (interface);
1345       super_name = CLASS_SUPER_NAME (interface);
1346
1347       op1 = CLASS_IVARS (interface);
1348       if (op1)
1349         {
1350           tree head, tail = objc_copy_list (op1, &head);
1351
1352           /* prepend super class ivars...make a copy of the list, we
1353            * do not want to alter the original.
1354            */
1355           TREE_CHAIN (tail) = ivar_chain;
1356           ivar_chain = head;
1357         }
1358     }
1359   return ivar_chain;
1360 }
1361
1362 /*
1363  *  struct <classname> {
1364  *    struct objc_class *isa;
1365  *    ...
1366  *  };
1367  */
1368 static tree
1369 build_private_template (class)
1370      tree class;
1371 {
1372   tree ivar_context;
1373
1374   if (CLASS_STATIC_TEMPLATE (class))
1375     {
1376       _PRIVATE_record = CLASS_STATIC_TEMPLATE (class);
1377       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
1378     }
1379   else
1380     {
1381       _PRIVATE_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
1382
1383       ivar_context = build_ivar_chain (class);
1384
1385       finish_struct (_PRIVATE_record, ivar_context);
1386
1387       CLASS_STATIC_TEMPLATE (class) = _PRIVATE_record;
1388
1389       /* mark this record as class template - for class type checking */
1390       TREE_STATIC_TEMPLATE (_PRIVATE_record) = 1;
1391     }
1392   instance_type = groktypename (
1393                                 build_tree_list (build_tree_list (NULLT, _PRIVATE_record),
1394                                                  build1 (INDIRECT_REF, NULLT, NULLT)));
1395   return ivar_context;
1396 }
1397
1398 /*
1399  *  struct objc_category {
1400  *    char *category_name;
1401  *    char *class_name;
1402  *    struct objc_method_list *instance_methods;
1403  *    struct objc_method_list *class_methods;
1404  *  };
1405  */
1406 static void
1407 build_category_template ()
1408 {
1409   tree decl_specs, field_decl, field_decl_chain;
1410
1411   objc_category_template = start_struct (RECORD_TYPE,
1412                                          get_identifier (_TAG_CATEGORY));
1413   /* char *category_name; */
1414
1415   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1416   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("category_name"));
1417   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1418   field_decl_chain = field_decl;
1419
1420   /* char *class_name; */
1421
1422   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1423   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_name"));
1424   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1425   chainon (field_decl_chain, field_decl);
1426
1427   /* struct objc_method_list *instance_methods; */
1428
1429   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1430                                                  get_identifier (_TAG_METHOD_LIST)));
1431   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
1432   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1433   chainon (field_decl_chain, field_decl);
1434
1435   /* struct objc_method_list *class_methods; */
1436
1437   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1438                                                  get_identifier (_TAG_METHOD_LIST)));
1439   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
1440   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1441   chainon (field_decl_chain, field_decl);
1442
1443   finish_struct (objc_category_template, field_decl_chain);
1444 }
1445
1446 /*
1447  *  struct objc_class {
1448  *    struct objc_class *isa;
1449  *    struct objc_class *super_class;
1450  *    char *name;
1451  *    long version;
1452  *    long info;
1453  *    long instance_size;
1454  *    struct objc_ivar_list *ivars;
1455  *    struct objc_method_list *methods;
1456  *    struct objc_cache *cache;
1457  *  };
1458  */
1459 static void
1460 build_class_template ()
1461 {
1462   tree decl_specs, field_decl, field_decl_chain;
1463
1464   objc_class_template = start_struct (RECORD_TYPE, get_identifier (_TAG_CLASS));
1465
1466   /* struct objc_class *isa; */
1467
1468   decl_specs = build_tree_list (NULLT, objc_class_template);
1469   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
1470   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1471   field_decl_chain = field_decl;
1472
1473   /* struct objc_class *super_class; */
1474
1475   decl_specs = build_tree_list (NULLT, objc_class_template);
1476   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("super_class"));
1477   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1478   chainon (field_decl_chain, field_decl);
1479
1480   /* char *name; */
1481
1482   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1483   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
1484   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1485   chainon (field_decl_chain, field_decl);
1486
1487   /* long version; */
1488
1489   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1490   field_decl = get_identifier ("version");
1491   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1492   chainon (field_decl_chain, field_decl);
1493
1494   /* long info; */
1495
1496   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1497   field_decl = get_identifier ("info");
1498   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1499   chainon (field_decl_chain, field_decl);
1500
1501   /* long instance_size; */
1502
1503   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1504   field_decl = get_identifier ("instance_size");
1505   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1506   chainon (field_decl_chain, field_decl);
1507
1508   /* struct objc_ivar_list *ivars; */
1509
1510   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1511                                                  get_identifier (_TAG_IVAR_LIST)));
1512   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivars"));
1513   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1514   chainon (field_decl_chain, field_decl);
1515
1516   /* struct objc_method_list *methods; */
1517
1518   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1519                                                  get_identifier (_TAG_METHOD_LIST)));
1520   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("methods"));
1521   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1522   chainon (field_decl_chain, field_decl);
1523
1524   /* struct objc_cache *cache; */
1525
1526   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1527                                                  get_identifier ("objc_cache")));
1528   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("cache"));
1529   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1530   chainon (field_decl_chain, field_decl);
1531
1532   finish_struct (objc_class_template, field_decl_chain);
1533 }
1534
1535 /*
1536  * generate appropriate forward declarations for an implementation
1537  */
1538 static void
1539 synth_forward_declarations ()
1540 {
1541   tree sc_spec, decl_specs, factory_id, anId;
1542
1543   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
1544
1545   anId = synth_id_with_class_suffix ("_OBJC_CLASS");
1546
1547   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
1548   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
1549   _OBJC_CLASS_decl = define_decl (anId, decl_specs);
1550
1551   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
1552
1553   anId = synth_id_with_class_suffix ("_OBJC_METACLASS");
1554
1555   _OBJC_METACLASS_decl = define_decl (anId, decl_specs);
1556
1557   /* pre-build the following entities - for speed/convenience. */
1558
1559   anId = get_identifier ("super_class");
1560   _clsSuper_ref = build_component_ref (_OBJC_CLASS_decl, anId);
1561   __clsSuper_ref = build_component_ref (_OBJC_METACLASS_decl, anId);
1562 }
1563
1564 static void
1565 error_with_ivar (message, decl, rawdecl)
1566      char *message;
1567      tree decl;
1568      tree rawdecl;
1569 {
1570   count_error (0);
1571   fprintf (stderr, "%s:%d: ",
1572            DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
1573   bzero (errbuf, BUFSIZE);
1574   fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
1575 }
1576
1577 #define USERTYPE(t)     (TREE_CODE (t) == RECORD_TYPE || \
1578                          TREE_CODE (t) == UNION_TYPE ||  \
1579                          TREE_CODE (t) == ENUMERAL_TYPE)
1580
1581 static void
1582 check_ivars (inter, imp)
1583      tree inter;
1584      tree imp;
1585 {
1586   tree intdecls = CLASS_IVARS (inter);
1587   tree impdecls = CLASS_IVARS (imp);
1588   tree rawintdecls = CLASS_RAW_IVARS (inter);
1589   tree rawimpdecls = CLASS_RAW_IVARS (imp);
1590
1591   while (1)
1592     {
1593       tree t1, t2;
1594
1595       if (intdecls == 0 && impdecls == 0)
1596         break;
1597       if (intdecls == 0 || impdecls == 0)
1598         {
1599           error ("inconsistent instance variable specification");
1600           break;
1601         }
1602       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
1603
1604       if (!comptypes (t1, t2))
1605         {
1606           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
1607             {
1608               error_with_ivar ("conflicting instance variable type",
1609                                impdecls, rawimpdecls);
1610               error_with_ivar ("previous declaration of",
1611                                intdecls, rawintdecls);
1612             }
1613           else                  /* both the type and the name don't match */
1614             {
1615               error ("inconsistent instance variable specification");
1616               break;
1617             }
1618         }
1619       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
1620         {
1621           error_with_ivar ("conflicting instance variable name",
1622                            impdecls, rawimpdecls);
1623           error_with_ivar ("previous declaration of",
1624                            intdecls, rawintdecls);
1625         }
1626       intdecls = TREE_CHAIN (intdecls);
1627       impdecls = TREE_CHAIN (impdecls);
1628       rawintdecls = TREE_CHAIN (rawintdecls);
1629       rawimpdecls = TREE_CHAIN (rawimpdecls);
1630     }
1631 }
1632
1633 /*
1634  *      struct objc_super {
1635  *              id self;
1636  *              struct objc_class *class;
1637  *      };
1638  */
1639 static tree
1640 build_super_template ()
1641 {
1642   tree record, decl_specs, field_decl, field_decl_chain;
1643
1644   record = start_struct (RECORD_TYPE, get_identifier (_TAG_SUPER));
1645
1646   /* struct objc_object *self; */
1647
1648   decl_specs = build_tree_list (NULLT, objc_object_reference);
1649   field_decl = get_identifier ("self");
1650   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
1651   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1652   field_decl_chain = field_decl;
1653
1654   /* struct objc_class *class; */
1655
1656   decl_specs = get_identifier (_TAG_CLASS);
1657   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
1658   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class"));
1659
1660   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1661   chainon (field_decl_chain, field_decl);
1662
1663   finish_struct (record, field_decl_chain);
1664
1665   /* `struct objc_super *' */
1666   super_type = groktypename (build_tree_list (build_tree_list (NULLT, record),
1667                                               build1 (INDIRECT_REF, NULLT, NULLT)));
1668   return record;
1669 }
1670
1671 /*
1672  *      struct objc_ivar {
1673  *              char *ivar_name;
1674  *              char *ivar_type;
1675  *              int ivar_offset;
1676  *      };
1677  */
1678 static tree
1679 build_ivar_template ()
1680 {
1681   tree objc_ivar_id, objc_ivar_record;
1682   tree decl_specs, field_decl, field_decl_chain;
1683
1684   objc_ivar_id = get_identifier (_TAG_IVAR);
1685   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
1686
1687   /* char *ivar_name; */
1688
1689   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1690   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_name"));
1691
1692   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1693   field_decl_chain = field_decl;
1694
1695   /* char *ivar_type; */
1696
1697   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1698   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_type"));
1699
1700   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1701   chainon (field_decl_chain, field_decl);
1702
1703   /* int ivar_offset; */
1704
1705   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1706   field_decl = get_identifier ("ivar_offset");
1707
1708   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1709   chainon (field_decl_chain, field_decl);
1710
1711   finish_struct (objc_ivar_record, field_decl_chain);
1712
1713   return objc_ivar_record;
1714 }
1715
1716 /*
1717  *      struct {
1718  *              int ivar_count;
1719  *              struct objc_ivar ivar_list[ivar_count];
1720  *      };
1721  */
1722 static tree
1723 build_ivar_list_template (list_type, size)
1724      tree list_type;
1725      int size;
1726 {
1727   tree objc_ivar_list_id, objc_ivar_list_record;
1728   tree decl_specs, field_decl, field_decl_chain;
1729
1730   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
1731
1732   /* int ivar_count; */
1733
1734   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1735   field_decl = get_identifier ("ivar_count");
1736
1737   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1738   field_decl_chain = field_decl;
1739
1740   /* struct objc_ivar ivar_list[]; */
1741
1742   decl_specs = build_tree_list (NULLT, list_type);
1743   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
1744                          build_int_2 (size, 0));
1745
1746   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1747   chainon (field_decl_chain, field_decl);
1748
1749   finish_struct (objc_ivar_list_record, field_decl_chain);
1750
1751   return objc_ivar_list_record;
1752 }
1753
1754 /*
1755  *      struct {
1756  *              int method_next;
1757  *              int method_count;
1758  *              struct objc_method method_list[method_count];
1759  *      };
1760  */
1761 static tree
1762 build_method_list_template (list_type, size)
1763      tree list_type;
1764      int size;
1765 {
1766   tree objc_ivar_list_id, objc_ivar_list_record;
1767   tree decl_specs, field_decl, field_decl_chain;
1768
1769   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
1770
1771   /* int method_next; */
1772
1773   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1774   field_decl = get_identifier ("method_next");
1775
1776   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1777   field_decl_chain = field_decl;
1778
1779   /* int method_count; */
1780
1781   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1782   field_decl = get_identifier ("method_count");
1783
1784   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1785   chainon (field_decl_chain, field_decl);
1786
1787   /* struct objc_method method_list[]; */
1788
1789   decl_specs = build_tree_list (NULLT, list_type);
1790   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
1791                          build_int_2 (size, 0));
1792
1793   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1794   chainon (field_decl_chain, field_decl);
1795
1796   finish_struct (objc_ivar_list_record, field_decl_chain);
1797
1798   return objc_ivar_list_record;
1799 }
1800
1801 static tree
1802 build_ivar_list_initializer (field_decl, size)
1803      tree field_decl;
1804      int *size;
1805 {
1806   tree initlist = NULLT;
1807
1808   do
1809     {
1810       int offset;
1811
1812     /* set name */
1813     if (DECL_NAME (field_decl))
1814       {
1815         offset = add_objc_string (DECL_NAME (field_decl));
1816         initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1817       }
1818     else
1819       {
1820         /* unnamed bit-field ivar (yuck). */
1821         initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
1822       }
1823
1824       /* set type */
1825       encode_field_decl (field_decl, OBJC_ENCODE_DONT_INLINE_DEFS);
1826       offset = add_objc_string (get_identifier (obstack_finish (&util_obstack)));
1827       obstack_free (&util_obstack, util_firstobj);
1828
1829       initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1830
1831       /* set offset */
1832       initlist = tree_cons (NULLT,
1833                             build_int_2 (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)) / BITS_PER_UNIT, 0),
1834                             
1835                             initlist);
1836       (*size)++;
1837       field_decl = TREE_CHAIN (field_decl);
1838     }
1839   while (field_decl);
1840
1841   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1842 }
1843
1844 static tree
1845 generate_ivars_list (type, name, size, list)
1846      tree type;
1847      char *name;
1848      int size;
1849      tree list;
1850 {
1851   tree sc_spec, decl_specs, decl, initlist;
1852
1853   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1854   decl_specs = tree_cons (NULLT, type, sc_spec);
1855
1856   decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
1857
1858   initlist = build_tree_list (NULLT, build_int_2 (size, 0));
1859   initlist = tree_cons (NULLT, list, initlist);
1860
1861   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
1862
1863   return decl;
1864 }
1865
1866 static void
1867 generate_ivar_lists ()
1868 {
1869   tree initlist, ivar_list_template, chain;
1870   tree cast, variable_length_type;
1871   int size;
1872
1873   if (!objc_ivar_template)
1874     objc_ivar_template = build_ivar_template ();
1875
1876   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1877                                                             get_identifier (_TAG_IVAR_LIST))), NULLT);
1878   variable_length_type = groktypename (cast);
1879
1880   /* only generate class variables for the root of the inheritance
1881      hierarchy since these will be the same for every class */
1882
1883   if (CLASS_SUPER_NAME (implementation_template) == NULLT
1884       && (chain = TYPE_FIELDS (objc_class_template)))
1885     {
1886       size = 0;
1887       initlist = build_ivar_list_initializer (chain, &size);
1888
1889       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1890
1891       _OBJC_CLASS_VARIABLES_decl =
1892         generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
1893                              size, initlist);
1894       /* cast! */
1895       TREE_TYPE (_OBJC_CLASS_VARIABLES_decl) = variable_length_type;
1896     }
1897   else
1898     _OBJC_CLASS_VARIABLES_decl = 0;
1899
1900   chain = CLASS_IVARS (implementation_template);
1901   if (chain)
1902     {
1903       size = 0;
1904       initlist = build_ivar_list_initializer (chain, &size);
1905
1906       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1907
1908       _OBJC_INSTANCE_VARIABLES_decl =
1909         generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
1910                              size, initlist);
1911       /* cast! */
1912       TREE_TYPE (_OBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
1913     }
1914   else
1915     _OBJC_INSTANCE_VARIABLES_decl = 0;
1916 }
1917
1918 static tree
1919 build_dispatch_table_initializer (entries, size)
1920      tree entries;
1921      int *size;
1922 {
1923   tree initlist = NULLT;
1924
1925   do
1926     {
1927       int offset = add_objc_string (METHOD_SEL_NAME (entries));
1928
1929       initlist = tree_cons (NULLT, init_selector (offset), initlist);
1930
1931       offset = add_objc_string (METHOD_ENCODING (entries));
1932       initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1933
1934       initlist = tree_cons (NULLT, METHOD_DEFINITION (entries), initlist);
1935
1936       (*size)++;
1937       entries = TREE_CHAIN (entries);
1938     }
1939   while (entries);
1940
1941   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1942 }
1943
1944 /*
1945  * To accomplish method prototyping without generating all kinds of
1946  * inane warnings, the definition of the dispatch table entries were
1947  * changed from:
1948  *
1949  *      struct objc_method { SEL _cmd; id (*_imp)(); };
1950  * to:
1951  *      struct objc_method { SEL _cmd; void *_imp; };
1952  */
1953 static tree
1954 build_method_template ()
1955 {
1956   tree _SLT_record;
1957   tree decl_specs, field_decl, field_decl_chain, parms;
1958
1959   _SLT_record = start_struct (RECORD_TYPE, get_identifier (_TAG_METHOD));
1960
1961 #ifdef OBJC_INT_SELECTORS
1962   /* unsigned int _cmd; */
1963   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
1964   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
1965   field_decl = get_identifier ("_cmd");
1966 #else /* not OBJC_INT_SELECTORS */
1967   /* struct objc_selector *_cmd; */
1968   decl_specs = tree_cons (NULLT,
1969                           xref_tag (RECORD_TYPE,
1970                                     get_identifier (TAG_SELECTOR)),
1971                           NULLT);
1972   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
1973 #endif /* not OBJC_INT_SELECTORS */
1974
1975   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1976   field_decl_chain = field_decl;
1977
1978   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
1979   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
1980   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1981   chainon (field_decl_chain, field_decl);
1982
1983   /* void *_imp; */
1984
1985   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_VOID], NULLT);
1986   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_imp"));
1987   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1988   chainon (field_decl_chain, field_decl);
1989
1990   finish_struct (_SLT_record, field_decl_chain);
1991
1992   return _SLT_record;
1993 }
1994
1995
1996 static tree
1997 generate_dispatch_table (type, name, size, list)
1998      tree type;
1999      char *name;
2000      int size;
2001      tree list;
2002 {
2003   tree sc_spec, decl_specs, decl, initlist;
2004
2005   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
2006   decl_specs = tree_cons (NULLT, type, sc_spec);
2007
2008   decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
2009
2010   initlist = build_tree_list (NULLT, build_int_2 (0, 0));
2011   initlist = tree_cons (NULLT, build_int_2 (size, 0), initlist);
2012   initlist = tree_cons (NULLT, list, initlist);
2013
2014   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
2015
2016   return decl;
2017 }
2018
2019 static void
2020 generate_dispatch_tables ()
2021 {
2022   tree initlist, chain, method_list_template;
2023   tree cast, variable_length_type;
2024   int size;
2025
2026   if (!objc_method_template)
2027     objc_method_template = build_method_template ();
2028
2029   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2030                                                             get_identifier (_TAG_METHOD_LIST))), NULLT);
2031   variable_length_type = groktypename (cast);
2032
2033   chain = CLASS_CLS_METHODS (implementation_context);
2034   if (chain)
2035     {
2036       size = 0;
2037       initlist = build_dispatch_table_initializer (chain, &size);
2038
2039       method_list_template = build_method_list_template (objc_method_template,
2040                                                          size);
2041       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
2042         _OBJC_CLASS_METHODS_decl = 
2043             generate_dispatch_table (method_list_template,
2044                                      "_OBJC_CLASS_METHODS", 
2045                                      size, initlist);
2046       else
2047         /* we have a category */
2048         _OBJC_CLASS_METHODS_decl = 
2049             generate_dispatch_table (method_list_template,
2050                                      "_OBJC_CATEGORY_CLASS_METHODS", 
2051                                      size, initlist);
2052       /* cast! */
2053       TREE_TYPE (_OBJC_CLASS_METHODS_decl) = variable_length_type;
2054     }
2055   else
2056     _OBJC_CLASS_METHODS_decl = 0;
2057
2058   chain = CLASS_NST_METHODS (implementation_context);
2059   if (chain)
2060     {
2061       size = 0;
2062       initlist = build_dispatch_table_initializer (chain, &size);
2063
2064       method_list_template = build_method_list_template (objc_method_template,
2065                                                          size);
2066       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
2067         _OBJC_INSTANCE_METHODS_decl = 
2068             generate_dispatch_table (method_list_template,
2069                                      "_OBJC_INSTANCE_METHODS", 
2070                                      size, initlist);
2071       else
2072         /* we have a category */
2073         _OBJC_INSTANCE_METHODS_decl = 
2074             generate_dispatch_table (method_list_template,
2075                                      "_OBJC_CATEGORY_INSTANCE_METHODS", 
2076                                      size, initlist);
2077       /* cast! */
2078       TREE_TYPE (_OBJC_INSTANCE_METHODS_decl) = variable_length_type;
2079     }
2080   else
2081     _OBJC_INSTANCE_METHODS_decl = 0;
2082 }
2083
2084 static tree
2085 build_category_initializer (cat_name, class_name,
2086                             instance_methods, class_methods)
2087      tree cat_name;
2088      tree class_name;
2089      tree instance_methods;
2090      tree class_methods;
2091 {
2092   tree initlist = NULLT, expr;
2093
2094   initlist = tree_cons (NULLT, cat_name, initlist);
2095   initlist = tree_cons (NULLT, class_name, initlist);
2096
2097   if (!instance_methods)
2098     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2099   else
2100     {
2101       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
2102       initlist = tree_cons (NULLT, expr, initlist);
2103     }
2104   if (!class_methods)
2105     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2106   else
2107     {
2108       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
2109       initlist = tree_cons (NULLT, expr, initlist);
2110     }
2111   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
2112 }
2113
2114 /*
2115  *  struct objc_class {
2116  *    struct objc_class *isa;
2117  *    struct objc_class *super_class;
2118  *    char *name;
2119  *    long version;
2120  *    long info;
2121  *    long instance_size;
2122  *    struct objc_ivar_list *ivars;
2123  *    struct objc_method_list *methods;
2124  *    struct objc_cache *cache;
2125  *  };
2126  */
2127 static tree
2128 build_shared_structure_initializer (isa, super, name, size, status,
2129                                     dispatch_table, ivar_list)
2130      tree isa;
2131      tree super;
2132      tree name;
2133      tree size;
2134      int status;
2135      tree dispatch_table;
2136      tree ivar_list;
2137 {
2138   tree initlist = NULLT, expr;
2139
2140   /* isa = */
2141   initlist = tree_cons (NULLT, isa, initlist);
2142
2143   /* super_class = */
2144   initlist = tree_cons (NULLT, super, initlist);
2145
2146   /* name = */
2147   initlist = tree_cons (NULLT, name, initlist);
2148
2149   /* version = */
2150   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2151
2152   /* info = */
2153   initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist);
2154
2155   /* instance_size = */
2156   initlist = tree_cons (NULLT, size, initlist);
2157
2158   /* objc_ivar_list = */
2159   if (!ivar_list)
2160     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2161   else
2162     {
2163       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
2164       initlist = tree_cons (NULLT, expr, initlist);
2165     }
2166
2167   /* objc_method_list = */
2168   if (!dispatch_table)
2169     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2170   else
2171     {
2172       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
2173       initlist = tree_cons (NULLT, expr, initlist);
2174     }
2175
2176   /* method_cache = */
2177   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2178
2179   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
2180 }
2181
2182 /*
2183  * static struct objc_category _OBJC_CATEGORY_<name> = { ... };
2184  */
2185 static void
2186 generate_category (cat)
2187      tree cat;
2188 {
2189   tree sc_spec, decl_specs, decl;
2190   tree initlist, cat_name_expr, class_name_expr;
2191   int offset;
2192
2193   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
2194   decl_specs = tree_cons (NULLT, objc_category_template, sc_spec);
2195
2196   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY"),
2197                      decl_specs, 1);
2198
2199   offset = add_objc_string (CLASS_SUPER_NAME (cat));
2200   cat_name_expr = build_msg_pool_reference (offset);
2201
2202   offset = add_objc_string (CLASS_NAME (cat));
2203   class_name_expr = build_msg_pool_reference (offset);
2204
2205   initlist = build_category_initializer (
2206                                          cat_name_expr, class_name_expr,
2207                                          _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl);
2208
2209   finish_decl (decl, initlist, NULLT);
2210 }
2211
2212 /*
2213  * static struct objc_class _OBJC_METACLASS_Foo={ ... };
2214  * static struct objc_class _OBJC_CLASS_Foo={ ... };
2215  */
2216 static void
2217 generate_shared_structures ()
2218 {
2219   tree sc_spec, decl_specs, expr_decl, decl;
2220   tree name_expr, super_expr, root_expr;
2221   tree my_root_id = NULLT, my_super_id = NULLT;
2222   tree cast_type, initlist;
2223   int offset;
2224
2225   my_super_id = CLASS_SUPER_NAME (implementation_template);
2226   if (my_super_id)
2227     {
2228       add_class_reference (my_super_id);
2229
2230       /* compute "my_root_id" - this is required for code generation.
2231        * the "isa" for all meta class structures points to the root of
2232        * the inheritance hierarchy (e.g. "__Object")...
2233        */
2234       my_root_id = my_super_id;
2235       do
2236         {
2237           tree my_root_int = lookup_interface (my_root_id);
2238
2239           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
2240             my_root_id = CLASS_SUPER_NAME (my_root_int);
2241           else
2242             break;
2243         }
2244       while (1);
2245     }
2246   else                          /* no super class */
2247     {
2248       my_root_id = CLASS_NAME (implementation_template);
2249     }
2250
2251   cast_type = groktypename (build_tree_list (build_tree_list (NULLT,
2252                                                               objc_class_template), build1 (INDIRECT_REF, NULLT, NULLT)));
2253
2254   offset = add_objc_string (CLASS_NAME (implementation_template));
2255   name_expr = build_msg_pool_reference (offset);
2256
2257   /* install class `isa' and `super' pointers at runtime */
2258   if (my_super_id)
2259     {
2260       offset = add_objc_string (my_super_id);
2261       super_expr = build_msg_pool_reference (offset);
2262       TREE_TYPE (super_expr) = cast_type; /* cast! */
2263     }
2264   else
2265     super_expr = build_int_2 (0, 0);
2266
2267   offset = add_objc_string (my_root_id);
2268   root_expr = build_msg_pool_reference (offset);
2269   TREE_TYPE (root_expr) = cast_type; /* cast! */
2270
2271   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2272
2273   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
2274   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
2275
2276   decl = start_decl (DECL_NAME (_OBJC_METACLASS_decl), decl_specs, 1);
2277
2278   initlist = build_shared_structure_initializer (
2279                                                  root_expr, super_expr, name_expr,
2280                                                  build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) / BITS_PER_UNIT, 0),
2281                                                  2 /*CLS_META*/,
2282                                                  _OBJC_CLASS_METHODS_decl, _OBJC_CLASS_VARIABLES_decl);
2283
2284   finish_decl (decl, initlist, NULLT);
2285
2286   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2287
2288   decl = start_decl (DECL_NAME (_OBJC_CLASS_decl), decl_specs, 1);
2289
2290   initlist = build_shared_structure_initializer (
2291                                                  build_unary_op (ADDR_EXPR, _OBJC_METACLASS_decl, 0),
2292                                                  super_expr, name_expr,
2293                                                  build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) / BITS_PER_UNIT, 0),
2294                                                  1 /*CLS_FACTORY*/,
2295                                                  _OBJC_INSTANCE_METHODS_decl, _OBJC_INSTANCE_VARIABLES_decl);
2296
2297   finish_decl (decl, initlist, NULLT);
2298 }
2299
2300 static tree
2301 synth_id_with_class_suffix (preamble)
2302      char *preamble;
2303 {
2304   char *string;
2305   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
2306     {
2307       string = (char *) alloca (strlen (preamble)
2308                                 + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context)))
2309                                 + 3);
2310       sprintf (string, "%s_%s", preamble,
2311                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
2312     }
2313   else
2314     {
2315       /* we have a category */
2316       string = (char *) alloca (strlen (preamble)
2317                                 + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context)))
2318                                 + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)))
2319                                 + 3);
2320       sprintf (string, "%s_%s_%s", preamble,
2321                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
2322                IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
2323     }
2324   return get_identifier (string);
2325 }
2326
2327 /*
2328  *   usage:
2329  *              keyworddecl:
2330  *                      selector ':' '(' typename ')' identifier
2331  *
2332  *   purpose:
2333  *              transform an Objective-C keyword argument into
2334  *              the C equivalent parameter declarator.
2335  *
2336  *   in:        key_name, an "identifier_node" (optional).
2337  *              arg_type, a  "tree_list" (optional).
2338  *              arg_name, an "identifier_node".
2339  *
2340  *   note:      it would be really nice to strongly type the preceding
2341  *              arguments in the function prototype; however, then i
2342  *              could not use the "accessor" macros defined in "tree.h".
2343  *
2344  *   out:       an instance of "keyword_decl".
2345  *
2346  */
2347
2348 tree
2349 build_keyword_decl (key_name, arg_type, arg_name)
2350      tree key_name;
2351      tree arg_type;
2352      tree arg_name;
2353 {
2354   tree keyword_decl;
2355
2356   /* if no type is specified, default to "id" */
2357   if (arg_type == NULLT)
2358     arg_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
2359                                 build1 (INDIRECT_REF, NULLT, NULLT));
2360
2361   keyword_decl = make_node (KEYWORD_DECL);
2362
2363   TREE_TYPE (keyword_decl) = arg_type;
2364   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
2365   KEYWORD_KEY_NAME (keyword_decl) = key_name;
2366
2367   return keyword_decl;
2368 }
2369
2370 /*
2371  *  given a chain of keyword_decl's, synthesize the full keyword selector.
2372  */
2373 static tree
2374 build_keyword_selector (selector)
2375      tree selector;
2376 {
2377   int len = 0;
2378   tree key_chain, key_name;
2379   char *buf;
2380
2381   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
2382     {
2383       if (TREE_CODE (selector) == KEYWORD_DECL)
2384         key_name = KEYWORD_KEY_NAME (key_chain);
2385       else if (TREE_CODE (selector) == TREE_LIST)
2386         key_name = TREE_PURPOSE (key_chain);
2387
2388       if (key_name)
2389         len += IDENTIFIER_LENGTH (key_name) + 1;
2390       else                      /* just a ':' arg */
2391         len++;
2392     }
2393   buf = (char *)alloca (len + 1);
2394   bzero (buf, len + 1);
2395
2396   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
2397     {
2398       if (TREE_CODE (selector) == KEYWORD_DECL)
2399         key_name = KEYWORD_KEY_NAME (key_chain);
2400       else if (TREE_CODE (selector) == TREE_LIST)
2401         key_name = TREE_PURPOSE (key_chain);
2402
2403       if (key_name)
2404         strcat (buf, IDENTIFIER_POINTER (key_name));
2405       strcat (buf, ":");
2406     }
2407   return get_identifier (buf);
2408 }
2409
2410 /* used for declarations and definitions */
2411
2412 tree
2413 build_method_decl (code, ret_type, selector, add_args)
2414      enum tree_code code;
2415      tree ret_type;
2416      tree selector;
2417      tree add_args;
2418 {
2419   tree method_decl;
2420
2421   /* if no type is specified, default to "id" */
2422   if (ret_type == NULLT)
2423     ret_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
2424                                 build1 (INDIRECT_REF, NULLT, NULLT));
2425
2426   method_decl = make_node (code);
2427   TREE_TYPE (method_decl) = ret_type;
2428
2429   /*
2430    *  if we have a keyword selector, create an identifier_node that
2431    *  represents the full selector name (`:' included)...
2432    */
2433   if (TREE_CODE (selector) == KEYWORD_DECL)
2434     {
2435       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
2436       METHOD_SEL_ARGS (method_decl) = selector;
2437       METHOD_ADD_ARGS (method_decl) = add_args;
2438     }
2439   else
2440     {
2441       METHOD_SEL_NAME (method_decl) = selector;
2442       METHOD_SEL_ARGS (method_decl) = NULLT;
2443       METHOD_ADD_ARGS (method_decl) = NULLT;
2444     }
2445
2446   return method_decl;
2447 }
2448
2449 #define METHOD_DEF 0
2450 #define METHOD_REF 1
2451 /* Used by `build_message_expr' and `comp_method_types'.
2452    Return an argument list for method METH.
2453    CONTEXT is either METHOD_DEF or METHOD_REF,
2454     saying whether we are trying to define a method or call one.
2455    SUPERFLAG says this is for a send to super;
2456     this makes a difference for the NeXT calling sequence
2457     in which the lookup and the method call are done together.  */
2458
2459 static tree
2460 get_arg_type_list (meth, context, superflag)
2461      tree meth;
2462      int context;
2463      int superflag;
2464 {
2465   tree arglist, akey;
2466
2467 #ifdef NEXT_OBJC_RUNTIME
2468   /* receiver type */
2469   if (superflag)
2470     {
2471       arglist = build_tree_list (NULLT, super_type);
2472     }
2473   else
2474 #endif
2475     {
2476       if (context == METHOD_DEF)
2477         arglist = build_tree_list (NULLT, TREE_TYPE (self_decl));
2478       else
2479         arglist = build_tree_list (NULLT, id_type);
2480     }
2481
2482   /* selector type - will eventually change to `int' */
2483   chainon (arglist, build_tree_list (NULLT, selector_type));
2484
2485   /* build a list of argument types */
2486   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
2487     {
2488       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
2489       chainon (arglist, build_tree_list (NULLT, TREE_TYPE (arg_decl)));
2490     }
2491
2492   if (METHOD_ADD_ARGS (meth) == (tree)1)
2493     /*
2494      * we have a `, ...' immediately following the selector,
2495      * finalize the arglist...simulate get_parm_info (0)
2496      */
2497     ;
2498   else if (METHOD_ADD_ARGS (meth))
2499     {
2500       /* we have a variable length selector */
2501       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
2502       chainon (arglist, add_arg_list);
2503     }
2504   else                          /* finalize the arglist...simulate get_parm_info (1) */
2505     chainon (arglist, build_tree_list (NULLT, void_type_node));
2506
2507   return arglist;
2508 }
2509
2510 static tree
2511 check_duplicates (hsh)
2512      hash hsh;
2513 {
2514   tree meth = NULLT;
2515
2516   if (hsh)
2517     {
2518       meth = hsh->key;
2519
2520       if (hsh->list)
2521         {
2522           /* we have two methods with the same name and different types */
2523           attr loop;
2524           char type;
2525
2526           type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
2527
2528           warning ("multiple declarations for method `%s'",
2529                    IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
2530
2531           warn_with_method ("using", type, meth);
2532           for (loop = hsh->list; loop; loop = loop->next)
2533             warn_with_method ("also found", type, loop->value);
2534         }
2535     }
2536   return meth;
2537 }
2538
2539 static tree
2540 receiver_is_class_object (receiver)
2541       tree receiver;
2542 {
2543   /* the receiver is a function call that returns an id...
2544    * ...check if it is a call to objc_getClass, if so, give it
2545    * special treatment.
2546    */
2547   tree exp = TREE_OPERAND (receiver, 0);
2548
2549   if (exp != 0 && (TREE_CODE (exp) == ADDR_EXPR))
2550     {
2551       exp = TREE_OPERAND (exp, 0);
2552       if (exp != 0
2553           && TREE_CODE (exp) == FUNCTION_DECL && exp == objc_getClass_decl)
2554         {
2555           /* we have a call to objc_getClass! */
2556           tree arg = TREE_OPERAND (receiver, 1);
2557
2558           if (arg != 0
2559               && TREE_CODE (arg) == TREE_LIST
2560               && (arg = TREE_VALUE (arg))
2561               && TREE_CODE (arg) == NOP_EXPR
2562               && (arg = TREE_OPERAND (arg, 0))
2563               && TREE_CODE (arg) == ADDR_EXPR
2564               && (arg = TREE_OPERAND (arg, 0))
2565               && TREE_CODE (arg) == STRING_CST)
2566             /* finally, we have the class name */
2567             return get_identifier (TREE_STRING_POINTER (arg));
2568         }
2569     }
2570   return 0;
2571 }
2572 \f
2573 /* If we are currently building a message expr, this holds
2574    the identifier of the selector of the message.  This is
2575    used when printing warnings about argument mismatches. */
2576
2577 static tree building_objc_message_expr = 0;
2578
2579 tree
2580 maybe_building_objc_message_expr ()
2581 {
2582   return building_objc_message_expr;
2583 }
2584
2585 /* Construct an expression for sending a message.
2586    MESS has the object to send to in TREE_PURPOSE
2587    and the argument list (including selector) in TREE_VALUE.  */
2588
2589 tree
2590 build_message_expr (mess)
2591      tree mess;
2592 {
2593   tree receiver = TREE_PURPOSE (mess);
2594   tree selector, self_object;
2595   tree rtype, sel_name;
2596   tree args = TREE_VALUE (mess);
2597   tree method_params = NULLT;
2598   tree method_prototype = NULLT;
2599   int selTransTbl_index;
2600   tree retval;
2601   int statically_typed = 0, statically_allocated = 0;
2602   tree class_ident = 0;
2603
2604   /* 1 if this is sending to the superclass.  */
2605   int super;
2606
2607   if (!doing_objc_thang)
2608     fatal ("Objective-C text in C source file");
2609
2610   if (TREE_CODE (receiver) == ERROR_MARK)
2611     return error_mark_node;
2612
2613   /* determine receiver type */
2614   rtype = TREE_TYPE (receiver);
2615   super = (TREE_TYPE (receiver) == super_type);
2616
2617   if (! super)
2618     {
2619       if (TREE_STATIC_TEMPLATE (rtype))
2620         statically_allocated = 1;
2621       else if (TREE_CODE (rtype) == POINTER_TYPE
2622                && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
2623         statically_typed = 1;
2624       /* classfix -smn */
2625       else if (TREE_CODE (receiver) == CALL_EXPR && rtype == id_type
2626                && (class_ident = receiver_is_class_object (receiver)))
2627         ;
2628       else if (rtype != id_type && rtype != 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 (rtype == 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 tree
3418 start_class (code, class_name, super_name)
3419      enum tree_code code;
3420      tree class_name;
3421      tree super_name;
3422 {
3423   tree class;
3424
3425   if (!doing_objc_thang)
3426      fatal ("Objective-C text in C source file");
3427
3428   class = make_node (code);
3429
3430   CLASS_NAME (class) = class_name;
3431   CLASS_SUPER_NAME (class) = super_name;
3432   CLASS_CLS_METHODS (class) = NULL_TREE;
3433
3434   if (code == IMPLEMENTATION_TYPE)
3435     {
3436       /* pre-build the following entities - for speed/convenience. */
3437       if (!self_id)
3438         self_id = get_identifier ("self");
3439       if (!_cmd_id)
3440         _cmd_id = get_identifier ("_cmd");
3441
3442       if (!objc_super_template)
3443         objc_super_template = build_super_template ();
3444
3445       method_slot = 0;          /* reset for multiple classes per file */
3446
3447       implementation_context = class;
3448
3449       /* lookup the interface for this implementation. */
3450
3451       if (!(implementation_template = lookup_interface (class_name)))
3452         {
3453           warning ("Cannot find interface declaration for `%s'",
3454                    IDENTIFIER_POINTER (class_name));
3455           add_class (implementation_template = implementation_context);
3456         }
3457
3458       /* if a super class has been specified in the implementation,
3459          insure it conforms to the one specified in the interface */
3460
3461       if (super_name
3462           && (super_name != CLASS_SUPER_NAME (implementation_template)))
3463         {
3464           error ("conflicting super class name `%s'",
3465                  IDENTIFIER_POINTER (super_name));
3466           error ("previous declaration of `%s'",
3467                  IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)));
3468         }
3469     }
3470   else if (code == INTERFACE_TYPE)
3471     {
3472       if (lookup_interface (class_name))
3473         warning ("duplicate interface declaration for class `%s'",
3474                  IDENTIFIER_POINTER (class_name));
3475       else
3476         add_class (class);
3477     }
3478   else if (code == PROTOCOL_TYPE)
3479     {
3480       tree class_category_is_assoc_with;
3481
3482       /* for a category, class_name is really the name of the class that
3483          the following set of methods will be associated with...we must
3484          find the interface so that can derive the objects template */
3485
3486       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
3487         {
3488           error ("Cannot find interface declaration for `%s'",
3489                  IDENTIFIER_POINTER (class_name));
3490           exit (1);
3491         }
3492       else
3493         add_category (class_category_is_assoc_with, class);
3494     }
3495   else if (code == CATEGORY_TYPE)
3496     {
3497       /* pre-build the following entities - for speed/convenience. */
3498       if (!self_id)
3499         self_id = get_identifier ("self");
3500       if (!_cmd_id)
3501         _cmd_id = get_identifier ("_cmd");
3502
3503       if (!objc_super_template)
3504         objc_super_template = build_super_template ();
3505
3506       method_slot = 0;          /* reset for multiple classes per file */
3507
3508       implementation_context = class;
3509
3510       /* for a category, class_name is really the name of the class that
3511          the following set of methods will be associated with...we must
3512          find the interface so that can derive the objects template */
3513
3514       if (!(implementation_template = lookup_interface (class_name)))
3515         {
3516           error ("Cannot find interface declaration for `%s'",
3517                  IDENTIFIER_POINTER (class_name));
3518           exit (1);
3519         }
3520     }
3521   return class;
3522 }
3523
3524 tree
3525 continue_class (class)
3526      tree class;
3527 {
3528   if (TREE_CODE (class) == IMPLEMENTATION_TYPE
3529       || TREE_CODE (class) == CATEGORY_TYPE)
3530     {
3531       struct imp_entry *impEntry;
3532       tree ivar_context;
3533
3534       /* check consistency of the instance variables. */
3535
3536       if (CLASS_IVARS (class))
3537         check_ivars (implementation_template, class);
3538
3539       /* code generation */
3540
3541       ivar_context = build_private_template (implementation_template);
3542
3543       if (!objc_class_template)
3544         build_class_template ();
3545
3546       if (!(impEntry = (struct imp_entry *)xmalloc (sizeof (struct imp_entry))))
3547         perror ("unable to allocate in objc-tree.c");
3548
3549       impEntry->next = imp_list;
3550       impEntry->imp_context = class;
3551       impEntry->imp_template = implementation_template;
3552
3553       synth_forward_declarations ();
3554       impEntry->class_decl = _OBJC_CLASS_decl;
3555       impEntry->meta_decl = _OBJC_METACLASS_decl;
3556
3557       /* append to front and increment count */
3558       imp_list = impEntry;
3559       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3560         imp_count++;
3561       else
3562         cat_count++;
3563
3564       return ivar_context;
3565     }
3566   else if (TREE_CODE (class) == INTERFACE_TYPE)
3567     {
3568       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
3569
3570       if (!TYPE_FIELDS (record))
3571         {
3572           finish_struct (record, build_ivar_chain (class));
3573           CLASS_STATIC_TEMPLATE (class) = record;
3574
3575           /* mark this record as a class template - for static typing */
3576           TREE_STATIC_TEMPLATE (record) = 1;
3577         }
3578       return NULLT;
3579     }
3580   else
3581     return error_mark_node;
3582 }
3583
3584 /*
3585  * this is called once we see the "@end" in an interface/implementation.
3586  */
3587 void
3588 finish_class (class)
3589      tree class;
3590 {
3591   if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3592     {
3593       /* all code generation is done in finish_objc */
3594
3595       if (implementation_template != implementation_context)
3596         {
3597           /* ensure that all method listed in the interface contain bodies! */
3598           check_methods (CLASS_CLS_METHODS (implementation_template),
3599                          CLASS_CLS_METHODS (implementation_context), '+');
3600           check_methods (CLASS_NST_METHODS (implementation_template),
3601                          CLASS_NST_METHODS (implementation_context), '-');
3602         }
3603     }
3604   else if (TREE_CODE (class) == CATEGORY_TYPE)
3605     {
3606       tree category = CLASS_CATEGORY_LIST (implementation_template);
3607   
3608       /* find the category interface from the class it is associated with */
3609       while (category)
3610         {
3611           if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
3612             break;
3613           category = CLASS_CATEGORY_LIST (category);
3614         }
3615   
3616       if (category)
3617         {
3618           /* ensure that all method listed in the interface contain bodies! */
3619           check_methods (CLASS_CLS_METHODS (category),
3620                          CLASS_CLS_METHODS (implementation_context), '+');
3621           check_methods (CLASS_NST_METHODS (category),
3622                          CLASS_NST_METHODS (implementation_context), '-');
3623         }
3624     } 
3625   else if (TREE_CODE (class) == INTERFACE_TYPE)
3626     {
3627       tree decl_specs;
3628       char *string = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (class))) + 3);
3629
3630       /* extern struct objc_object *_<my_name>; */
3631
3632       sprintf (string, "_%s", IDENTIFIER_POINTER (CLASS_NAME (class)));
3633
3634       decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
3635       decl_specs = tree_cons (NULLT, objc_object_reference, decl_specs);
3636       define_decl (build1 (INDIRECT_REF, NULLT, get_identifier (string)),
3637                    decl_specs);
3638     }
3639 }
3640 \f
3641 /* "Encode" a data type into a string, whichg rows  in util_obstack.
3642    ??? What is the FORMAT?  Someone please document this!  */
3643
3644 /* Encode a pointer type.  */
3645
3646 static void
3647 encode_pointer (type, format)
3648      tree type;
3649      int format;
3650 {
3651   tree pointer_to = TREE_TYPE (type);
3652
3653   if (TREE_CODE (pointer_to) == RECORD_TYPE)
3654     {
3655       if (TYPE_NAME (pointer_to)
3656           && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
3657         {
3658           char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
3659
3660           if ((strcmp (name, TAG_OBJECT) == 0) /* '@' */
3661               || TREE_STATIC_TEMPLATE (pointer_to))
3662             {
3663               obstack_1grow (&util_obstack, '@');
3664               return;
3665             }
3666           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
3667             {
3668               obstack_1grow (&util_obstack, '#');
3669               return;
3670             }
3671 #ifndef OBJC_INT_SELECTORS
3672           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
3673             {
3674               obstack_1grow (&util_obstack, ':');
3675               return;
3676             }
3677 #endif /* OBJC_INT_SELECTORS */
3678         }
3679     }
3680   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
3681            && TYPE_MODE (pointer_to) == QImode)
3682     {
3683       obstack_1grow (&util_obstack, '*');
3684       return;
3685     }
3686
3687   /* we have a type that does not get special treatment... */
3688
3689   /* NeXT extension */
3690   obstack_1grow (&util_obstack, '^');
3691   encode_type (pointer_to, format);
3692 }
3693
3694 static void
3695 encode_array (type, format)
3696      tree type;
3697      int format;
3698 {
3699   tree anIntCst = TYPE_SIZE (type);
3700   tree array_of = TREE_TYPE (type);
3701   char buffer[40];
3702
3703   /* An incomplete array is treated like a pointer.  */
3704   if (anIntCst == NULL)
3705     {
3706       /* split for obvious reasons.  North-Keys 30 Mar 1991 */
3707       encode_pointer (type, format);
3708       return;
3709     }
3710   
3711   sprintf (buffer, "[%d",
3712            TREE_INT_CST_LOW (anIntCst)
3713            / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
3714   obstack_grow (&util_obstack, buffer, strlen (buffer));
3715   encode_type (array_of, format);
3716   obstack_1grow (&util_obstack, ']');
3717   return;
3718 }
3719 \f
3720 static void
3721 encode_aggregate (type, format)
3722      tree type;
3723      int format;
3724 {
3725   enum tree_code code = TREE_CODE (type);
3726
3727   switch (code)
3728     {
3729     case RECORD_TYPE:
3730       {
3731         if (*obstack_next_free (&util_obstack) == '^'
3732             || format !=  OBJC_ENCODE_INLINE_DEFS)
3733           {
3734             /* we have a reference - this is a NeXT extension--
3735                or we don't want the details.  */
3736             if (TYPE_NAME (type)
3737                 && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE))
3738               {
3739                 obstack_1grow (&util_obstack, '{');
3740                 obstack_grow (&util_obstack,
3741                               IDENTIFIER_POINTER (TYPE_NAME (type)),
3742                               strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
3743                 obstack_1grow (&util_obstack, '}');
3744               }
3745             else /* we have an untagged structure or a typedef */
3746               obstack_grow (&util_obstack, "{?}", 3);
3747           }
3748         else
3749           {
3750             tree fields = TYPE_FIELDS (type);
3751             obstack_1grow (&util_obstack, '{');
3752             for ( ; fields; fields = TREE_CHAIN (fields))
3753               encode_field_decl (fields, format);
3754             obstack_1grow (&util_obstack, '}');
3755           }
3756         break;
3757       }
3758     case UNION_TYPE:
3759       {
3760         if (*obstack_next_free (&util_obstack) == '^'
3761             || format !=  OBJC_ENCODE_INLINE_DEFS)
3762           {
3763             /* we have a reference - this is a NeXT extension--
3764                or we don't want the details.  */
3765             if (TYPE_NAME (type)
3766                 && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE))
3767               {
3768                 obstack_1grow (&util_obstack, '<');
3769                 obstack_grow (&util_obstack,
3770                               IDENTIFIER_POINTER (TYPE_NAME (type)),
3771                               strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
3772                 obstack_1grow (&util_obstack, '>');
3773               }
3774             else /* we have an untagged structure or a typedef */
3775               obstack_grow (&util_obstack, "<?>", 3);
3776           }
3777         else
3778           {
3779             tree fields = TYPE_FIELDS (type);
3780             obstack_1grow (&util_obstack, '<');
3781             for ( ; fields; fields = TREE_CHAIN (fields))
3782               encode_field_decl (fields, format);
3783             obstack_1grow (&util_obstack, '>');
3784           }
3785         break;
3786       }
3787
3788     case ENUMERAL_TYPE:
3789       obstack_1grow (&util_obstack, 'i');
3790       break;
3791     }
3792 }
3793
3794 /*
3795  *  support bitfields, the current version of Objective-C does not support
3796  *  them. the string will consist of one or more "b:n"'s where n is an
3797  *  integer describing the width of the bitfield. Currently, classes in
3798  *  the kit implement a method "-(char *)describeBitfieldStruct:" that
3799  *  simulates this...if they do not implement this method, the archiver
3800  *  assumes the bitfield is 16 bits wide (padded if necessary) and packed
3801  *  according to the GNU compiler. After looking at the "kit", it appears
3802  *  that all classes currently rely on this default behavior, rather than
3803  *  hand generating this string (which is tedious).
3804  */
3805 static void
3806 encode_bitfield (width, format)
3807      int width;
3808      int format;
3809 {
3810   char buffer[40];
3811   sprintf (buffer, "b%d", width);
3812   obstack_grow (&util_obstack, buffer, strlen (buffer));
3813 }
3814 \f
3815 /*
3816  *      format will be:
3817  *
3818  *      OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS
3819  */
3820 static void
3821 encode_type (type, format)
3822      tree type;
3823      int format;
3824 {
3825   enum tree_code code = TREE_CODE (type);
3826
3827   if (code == INTEGER_TYPE)
3828     {
3829       if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0)
3830         {
3831           /* unsigned integer types */
3832
3833           if (TYPE_MODE (type) == QImode) /* 'C' */
3834             obstack_1grow (&util_obstack, 'C');
3835           else if (TYPE_MODE (type) == HImode) /* 'S' */
3836             obstack_1grow (&util_obstack, 'S');
3837           else if (TYPE_MODE (type) == SImode)
3838             {
3839               if (type == long_unsigned_type_node)
3840                 obstack_1grow (&util_obstack, 'L'); /* 'L' */
3841               else
3842                 obstack_1grow (&util_obstack, 'I'); /* 'I' */
3843             }
3844         }
3845       else                      /* signed 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) /* 'i' */
3852             {
3853               if (type == long_integer_type_node)
3854                 obstack_1grow (&util_obstack, 'l'); /* 'l' */
3855               else
3856                 obstack_1grow (&util_obstack, 'i'); /* 'i' */
3857             }
3858         }
3859     }
3860   else if (code == REAL_TYPE)
3861     {
3862       /* floating point types */
3863
3864       if (TYPE_MODE (type) == SFmode) /* 'f' */
3865         obstack_1grow (&util_obstack, 'f');
3866       else if (TYPE_MODE (type) == DFmode
3867                || TYPE_MODE (type) == TFmode) /* 'd' */
3868         obstack_1grow (&util_obstack, 'd');
3869     }
3870
3871   else if (code == VOID_TYPE)   /* 'v' */
3872     obstack_1grow (&util_obstack, 'v');
3873
3874   else if (code == ARRAY_TYPE)
3875     encode_array (type, format);
3876
3877   else if (code == POINTER_TYPE)
3878     encode_pointer (type, format);
3879
3880   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
3881     encode_aggregate (type, format);
3882
3883   else if (code == FUNCTION_TYPE) /* '?' */
3884     obstack_1grow (&util_obstack, '?');
3885 }
3886
3887 static void
3888 encode_field_decl (field_decl, format)
3889      tree field_decl;
3890      int format;
3891 {
3892   if (DECL_BIT_FIELD (field_decl))
3893     encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
3894   else
3895     encode_type (TREE_TYPE (field_decl), format);
3896 }
3897
3898 static tree
3899 expr_last (complex_expr)
3900      tree complex_expr;
3901 {
3902   tree next;
3903
3904   if (complex_expr)
3905     while (next = TREE_OPERAND (complex_expr, 0))
3906       complex_expr = next;
3907   return complex_expr;
3908 }
3909 \f
3910 /* The selector of the current method,
3911    or NULL if we aren't compiling a method.  */
3912
3913 tree
3914 maybe_objc_method_name (decl)
3915       tree decl;
3916 {
3917   if (method_context)
3918     return METHOD_SEL_NAME (method_context);
3919   else
3920     return 0;
3921 }
3922
3923 /*
3924  *  Transform a method definition into a function definition as follows:
3925  *
3926  *  - synthesize the first two arguments, "self" and "_cmd".
3927  */
3928
3929 void
3930 start_method_def (method)
3931      tree method;
3932 {
3933   tree decl_specs;
3934
3935   /* required to implement _msgSuper () */
3936   method_context = method;
3937   _OBJC_SUPER_decl = NULLT;
3938
3939   pushlevel (0);                /* must be called BEFORE "start_function ()" */
3940
3941   /* generate prototype declarations for arguments..."new-style" */
3942
3943   if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
3944     decl_specs = build_tree_list (NULLT, _PRIVATE_record);
3945   else
3946     /* really a `struct objc_class *'...however we allow people to
3947        assign to self...which changes its type midstream.
3948        */
3949     decl_specs = build_tree_list (NULLT, objc_object_reference);
3950
3951   push_parm_decl (build_tree_list (decl_specs,
3952                                    build1 (INDIRECT_REF, NULLT, self_id)));
3953
3954 #ifdef OBJC_INT_SELECTORS
3955   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
3956   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
3957   push_parm_decl (build_tree_list (decl_specs, _cmd_id));
3958 #else /* not OBJC_INT_SELECTORS */
3959   decl_specs = build_tree_list (NULLT,
3960                                 xref_tag (RECORD_TYPE,
3961                                           get_identifier (TAG_SELECTOR)));
3962   push_parm_decl (build_tree_list (decl_specs, 
3963                                    build1 (INDIRECT_REF, NULLT, _cmd_id)));
3964 #endif /* not OBJC_INT_SELECTORS */
3965
3966   /* generate argument declarations if a keyword_decl */
3967   if (METHOD_SEL_ARGS (method))
3968     {
3969       tree arglist = METHOD_SEL_ARGS (method);
3970       do
3971         {
3972           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
3973           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
3974
3975           if (arg_decl)
3976             {
3977               tree last_expr = expr_last (arg_decl);
3978
3979               /* unite the abstract decl with its name */
3980               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
3981               push_parm_decl (build_tree_list (arg_spec, arg_decl));
3982               /* unhook...restore the abstract declarator */
3983               TREE_OPERAND (last_expr, 0) = NULLT;
3984             }
3985           else
3986             push_parm_decl (build_tree_list (arg_spec, KEYWORD_ARG_NAME (arglist)));
3987
3988           arglist = TREE_CHAIN (arglist);
3989         }
3990       while (arglist);
3991     }
3992
3993   if (METHOD_ADD_ARGS (method) > (tree)1)
3994     {
3995       /* we have a variable length selector - in "prototype" format */
3996       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
3997       while (akey)
3998         {
3999           /* this must be done prior to calling pushdecl (). pushdecl () is
4000            * going to change our chain on us...
4001            */
4002           tree nextkey = TREE_CHAIN (akey);
4003           pushdecl (akey);
4004           akey = nextkey;
4005         }
4006     }
4007 }
4008
4009 static void
4010 error_with_method (message, mtype, method)
4011      char *message;
4012      char mtype;
4013      tree method;
4014 {
4015   count_error (0);
4016   fprintf (stderr, "%s:%d: ",
4017            DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
4018   bzero (errbuf, BUFSIZE);
4019   fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
4020 }
4021
4022 static void
4023 warn_with_method (message, mtype, method)
4024      char *message;
4025      char mtype;
4026      tree method;
4027 {
4028   count_error (1);
4029   fprintf (stderr, "%s:%d: ",
4030            DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
4031   bzero (errbuf, BUFSIZE);
4032   fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
4033 }
4034
4035 /* return 1 if `method' is consistent with `proto' */
4036
4037 static int
4038 comp_method_with_proto (method, proto)
4039      tree method, proto;
4040 {
4041   static tree function_type = 0;
4042
4043   /* create a function_type node once */
4044   if (!function_type)
4045     {
4046       struct obstack *ambient_obstack = current_obstack;
4047       
4048       current_obstack = &permanent_obstack;
4049       function_type = make_node (FUNCTION_TYPE);
4050       current_obstack = ambient_obstack;
4051     }
4052
4053   /* install argument types - normally set by "build_function_type ()". */
4054   TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
4055
4056   /* install return type */
4057   TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
4058
4059   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
4060 }
4061
4062 /* return 1 if `proto1' is consistent with `proto2' */
4063
4064 static int
4065 comp_proto_with_proto (proto1, proto2)
4066      tree proto1, proto2;
4067 {
4068   static tree function_type1 = 0, function_type2 = 0;
4069
4070   /* create a couple function_type node's once */
4071   if (!function_type1)
4072     {
4073       struct obstack *ambient_obstack = current_obstack;
4074       
4075       current_obstack = &permanent_obstack;
4076       function_type1 = make_node (FUNCTION_TYPE);
4077       function_type2 = make_node (FUNCTION_TYPE);
4078       current_obstack = ambient_obstack;
4079     }
4080
4081   /* install argument types - normally set by "build_function_type ()". */
4082   TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
4083   TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
4084
4085   /* install return type */
4086   TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
4087   TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
4088
4089   return comptypes (function_type1, function_type2);
4090 }
4091
4092 /*
4093  *  - generate an identifier for the function. the format is "_n_cls",
4094  *    where 1 <= n <= nMethods, and cls is the name the implementation we
4095  *    are processing.
4096  *  - install the return type from the method declaration.
4097  *  - if we have a prototype, check for type consistency.
4098  */
4099 static void
4100 really_start_method (method, parmlist)
4101      tree method, parmlist;
4102 {
4103   tree sc_spec, ret_spec, ret_decl, decl_specs;
4104   tree method_decl, method_id;
4105   char *buf;
4106
4107   /* synth the storage class & assemble the return type */
4108   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
4109   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
4110   decl_specs = chainon (sc_spec, ret_spec);
4111
4112   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
4113     {
4114       /* Make sure this is big enough for any plausible method label.  */
4115       buf = (char *) alloca (50
4116                              + strlen (IDENTIFIER_POINTER (METHOD_SEL_NAME (method)))
4117                              + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))));
4118 #ifdef OBJC_GEN_METHOD_LABEL
4119       OBJC_GEN_METHOD_LABEL (buf,
4120                              TREE_CODE (method) == INSTANCE_METHOD_DECL,
4121                              IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4122                              NULL,
4123                              IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4124 #else
4125       sprintf (buf, "_%d_%s", ++method_slot,
4126                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
4127 #endif
4128     }
4129   else                          /* we have a category */
4130     {
4131       /* Make sure this is big enough for any plausible method label.  */
4132       buf = (char *) alloca (50
4133                              + strlen (IDENTIFIER_POINTER (METHOD_SEL_NAME (method)))
4134                              + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)))
4135                              + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))));
4136 #ifdef OBJC_GEN_METHOD_LABEL
4137       OBJC_GEN_METHOD_LABEL (buf,
4138                              TREE_CODE (method) == INSTANCE_METHOD_DECL,
4139                              IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4140                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)),
4141                              IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4142 #else
4143       sprintf (buf, "_%d_%s_%s", ++method_slot,
4144                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4145                IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
4146 #endif
4147     }
4148
4149   method_id = get_identifier (buf);
4150
4151   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULLT);
4152
4153   /* check the declarator portion of the return type for the method */
4154   if (ret_decl = TREE_VALUE (TREE_TYPE (method)))
4155     {
4156       /*
4157        * unite the complex decl (specified in the abstract decl) with the
4158        * function decl just synthesized...(int *), (int (*)()), (int (*)[]).
4159        */
4160       tree save_expr = expr_last (ret_decl);
4161
4162       TREE_OPERAND (save_expr, 0) = method_decl;
4163       method_decl = ret_decl;
4164       /* fool the parser into thinking it is starting a function */
4165       start_function (decl_specs, method_decl, 0);
4166       /* unhook...this has the effect of restoring the abstract declarator */
4167       TREE_OPERAND (save_expr, 0) = NULLT;
4168     }
4169   else
4170     {
4171       TREE_VALUE (TREE_TYPE (method)) = method_decl;
4172       /* fool the parser into thinking it is starting a function */
4173       start_function (decl_specs, method_decl, 0);
4174       /* unhook...this has the effect of restoring the abstract declarator */
4175       TREE_VALUE (TREE_TYPE (method)) = NULLT;
4176     }
4177
4178   METHOD_DEFINITION (method) = current_function_decl;
4179
4180   /* check consistency...start_function (), pushdecl (), duplicate_decls (). */
4181
4182   if (implementation_template != implementation_context)
4183     {
4184       tree chain, proto;
4185
4186       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
4187         chain = CLASS_NST_METHODS (implementation_template);
4188       else
4189         chain = CLASS_CLS_METHODS (implementation_template);
4190
4191       if (proto = lookup_method (chain, METHOD_SEL_NAME (method)))
4192         {
4193           if (!comp_method_with_proto (method, proto))
4194             {
4195               fprintf (stderr, "%s: In method `%s'\n", input_filename,
4196                        IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4197               if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
4198                 {
4199                   error_with_method ("conflicting types for", '-', method);
4200                   error_with_method ("previous declaration of", '-', proto);
4201                 }
4202               else
4203                 {
4204                   error_with_method ("conflicting types for", '+', method);
4205                   error_with_method ("previous declaration of", '+', proto);
4206                 }
4207             }
4208         }
4209     }
4210 }
4211
4212 /*
4213  * the following routine is always called...this "architecture" is to
4214  * accommodate "old-style" variable length selectors.
4215  *
4216  *      - a:a b:b // prototype  ; id c; id d; // old-style
4217  */
4218 void
4219 continue_method_def ()
4220 {
4221   tree parmlist;
4222
4223   if (METHOD_ADD_ARGS (method_context) == (tree)1)
4224     /*
4225      * we have a `, ...' immediately following the selector.
4226      */
4227     parmlist = get_parm_info (0);
4228   else
4229     parmlist = get_parm_info (1); /* place a `void_at_end' */
4230
4231   /* set self_decl from the first argument...this global is used by
4232    * build_ivar_reference ().build_indirect_ref ().
4233    */
4234   self_decl = TREE_PURPOSE (parmlist);
4235
4236   poplevel (0, 0, 0);           /* must be called BEFORE "start_function ()" */
4237
4238   really_start_method (method_context, parmlist);
4239
4240   store_parm_decls ();          /* must be called AFTER "start_function ()" */
4241 }
4242
4243 void
4244 add_objc_decls ()
4245 {
4246   if (!_OBJC_SUPER_decl)
4247     _OBJC_SUPER_decl = start_decl (get_identifier (_TAG_SUPER),
4248                                    build_tree_list (NULLT, objc_super_template), 0);
4249
4250   /* this prevents `unused variable' warnings when compiling with `-Wall' */
4251   DECL_IN_SYSTEM_HEADER (_OBJC_SUPER_decl) = 1;
4252 }
4253
4254 /*
4255  *      _n_Method (id self, SEL sel, ...)
4256  *      {
4257  *              struct objc_super _S;
4258  *
4259  *              _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
4260  *      }
4261  */
4262 tree
4263 get_super_receiver ()
4264 {
4265   if (method_context)
4266     {
4267       tree super_expr, super_expr_list;
4268
4269       /* set receiver to self */
4270       super_expr = build_component_ref (_OBJC_SUPER_decl, self_id);
4271       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
4272       super_expr_list = build_tree_list (NULLT, super_expr);
4273
4274       /* set class to begin searching */
4275       super_expr = build_component_ref (_OBJC_SUPER_decl, get_identifier ("class"));
4276
4277       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
4278         {
4279           /* [_cls, __cls]Super are "pre-built" in synth_foward_declarations () */
4280
4281           if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4282             super_expr = build_modify_expr (super_expr, NOP_EXPR, _clsSuper_ref);
4283           else
4284             super_expr = build_modify_expr (super_expr, NOP_EXPR, __clsSuper_ref);
4285         }
4286       else                      /* we have a category... */
4287         {
4288           tree params, super_name = CLASS_SUPER_NAME (implementation_template);
4289           tree funcCall;
4290
4291           if (!super_name)  /* Barf if super used in a category of Object. */
4292             {
4293               error("no super class declared in interface for `%s'",
4294                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4295               return error_mark_node;
4296             }
4297
4298           add_class_reference (super_name);
4299
4300           params = build_tree_list (NULLT,
4301                                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
4302                                                      IDENTIFIER_POINTER (super_name)));
4303
4304           if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4305             funcCall = build_function_call (objc_getClass_decl, params);
4306           else
4307             funcCall = build_function_call (objc_getMetaClass_decl, params);
4308
4309           /* cast! */
4310           TREE_TYPE (funcCall) = TREE_TYPE (_clsSuper_ref);
4311           super_expr = build_modify_expr (super_expr, NOP_EXPR, funcCall);
4312         }
4313       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
4314
4315       super_expr = build_unary_op (ADDR_EXPR, _OBJC_SUPER_decl, 0);
4316       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
4317
4318       return build_compound_expr (super_expr_list);
4319     }
4320   else
4321     {
4322       error ("[super ...] must appear in a method context");
4323       return error_mark_node;
4324     }
4325 }
4326
4327 static tree
4328 encode_method_def (func_decl)
4329       tree func_decl;
4330 {
4331   tree parms;
4332   int stack_size = 0;
4333   char buffer[40];
4334   tree result;
4335
4336   /* return type */
4337   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
4338                OBJC_ENCODE_DONT_INLINE_DEFS);
4339   /* stack size */
4340   for (parms = DECL_ARGUMENTS (func_decl); parms;
4341        parms = TREE_CHAIN (parms))
4342     stack_size += TREE_INT_CST_LOW (TYPE_SIZE (DECL_ARG_TYPE (parms)))
4343                   / BITS_PER_UNIT;
4344
4345   sprintf (buffer, "%d", stack_size);
4346   obstack_grow (&util_obstack, buffer, strlen (buffer));
4347
4348   /* argument types */
4349   for (parms = DECL_ARGUMENTS (func_decl); parms;
4350        parms = TREE_CHAIN (parms))
4351     {
4352       int offset_in_bytes;
4353   
4354       /* type */ 
4355       encode_type (TREE_TYPE (parms), OBJC_ENCODE_DONT_INLINE_DEFS);
4356   
4357       /* compute offset */
4358       if (GET_CODE (DECL_INCOMING_RTL (parms)) == MEM)
4359         {
4360           rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
4361           
4362           /* ??? Here we assume that the parm address is indexed
4363               off the frame pointer or arg pointer.
4364               If that is not true, we produce meaningless results,
4365               but do not crash.  */
4366           if (GET_CODE (addr) == PLUS
4367               && GET_CODE (XEXP (addr, 1)) == CONST_INT)
4368             offset_in_bytes = INTVAL (XEXP (addr, 1));
4369           else
4370             offset_in_bytes = 0;
4371           
4372           /* This is the case where the parm is passed as an int or double
4373               and it is converted to a char, short or float and stored back
4374               in the parmlist.  In this case, describe the parm
4375               with the variable's declared type, and adjust the address
4376               if the least significant bytes (which we are using) are not
4377               the first ones.  */
4378 #if BYTES_BIG_ENDIAN
4379           if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
4380             offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
4381                                 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
4382 #endif
4383         }
4384       else
4385         offset_in_bytes = 0;
4386       
4387       /* The "+ 4" is a total hack to account for the return pc and
4388          saved fp on the 68k.  We should redefine this format! */
4389       sprintf (buffer, "%d", offset_in_bytes + 8);
4390       obstack_grow (&util_obstack, buffer, strlen (buffer));
4391     }
4392
4393   result = get_identifier (obstack_finish (&util_obstack));
4394   obstack_free (&util_obstack, util_firstobj);
4395   return result;
4396 }
4397
4398 void
4399 finish_method_def ()
4400 {
4401   METHOD_ENCODING (method_context) =
4402     encode_method_def (current_function_decl);
4403
4404   finish_function (0);
4405
4406   /* this must be done AFTER finish_function, since the optimizer may
4407      find "may be used before set" errors.  */
4408   method_context = NULLT;       /* required to implement _msgSuper () */
4409 }
4410
4411 int
4412 lang_report_error_function (decl)
4413       tree decl;
4414 {
4415   if (method_context)
4416     {
4417       fprintf (stderr, "In method `%s'\n",
4418                IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
4419       return 1;
4420     }
4421   else
4422     return 0;
4423 }
4424
4425 static int
4426 is_complex_decl (type)
4427      tree type;
4428 {
4429   return (TREE_CODE (type) == ARRAY_TYPE
4430           || TREE_CODE (type) == FUNCTION_TYPE
4431           || TREE_CODE (type) == POINTER_TYPE);
4432 }
4433
4434 \f
4435 /* Code to convert a decl node into text for a declaration in C.  */
4436
4437 static char tmpbuf[256];
4438
4439 static void
4440 adorn_decl (decl, str)
4441      tree decl;
4442      char *str;
4443 {
4444   enum tree_code code = TREE_CODE (decl);
4445
4446   if (code == ARRAY_REF)
4447     {
4448       tree anIntCst = TREE_OPERAND (decl, 1);
4449
4450       sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (anIntCst));
4451     }
4452   else if (code == ARRAY_TYPE)
4453     {
4454       tree anIntCst = TYPE_SIZE (decl);
4455       tree array_of = TREE_TYPE (decl);
4456
4457       sprintf (str + strlen (str), "[%d]",
4458                TREE_INT_CST_LOW (anIntCst)/TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
4459     }
4460   else if (code == CALL_EXPR)
4461     strcat (str, "()");
4462   else if (code == FUNCTION_TYPE)
4463     {
4464       tree chain  = TYPE_ARG_TYPES (decl); /* a list of types */
4465       strcat (str, "(");
4466       while (chain && TREE_VALUE (chain) != void_type_node)
4467         {
4468           gen_declaration (TREE_VALUE (chain), str);
4469           chain = TREE_CHAIN (chain);
4470           if (chain && TREE_VALUE (chain) != void_type_node)
4471             strcat (str, ",");
4472         }
4473       strcat (str, ")");
4474     }
4475   else
4476     {
4477       strcpy (tmpbuf, "*"); strcat (tmpbuf, str);
4478       strcpy (str, tmpbuf);
4479     }
4480 }
4481
4482 static char *
4483 gen_declarator (decl, buf, name)
4484      tree decl;
4485      char *buf;
4486      char *name;
4487 {
4488   if (decl)
4489     {
4490       enum tree_code code = TREE_CODE (decl);
4491       char *str;
4492       tree op;
4493       int wrap = 0;
4494
4495       switch (code)
4496         {
4497         case ARRAY_REF: case INDIRECT_REF: case CALL_EXPR:
4498           {
4499             op = TREE_OPERAND (decl, 0);
4500
4501             /* we have a pointer to a function or array...(*)(), (*)[] */
4502             if ((code == ARRAY_REF || code == CALL_EXPR) &&
4503                 (op && TREE_CODE (op) == INDIRECT_REF))
4504               wrap = 1;
4505
4506             str = gen_declarator (op, buf, name);
4507
4508             if (wrap)
4509               {
4510                 strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
4511                 strcpy (str, tmpbuf);
4512               }
4513
4514             adorn_decl (decl, str);
4515             break;
4516           }
4517         case ARRAY_TYPE: case FUNCTION_TYPE: case POINTER_TYPE:
4518           {
4519             str = strcpy (buf, name);
4520
4521             /* this clause is done iteratively...rather than recursively */
4522             do
4523               {
4524                 op = is_complex_decl (TREE_TYPE (decl))
4525                   ? TREE_TYPE (decl)
4526                     : NULLT;
4527
4528                 adorn_decl (decl, str);
4529
4530                 /* we have a pointer to a function or array...(*)(), (*)[] */
4531                 if ((code == POINTER_TYPE) &&
4532                     (op && (TREE_CODE (op) == FUNCTION_TYPE
4533                             || TREE_CODE (op) == ARRAY_TYPE)))
4534                   {
4535                     strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
4536                     strcpy (str, tmpbuf);
4537                   }
4538
4539                 decl = is_complex_decl (TREE_TYPE (decl))
4540                   ? TREE_TYPE (decl)
4541                     : NULLT;
4542               }
4543             while (decl && (code = TREE_CODE (decl)));
4544
4545             break;
4546           }
4547         case IDENTIFIER_NODE:
4548           /* will only happen if we are processing a "raw" expr-decl. */
4549           return strcpy (buf, IDENTIFIER_POINTER (decl));
4550         }
4551
4552       return str;
4553     }
4554   else                          /* we have an abstract declarator or a _DECL node */
4555     {
4556       return strcpy (buf, name);
4557     }
4558 }
4559
4560 static void
4561 gen_declspecs (declspecs, buf, raw)
4562      tree declspecs;
4563      char *buf;
4564      int raw;
4565 {
4566   if (raw)
4567     {
4568       tree chain;
4569
4570       for (chain = declspecs; chain; chain = TREE_CHAIN (chain))
4571         {
4572           tree aspec = TREE_VALUE (chain);
4573
4574           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
4575             strcat (buf, IDENTIFIER_POINTER (aspec));
4576           else if (TREE_CODE (aspec) == RECORD_TYPE)
4577             {
4578               if (TYPE_NAME (aspec))
4579                 {
4580                   if (!TREE_STATIC_TEMPLATE (aspec))
4581                     strcat (buf, "struct ");
4582                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4583                 }
4584               else
4585                 strcat (buf, "untagged struct");
4586             }
4587           else if (TREE_CODE (aspec) == UNION_TYPE)
4588             {
4589               if (TYPE_NAME (aspec))
4590                 {
4591                   if (!TREE_STATIC_TEMPLATE (aspec))
4592                     strcat (buf, "union ");
4593                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4594                 }
4595               else
4596                 strcat (buf, "untagged union");
4597             }
4598           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
4599             {
4600               if (TYPE_NAME (aspec))
4601                 {
4602                   if (!TREE_STATIC_TEMPLATE (aspec))
4603                     strcat (buf, "enum ");
4604                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4605                 }
4606               else
4607                 strcat (buf, "untagged enum");
4608             }
4609           strcat (buf, " ");
4610         }
4611     }
4612   else
4613     switch (TREE_CODE (declspecs))
4614       {
4615         /* type specifiers */
4616
4617       case INTEGER_TYPE:        /* signed integer types */
4618
4619         if (declspecs == short_integer_type_node) /* 's' */
4620           strcat (buf, "short int ");
4621         else if (declspecs == integer_type_node) /* 'i' */
4622           strcat (buf, "int ");
4623         else if (declspecs == long_integer_type_node) /* 'l' */
4624           strcat (buf, "long int ");
4625         else if (declspecs == signed_char_type_node || /* 'c' */
4626                  declspecs == char_type_node)
4627           strcat (buf, "char ");
4628
4629         /* unsigned integer types */
4630
4631         else if (declspecs == short_unsigned_type_node) /* 'S' */
4632           strcat (buf, "unsigned short ");
4633         else if (declspecs == unsigned_type_node) /* 'I' */
4634           strcat (buf, "unsigned int ");
4635         else if (declspecs == long_unsigned_type_node) /* 'L' */
4636           strcat (buf, "unsigned long ");
4637         else if (declspecs == unsigned_char_type_node) /* 'C' */
4638           strcat (buf, "unsigned char ");
4639         break;
4640
4641       case REAL_TYPE:           /* floating point types */
4642
4643         if (declspecs == float_type_node) /* 'f' */
4644           strcat (buf, "float ");
4645         else if (declspecs == double_type_node) /* 'd' */
4646           strcat (buf, "double ");
4647         else if (declspecs == long_double_type_node) /* 'd' */
4648           strcat (buf, "long double ");
4649         break;
4650
4651       case RECORD_TYPE:
4652         if (!TREE_STATIC_TEMPLATE (declspecs))
4653           strcat (buf, "struct ");
4654         if (TYPE_NAME (declspecs) &&
4655             (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4656           {
4657             strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4658             strcat (buf, " ");
4659           }
4660         break;
4661       case UNION_TYPE:
4662         strcat (buf, "union ");
4663         if (TYPE_NAME (declspecs) &&
4664             (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4665           {
4666             strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4667             strcat (buf, " ");
4668           }
4669         break;
4670       case ENUMERAL_TYPE:
4671         strcat (buf, "enum ");
4672         if (TYPE_NAME (declspecs) &&
4673             (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4674           {
4675             strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4676             strcat (buf, " ");
4677           }
4678         break;
4679       case VOID_TYPE:
4680         strcat (buf, "void ");
4681       }
4682 }
4683
4684 static char *
4685 gen_declaration (atype_or_adecl, buf)
4686      tree atype_or_adecl;
4687      char *buf;
4688 {
4689   char declbuf[256];
4690
4691   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
4692     {
4693       tree declspecs;           /* "identifier_node", "record_type" */
4694       tree declarator;          /* "array_ref", "indirect_ref", "call_expr"... */
4695
4696       /* we have a "raw", abstract declarator (typename) */
4697       declarator = TREE_VALUE (atype_or_adecl);
4698       declspecs  = TREE_PURPOSE (atype_or_adecl);
4699
4700       gen_declspecs (declspecs, buf, 1);
4701       strcat (buf, gen_declarator (declarator, declbuf, ""));
4702     }
4703   else
4704     {
4705       tree atype;
4706       tree declspecs;           /* "integer_type", "real_type", "record_type"... */
4707       tree declarator;          /* "array_type", "function_type", "pointer_type". */
4708
4709       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
4710           || TREE_CODE (atype_or_adecl) == PARM_DECL
4711           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
4712         atype = TREE_TYPE (atype_or_adecl);
4713       else
4714         atype = atype_or_adecl; /* assume we have a *_type node */
4715
4716       if (is_complex_decl (atype))
4717         {
4718           tree chain;
4719
4720           /* get the declaration specifier...it is at the end of the list */
4721           declarator = chain = atype;
4722           do
4723             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
4724           while (is_complex_decl (chain));
4725           declspecs = chain;
4726         }
4727       else
4728         {
4729           declspecs = atype;
4730           declarator = NULLT;
4731         }
4732
4733       gen_declspecs (declspecs, buf, 0);
4734
4735       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
4736           || TREE_CODE (atype_or_adecl) == PARM_DECL
4737           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
4738         {
4739           if (declarator)
4740             {
4741               strcat (buf, gen_declarator (declarator, declbuf,
4742                                            IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))));
4743             }
4744           else
4745             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)));
4746         }
4747       else
4748         {
4749           strcat (buf, gen_declarator (declarator, declbuf, ""));
4750         }
4751     }
4752   return buf;
4753 }
4754
4755 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
4756
4757 static char *
4758 gen_method_decl (method, buf)
4759      tree method;
4760      char *buf;
4761 {
4762   tree chain;
4763
4764   if (RAW_TYPESPEC (method) != objc_object_reference)
4765     {
4766       strcpy (buf, "(");
4767       gen_declaration (TREE_TYPE (method), buf);
4768       strcat (buf, ")");
4769     }
4770
4771   chain = METHOD_SEL_ARGS (method);
4772   if (chain)
4773     {                           /* we have a chain of keyword_decls */
4774       do
4775         {
4776           if (KEYWORD_KEY_NAME (chain))
4777             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
4778
4779           strcat (buf, ":");
4780           if (RAW_TYPESPEC (chain) != objc_object_reference)
4781             {
4782               strcat (buf, "(");
4783               gen_declaration (TREE_TYPE (chain), buf);
4784               strcat (buf, ")");
4785             }
4786           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
4787           if (chain = TREE_CHAIN (chain))
4788             strcat (buf, " ");
4789         }
4790       while (chain);
4791
4792       if (METHOD_ADD_ARGS (method) == (tree)1)
4793         strcat (buf, ", ...");
4794       else if (METHOD_ADD_ARGS (method))
4795         {                       /* we have a tree list node as generate by `get_parm_info ()' */
4796           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
4797           /* know we have a chain of parm_decls */
4798           while (chain)
4799             {
4800               strcat (buf, ", ");
4801               gen_declaration (chain, buf);
4802               chain = TREE_CHAIN (chain);
4803             }
4804         }
4805     }
4806   else                          /* we have a unary selector */
4807     {
4808       strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4809     }
4810
4811   return buf;
4812 }
4813
4814 void
4815 gen_prototype (fp, decl)
4816      FILE *fp;
4817      tree decl;
4818 {
4819   /* we have a function definition - generate prototype */
4820   bzero (errbuf, BUFSIZE);
4821   gen_declaration (decl, errbuf);
4822   fprintf (fp, "%s;\n", errbuf);
4823 }
4824 /*
4825  *  debug info...
4826  */
4827 static void
4828 dump_interface (fp, chain)
4829      FILE *fp;
4830      tree chain;
4831 {
4832   char *buf = (char *)xmalloc (256);
4833   char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
4834   tree ivar_decls = CLASS_RAW_IVARS (chain);
4835   tree nst_methods = CLASS_NST_METHODS (chain);
4836   tree cls_methods = CLASS_CLS_METHODS (chain);
4837
4838   fprintf (fp, "\n@interface %s", my_name);
4839
4840   if (CLASS_SUPER_NAME (chain))
4841     {
4842       char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
4843       fprintf (fp, " : %s\n", super_name);
4844     }
4845   else
4846     fprintf (fp, "\n");
4847
4848   if (ivar_decls)
4849     {
4850       fprintf (fp, "{\n");
4851       do
4852         {
4853           bzero (buf, 256);
4854           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
4855           ivar_decls = TREE_CHAIN (ivar_decls);
4856         }
4857       while (ivar_decls);
4858       fprintf (fp, "}\n");
4859     }
4860
4861   while (nst_methods)
4862     {
4863       bzero (buf, 256);
4864       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
4865       nst_methods = TREE_CHAIN (nst_methods);
4866     }
4867
4868   while (cls_methods)
4869     {
4870       bzero (buf, 256);
4871       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
4872       cls_methods = TREE_CHAIN (cls_methods);
4873     }
4874   fprintf (fp, "\n@end");
4875 }
4876
4877 void
4878 init_objc ()
4879 {
4880   /* Add the special tree codes of Objective C to the tables.  */
4881
4882   gcc_obstack_init (&util_obstack);
4883   util_firstobj = (char *) obstack_finish (&util_obstack);
4884
4885   tree_code_type
4886     = (char **) realloc (tree_code_type,
4887                          sizeof (char *) * LAST_OBJC_TREE_CODE);
4888   tree_code_length
4889     = (int *) realloc (tree_code_length,
4890                        sizeof (int) * LAST_OBJC_TREE_CODE);
4891   tree_code_name
4892     = (char **) realloc (tree_code_name,
4893                          sizeof (char *) * LAST_OBJC_TREE_CODE);
4894   bcopy (objc_tree_code_type,
4895          tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
4896          (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4897           * sizeof (char *)));
4898   bcopy (objc_tree_code_length,
4899          tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
4900          (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4901           * sizeof (int)));
4902   bcopy (objc_tree_code_name,
4903          tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
4904          (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4905           * sizeof (char *)));
4906
4907   errbuf = (char *)xmalloc (BUFSIZE);
4908   hash_init ();
4909   synth_module_prologue ();
4910 }
4911 \f
4912 void
4913 finish_objc ()
4914 {
4915   struct imp_entry *impent;
4916   tree chain;
4917
4918   generate_forward_declaration_to_string_table ();
4919
4920 #ifdef OBJC_PROLOGUE
4921   OBJC_PROLOGUE;
4922 #endif
4923
4924   if (implementation_context || sel_refdef_chain)
4925     generate_objc_symtab_decl ();
4926
4927   for (impent = imp_list; impent; impent = impent->next)
4928     {
4929       implementation_context = impent->imp_context;
4930       implementation_template = impent->imp_template;
4931
4932       _OBJC_CLASS_decl = impent->class_decl;
4933       _OBJC_METACLASS_decl = impent->meta_decl;
4934
4935       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
4936         {
4937           /* all of the following reference the string pool...  */
4938           generate_ivar_lists ();
4939           generate_dispatch_tables ();
4940           generate_shared_structures ();
4941         }
4942       else
4943         {
4944           generate_dispatch_tables ();
4945           generate_category (implementation_context);
4946         }
4947     }
4948
4949   if (sel_ref_chain)
4950     build_selector_translation_table ();
4951
4952   if (implementation_context || sel_refdef_chain)
4953     {
4954       /* Arrange for Objc data structures to be initialized at run time.  */
4955
4956       char *init_name = build_module_descriptor ();
4957       if (init_name)
4958         assemble_constructor (init_name);
4959     }
4960
4961   /* dump the string table last */
4962
4963   if (sel_refdef_chain)
4964     {
4965       build_message_selector_pool ();
4966     }
4967
4968   /* dump the class references...this forces the appropriate classes
4969      to be linked into the executable image, preserving unix archive
4970      semantics...this can be removed when we move to a more dynamically
4971      linked environment
4972      */
4973   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4974     handle_class_ref (chain);
4975
4976   for (impent = imp_list; impent; impent = impent->next)
4977     handle_impent (impent);
4978
4979 #if 0 /* If GAS has such a bug, let's fix it.  */
4980   /*** this fixes a gross bug in the assembler...it `expects' #APP to have
4981    *** a matching #NO_APP, or it crashes (sometimes). app_disable () will
4982    *** insure this is the case. 5/19/89, s.naroff.
4983    ***/
4984   if (cls_ref_chain || imp_list)
4985     app_disable ();
4986 #endif
4987
4988   if (flag_gen_declaration)
4989     {
4990       add_class (implementation_context);
4991       dump_interface (gen_declaration_file, implementation_context);
4992     }
4993   if (warn_selector)
4994     {
4995       int slot;
4996       
4997       /* Run through the selector hash tables and print a warning for any
4998          selector which has multiple methods. */
4999       
5000       for (slot = 0; slot < SIZEHASHTABLE; slot++)
5001         {
5002           hash hsh;
5003           
5004           for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
5005             {
5006               if (hsh->list)
5007                 {
5008                   tree meth = hsh->key;
5009                   char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5010                               ? '-' : '+';
5011                   attr loop;
5012               
5013                   warning ("potential selector conflict for method `%s'",
5014                            IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5015                   warn_with_method ("found", type, meth);
5016                   for (loop = hsh->list; loop; loop = loop->next)
5017                     warn_with_method ("found", type, loop->value);
5018                 }
5019             }
5020         }
5021     
5022       for (slot = 0; slot < SIZEHASHTABLE; slot++)
5023         {
5024           hash hsh;
5025           
5026           for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
5027             {
5028               if (hsh->list)
5029                 {
5030                   tree meth = hsh->key;
5031                   char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5032                               ? '-' : '+';
5033                   attr loop;
5034               
5035                   warning ("potential selector conflict for method `%s'",
5036                            IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5037                   warn_with_method ("found", type, meth);
5038                   for (loop = hsh->list; loop; loop = loop->next)
5039                     warn_with_method ("found", type, loop->value);
5040                 }
5041             }
5042         }
5043     }
5044 }
5045 \f
5046 /* Subroutines of finish_objc.  */
5047
5048 handle_class_ref (chain)
5049      tree chain;
5050 {
5051   tree decl;
5052   char *string
5053     = (char *) alloca (strlen (IDENTIFIER_POINTER (TREE_VALUE (chain))) + 30);
5054
5055   sprintf (string, ".objc_class_name_%s",
5056            IDENTIFIER_POINTER (TREE_VALUE (chain)));
5057
5058   /* Make a decl for this name, so we can use its address in a tree.  */
5059   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
5060   DECL_EXTERNAL (decl) = 1;
5061   TREE_PUBLIC (decl) = 1;
5062
5063   pushdecl (decl);
5064   rest_of_decl_compilation (decl, 0, 0, 0);
5065
5066   /* Make following constant read-only (why not)?  */
5067   text_section ();
5068
5069   /* Output a constant to reference this address.  */
5070   output_constant (build1 (ADDR_EXPR, string_type_node, decl),
5071                    int_size_in_bytes (string_type_node));
5072 }
5073
5074 handle_impent (impent)
5075      struct imp_entry *impent;
5076 {
5077   implementation_context = impent->imp_context;
5078   implementation_template = impent->imp_template;
5079
5080   if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
5081     {
5082       char *string
5083         = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))) + 30);
5084
5085       sprintf (string, ".objc_class_name_%s",
5086                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
5087       assemble_global (string);
5088       assemble_label (string);
5089     }
5090   else if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
5091     {
5092       char *string
5093         = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)))
5094                            + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)))
5095                            + 30);
5096
5097       /* Do the same for categories.  Even though no references to these
5098           symbols are generated automatically by the compiler, it gives
5099           you a handle to pull them into an archive by hand. */
5100       sprintf (string, ".objc_category_name_%s_%s",
5101                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
5102                IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
5103       assemble_global (string);
5104       assemble_label (string);
5105     }
5106 }
5107 \f
5108 #ifdef DEBUG
5109
5110 static void
5111 objc_debug (fp)
5112      FILE *fp;
5113 {
5114   char *buf = (char *)xmalloc (256);
5115
5116   {                             /* dump function prototypes */
5117     tree loop = _OBJC_MODULES_decl;
5118
5119     fprintf (fp, "\n\nfunction prototypes:\n");
5120     while (loop)
5121       {
5122         if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
5123           {
5124             /* we have a function definition - generate prototype */
5125             bzero (errbuf, BUFSIZE);
5126             gen_declaration (loop, errbuf);
5127             fprintf (fp, "%s;\n", errbuf);
5128           }
5129         loop = TREE_CHAIN (loop);
5130       }
5131   }
5132   {                             /* dump global chains */
5133     tree loop;
5134     int i, index = 0, offset = 0;
5135     hash hashlist;
5136
5137     for (i = 0; i < SIZEHASHTABLE; i++)
5138       {
5139         if (hashlist = nst_method_hash_list[i])
5140           {
5141             fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
5142             do
5143               {
5144                 bzero (buf, 256);
5145                 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
5146                 hashlist = hashlist->next;
5147               }
5148             while (hashlist);
5149           }
5150       }
5151     for (i = 0; i < SIZEHASHTABLE; i++)
5152       {
5153         if (hashlist = cls_method_hash_list[i])
5154           {
5155             fprintf (fp, "\n\ncls_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     fprintf (fp, "\nsel_refdef_chain:\n");
5166     for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
5167       {
5168         fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
5169                  IDENTIFIER_POINTER (TREE_VALUE (loop)));
5170         index++;
5171         /* add one for the '\0' character */
5172         offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
5173       }
5174     fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
5175   }
5176 }
5177 #endif
5178
5179 void
5180 print_lang_statistics ()
5181 {
5182 }