OSDN Git Service

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