xref: /openbsd-src/gnu/usr.bin/binutils/binutils/wrstabs.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
1c88b1d6cSniklas /* wrstabs.c -- Output stabs debugging information
2c074d1c9Sdrahn    Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003
3c074d1c9Sdrahn    Free Software Foundation, Inc.
4c88b1d6cSniklas    Written by Ian Lance Taylor <ian@cygnus.com>.
5c88b1d6cSniklas 
6c88b1d6cSniklas    This file is part of GNU Binutils.
7c88b1d6cSniklas 
8c88b1d6cSniklas    This program is free software; you can redistribute it and/or modify
9c88b1d6cSniklas    it under the terms of the GNU General Public License as published by
10c88b1d6cSniklas    the Free Software Foundation; either version 2 of the License, or
11c88b1d6cSniklas    (at your option) any later version.
12c88b1d6cSniklas 
13c88b1d6cSniklas    This program is distributed in the hope that it will be useful,
14c88b1d6cSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
15c88b1d6cSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16c88b1d6cSniklas    GNU General Public License for more details.
17c88b1d6cSniklas 
18c88b1d6cSniklas    You should have received a copy of the GNU General Public License
19c88b1d6cSniklas    along with this program; if not, write to the Free Software
20c88b1d6cSniklas    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21c88b1d6cSniklas    02111-1307, USA.  */
22c88b1d6cSniklas 
23c88b1d6cSniklas /* This file contains code which writes out stabs debugging
24c88b1d6cSniklas    information.  */
25c88b1d6cSniklas 
26c88b1d6cSniklas #include <stdio.h>
27c88b1d6cSniklas #include <assert.h>
28c88b1d6cSniklas 
29c88b1d6cSniklas #include "bfd.h"
30c88b1d6cSniklas #include "bucomm.h"
31c88b1d6cSniklas #include "libiberty.h"
32c074d1c9Sdrahn #include "safe-ctype.h"
33c88b1d6cSniklas #include "debug.h"
34c88b1d6cSniklas #include "budbg.h"
35c88b1d6cSniklas #include "aout/aout64.h"
36c88b1d6cSniklas #include "aout/stab_gnu.h"
37c88b1d6cSniklas 
38c88b1d6cSniklas /* The size of a stabs symbol.  This presumes 32 bit values.  */
39c88b1d6cSniklas 
40c88b1d6cSniklas #define STAB_SYMBOL_SIZE (12)
41c88b1d6cSniklas 
42c88b1d6cSniklas /* An entry in a string hash table.  */
43c88b1d6cSniklas 
44c88b1d6cSniklas struct string_hash_entry
45c88b1d6cSniklas {
46c88b1d6cSniklas   struct bfd_hash_entry root;
474361b62eSniklas   /* Next string in this table.  */
484361b62eSniklas   struct string_hash_entry *next;
49c88b1d6cSniklas   /* Index in string table.  */
50c88b1d6cSniklas   long index;
51c88b1d6cSniklas   /* Size of type if this is a typedef.  */
52c88b1d6cSniklas   unsigned int size;
53c88b1d6cSniklas };
54c88b1d6cSniklas 
55c88b1d6cSniklas /* A string hash table.  */
56c88b1d6cSniklas 
57c88b1d6cSniklas struct string_hash_table
58c88b1d6cSniklas {
59c88b1d6cSniklas   struct bfd_hash_table table;
60c88b1d6cSniklas };
61c88b1d6cSniklas 
62c88b1d6cSniklas /* The type stack.  Each element on the stack is a string.  */
63c88b1d6cSniklas 
64c88b1d6cSniklas struct stab_type_stack
65c88b1d6cSniklas {
66c88b1d6cSniklas   /* The next element on the stack.  */
67c88b1d6cSniklas   struct stab_type_stack *next;
68c88b1d6cSniklas   /* This element as a string.  */
69c88b1d6cSniklas   char *string;
70c88b1d6cSniklas   /* The type index of this element.  */
71c88b1d6cSniklas   long index;
72c88b1d6cSniklas   /* The size of the type.  */
73c88b1d6cSniklas   unsigned int size;
74c88b1d6cSniklas   /* Whether type string defines a new type.  */
75c074d1c9Sdrahn   bfd_boolean definition;
76c88b1d6cSniklas   /* String defining struct fields.  */
77c88b1d6cSniklas   char *fields;
78c88b1d6cSniklas   /* NULL terminated array of strings defining base classes for a
79c88b1d6cSniklas      class.  */
80c88b1d6cSniklas   char **baseclasses;
81c88b1d6cSniklas   /* String defining class methods.  */
82c88b1d6cSniklas   char *methods;
83c88b1d6cSniklas   /* String defining vtable pointer for a class.  */
84c88b1d6cSniklas   char *vtable;
85c88b1d6cSniklas };
86c88b1d6cSniklas 
87c88b1d6cSniklas /* This structure is used to keep track of type indices for tagged
88c88b1d6cSniklas    types.  */
89c88b1d6cSniklas 
90c88b1d6cSniklas struct stab_tag
91c88b1d6cSniklas {
92c88b1d6cSniklas   /* The type index.  */
93c88b1d6cSniklas   long index;
94c88b1d6cSniklas   /* The tag name.  */
95c88b1d6cSniklas   const char *tag;
96c88b1d6cSniklas   /* The kind of type.  This is set to DEBUG_KIND_ILLEGAL when the
97c88b1d6cSniklas      type is defined.  */
98c88b1d6cSniklas   enum debug_type_kind kind;
99c88b1d6cSniklas   /* The size of the struct.  */
100c88b1d6cSniklas   unsigned int size;
101c88b1d6cSniklas };
102c88b1d6cSniklas 
103c88b1d6cSniklas /* We remember various sorts of type indices.  They are not related,
104c88b1d6cSniklas    but, for convenience, we keep all the information in this
105c88b1d6cSniklas    structure.  */
106c88b1d6cSniklas 
107c88b1d6cSniklas struct stab_type_cache
108c88b1d6cSniklas {
109c88b1d6cSniklas   /* The void type index.  */
110c88b1d6cSniklas   long void_type;
111c88b1d6cSniklas   /* Signed integer type indices, indexed by size - 1.  */
112c88b1d6cSniklas   long signed_integer_types[8];
113c88b1d6cSniklas   /* Unsigned integer type indices, indexed by size - 1.  */
114c88b1d6cSniklas   long unsigned_integer_types[8];
115c88b1d6cSniklas   /* Floating point types, indexed by size - 1.  */
116c88b1d6cSniklas   long float_types[16];
117c88b1d6cSniklas   /* Pointers to types, indexed by the type index.  */
118c88b1d6cSniklas   long *pointer_types;
119c88b1d6cSniklas   size_t pointer_types_alloc;
120c88b1d6cSniklas   /* Functions returning types, indexed by the type index.  */
121c88b1d6cSniklas   long *function_types;
122c88b1d6cSniklas   size_t function_types_alloc;
123c88b1d6cSniklas   /* References to types, indexed by the type index.  */
124c88b1d6cSniklas   long *reference_types;
125c88b1d6cSniklas   size_t reference_types_alloc;
126c88b1d6cSniklas   /* Struct/union/class type indices, indexed by the struct id.  */
127c88b1d6cSniklas   struct stab_tag *struct_types;
128c88b1d6cSniklas   size_t struct_types_alloc;
129c88b1d6cSniklas };
130c88b1d6cSniklas 
131c88b1d6cSniklas /* This is the handle passed through debug_write.  */
132c88b1d6cSniklas 
133c88b1d6cSniklas struct stab_write_handle
134c88b1d6cSniklas {
135c88b1d6cSniklas   /* The BFD.  */
136c88b1d6cSniklas   bfd *abfd;
137c88b1d6cSniklas   /* This buffer holds the symbols.  */
138c88b1d6cSniklas   bfd_byte *symbols;
139c88b1d6cSniklas   size_t symbols_size;
140c88b1d6cSniklas   size_t symbols_alloc;
1414361b62eSniklas   /* This is a list of hash table entries for the strings.  */
1424361b62eSniklas   struct string_hash_entry *strings;
1434361b62eSniklas   /* The last string hash table entry.  */
1444361b62eSniklas   struct string_hash_entry *last_string;
1454361b62eSniklas   /* The size of the strings.  */
146c88b1d6cSniklas   size_t strings_size;
147c88b1d6cSniklas   /* This hash table eliminates duplicate strings.  */
148c88b1d6cSniklas   struct string_hash_table strhash;
149c88b1d6cSniklas   /* The type stack.  */
150c88b1d6cSniklas   struct stab_type_stack *type_stack;
151c88b1d6cSniklas   /* The next type index.  */
152c88b1d6cSniklas   long type_index;
153c88b1d6cSniklas   /* The type cache.  */
154c88b1d6cSniklas   struct stab_type_cache type_cache;
155c88b1d6cSniklas   /* A mapping from typedef names to type indices.  */
156c88b1d6cSniklas   struct string_hash_table typedef_hash;
157c88b1d6cSniklas   /* If this is not -1, it is the offset to the most recent N_SO
158c88b1d6cSniklas      symbol, and the value of that symbol needs to be set.  */
159c88b1d6cSniklas   long so_offset;
160c88b1d6cSniklas   /* If this is not -1, it is the offset to the most recent N_FUN
161c88b1d6cSniklas      symbol, and the value of that symbol needs to be set.  */
162c88b1d6cSniklas   long fun_offset;
163c88b1d6cSniklas   /* The last text section address seen.  */
164c88b1d6cSniklas   bfd_vma last_text_address;
165c88b1d6cSniklas   /* The block nesting depth.  */
166c88b1d6cSniklas   unsigned int nesting;
167c88b1d6cSniklas   /* The function address.  */
168c88b1d6cSniklas   bfd_vma fnaddr;
169c88b1d6cSniklas   /* A pending LBRAC symbol.  */
170c88b1d6cSniklas   bfd_vma pending_lbrac;
171c88b1d6cSniklas   /* The current line number file name.  */
172c88b1d6cSniklas   const char *lineno_filename;
173c88b1d6cSniklas };
174c88b1d6cSniklas 
175c88b1d6cSniklas static struct bfd_hash_entry *string_hash_newfunc
176*007c2a45Smiod   (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
177c074d1c9Sdrahn static bfd_boolean stab_write_symbol
178*007c2a45Smiod   (struct stab_write_handle *, int, int, bfd_vma, const char *);
179c074d1c9Sdrahn static bfd_boolean stab_push_string
180*007c2a45Smiod   (struct stab_write_handle *, const char *, long, bfd_boolean, unsigned int);
181c074d1c9Sdrahn static bfd_boolean stab_push_defined_type
182*007c2a45Smiod   (struct stab_write_handle *, long, unsigned int);
183*007c2a45Smiod static char *stab_pop_type (struct stab_write_handle *);
184c074d1c9Sdrahn static bfd_boolean stab_modify_type
185*007c2a45Smiod   (struct stab_write_handle *, int, unsigned int, long **, size_t *);
186c88b1d6cSniklas static long stab_get_struct_index
187*007c2a45Smiod   (struct stab_write_handle *, const char *, unsigned int,
188*007c2a45Smiod    enum debug_type_kind, unsigned int *);
189c074d1c9Sdrahn static bfd_boolean stab_class_method_var
190*007c2a45Smiod   (struct stab_write_handle *, const char *, enum debug_visibility,
191*007c2a45Smiod    bfd_boolean, bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean);
192*007c2a45Smiod static bfd_boolean stab_start_compilation_unit (void *, const char *);
193*007c2a45Smiod static bfd_boolean stab_start_source (void *, const char *);
194*007c2a45Smiod static bfd_boolean stab_empty_type (void *);
195*007c2a45Smiod static bfd_boolean stab_void_type (void *);
196*007c2a45Smiod static bfd_boolean stab_int_type (void *, unsigned int, bfd_boolean);
197*007c2a45Smiod static bfd_boolean stab_float_type (void *, unsigned int);
198*007c2a45Smiod static bfd_boolean stab_complex_type (void *, unsigned int);
199*007c2a45Smiod static bfd_boolean stab_bool_type (void *, unsigned int);
200c074d1c9Sdrahn static bfd_boolean stab_enum_type
201*007c2a45Smiod   (void *, const char *, const char **, bfd_signed_vma *);
202*007c2a45Smiod static bfd_boolean stab_pointer_type (void *);
203*007c2a45Smiod static bfd_boolean stab_function_type (void *, int, bfd_boolean);
204*007c2a45Smiod static bfd_boolean stab_reference_type (void *);
205*007c2a45Smiod static bfd_boolean stab_range_type (void *, bfd_signed_vma, bfd_signed_vma);
206c074d1c9Sdrahn static bfd_boolean stab_array_type
207*007c2a45Smiod   (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean);
208*007c2a45Smiod static bfd_boolean stab_set_type (void *, bfd_boolean);
209*007c2a45Smiod static bfd_boolean stab_offset_type (void *);
210*007c2a45Smiod static bfd_boolean stab_method_type (void *, bfd_boolean, int, bfd_boolean);
211*007c2a45Smiod static bfd_boolean stab_const_type (void *);
212*007c2a45Smiod static bfd_boolean stab_volatile_type (void *);
213c074d1c9Sdrahn static bfd_boolean stab_start_struct_type
214*007c2a45Smiod   (void *, const char *, unsigned int, bfd_boolean, unsigned int);
215c074d1c9Sdrahn static bfd_boolean stab_struct_field
216*007c2a45Smiod   (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
217*007c2a45Smiod static bfd_boolean stab_end_struct_type (void *);
218c074d1c9Sdrahn static bfd_boolean stab_start_class_type
219*007c2a45Smiod   (void *, const char *, unsigned int, bfd_boolean, unsigned int,
220*007c2a45Smiod    bfd_boolean, bfd_boolean);
221c074d1c9Sdrahn static bfd_boolean stab_class_static_member
222*007c2a45Smiod   (void *, const char *, const char *, enum debug_visibility);
223c074d1c9Sdrahn static bfd_boolean stab_class_baseclass
224*007c2a45Smiod   (void *, bfd_vma, bfd_boolean, enum debug_visibility);
225*007c2a45Smiod static bfd_boolean stab_class_start_method (void *, const char *);
226c074d1c9Sdrahn static bfd_boolean stab_class_method_variant
227*007c2a45Smiod   (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
228*007c2a45Smiod    bfd_vma, bfd_boolean);
229c074d1c9Sdrahn static bfd_boolean stab_class_static_method_variant
230*007c2a45Smiod   (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
231*007c2a45Smiod static bfd_boolean stab_class_end_method (void *);
232*007c2a45Smiod static bfd_boolean stab_end_class_type (void *);
233*007c2a45Smiod static bfd_boolean stab_typedef_type (void *, const char *);
234c074d1c9Sdrahn static bfd_boolean stab_tag_type
235*007c2a45Smiod   (void *, const char *, unsigned int, enum debug_type_kind);
236*007c2a45Smiod static bfd_boolean stab_typdef (void *, const char *);
237*007c2a45Smiod static bfd_boolean stab_tag (void *, const char *);
238*007c2a45Smiod static bfd_boolean stab_int_constant (void *, const char *, bfd_vma);
239*007c2a45Smiod static bfd_boolean stab_float_constant (void *, const char *, double);
240*007c2a45Smiod static bfd_boolean stab_typed_constant (void *, const char *, bfd_vma);
241c074d1c9Sdrahn static bfd_boolean stab_variable
242*007c2a45Smiod   (void *, const char *, enum debug_var_kind, bfd_vma);
243*007c2a45Smiod static bfd_boolean stab_start_function (void *, const char *, bfd_boolean);
244c074d1c9Sdrahn static bfd_boolean stab_function_parameter
245*007c2a45Smiod   (void *, const char *, enum debug_parm_kind, bfd_vma);
246*007c2a45Smiod static bfd_boolean stab_start_block (void *, bfd_vma);
247*007c2a45Smiod static bfd_boolean stab_end_block (void *, bfd_vma);
248*007c2a45Smiod static bfd_boolean stab_end_function (void *);
249*007c2a45Smiod static bfd_boolean stab_lineno (void *, const char *, unsigned long, bfd_vma);
250c88b1d6cSniklas 
251c88b1d6cSniklas static const struct debug_write_fns stab_fns =
252c88b1d6cSniklas {
253c88b1d6cSniklas   stab_start_compilation_unit,
254c88b1d6cSniklas   stab_start_source,
255c88b1d6cSniklas   stab_empty_type,
256c88b1d6cSniklas   stab_void_type,
257c88b1d6cSniklas   stab_int_type,
258c88b1d6cSniklas   stab_float_type,
259c88b1d6cSniklas   stab_complex_type,
260c88b1d6cSniklas   stab_bool_type,
261c88b1d6cSniklas   stab_enum_type,
262c88b1d6cSniklas   stab_pointer_type,
263c88b1d6cSniklas   stab_function_type,
264c88b1d6cSniklas   stab_reference_type,
265c88b1d6cSniklas   stab_range_type,
266c88b1d6cSniklas   stab_array_type,
267c88b1d6cSniklas   stab_set_type,
268c88b1d6cSniklas   stab_offset_type,
269c88b1d6cSniklas   stab_method_type,
270c88b1d6cSniklas   stab_const_type,
271c88b1d6cSniklas   stab_volatile_type,
272c88b1d6cSniklas   stab_start_struct_type,
273c88b1d6cSniklas   stab_struct_field,
274c88b1d6cSniklas   stab_end_struct_type,
275c88b1d6cSniklas   stab_start_class_type,
276c88b1d6cSniklas   stab_class_static_member,
277c88b1d6cSniklas   stab_class_baseclass,
278c88b1d6cSniklas   stab_class_start_method,
279c88b1d6cSniklas   stab_class_method_variant,
280c88b1d6cSniklas   stab_class_static_method_variant,
281c88b1d6cSniklas   stab_class_end_method,
282c88b1d6cSniklas   stab_end_class_type,
283c88b1d6cSniklas   stab_typedef_type,
284c88b1d6cSniklas   stab_tag_type,
285c88b1d6cSniklas   stab_typdef,
286c88b1d6cSniklas   stab_tag,
287c88b1d6cSniklas   stab_int_constant,
288c88b1d6cSniklas   stab_float_constant,
289c88b1d6cSniklas   stab_typed_constant,
290c88b1d6cSniklas   stab_variable,
291c88b1d6cSniklas   stab_start_function,
292c88b1d6cSniklas   stab_function_parameter,
293c88b1d6cSniklas   stab_start_block,
294c88b1d6cSniklas   stab_end_block,
295c88b1d6cSniklas   stab_end_function,
296c88b1d6cSniklas   stab_lineno
297c88b1d6cSniklas };
298c88b1d6cSniklas 
299c88b1d6cSniklas /* Routine to create an entry in a string hash table.  */
300c88b1d6cSniklas 
301c88b1d6cSniklas static struct bfd_hash_entry *
string_hash_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)302*007c2a45Smiod string_hash_newfunc (struct bfd_hash_entry *entry,
303*007c2a45Smiod 		     struct bfd_hash_table *table, const char *string)
304c88b1d6cSniklas {
305c88b1d6cSniklas   struct string_hash_entry *ret = (struct string_hash_entry *) entry;
306c88b1d6cSniklas 
307c88b1d6cSniklas   /* Allocate the structure if it has not already been allocated by a
308c88b1d6cSniklas      subclass.  */
309c88b1d6cSniklas   if (ret == (struct string_hash_entry *) NULL)
310c88b1d6cSniklas     ret = ((struct string_hash_entry *)
311c88b1d6cSniklas 	   bfd_hash_allocate (table, sizeof (struct string_hash_entry)));
312c88b1d6cSniklas   if (ret == (struct string_hash_entry *) NULL)
313c88b1d6cSniklas     return NULL;
314c88b1d6cSniklas 
315c88b1d6cSniklas   /* Call the allocation method of the superclass.  */
316c88b1d6cSniklas   ret = ((struct string_hash_entry *)
317c88b1d6cSniklas 	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
318c88b1d6cSniklas 
319c88b1d6cSniklas   if (ret)
320c88b1d6cSniklas     {
321c88b1d6cSniklas       /* Initialize the local fields.  */
3224361b62eSniklas       ret->next = NULL;
323c88b1d6cSniklas       ret->index = -1;
324c88b1d6cSniklas       ret->size = 0;
325c88b1d6cSniklas     }
326c88b1d6cSniklas 
327c88b1d6cSniklas   return (struct bfd_hash_entry *) ret;
328c88b1d6cSniklas }
329c88b1d6cSniklas 
330c88b1d6cSniklas /* Look up an entry in a string hash table.  */
331c88b1d6cSniklas 
332c88b1d6cSniklas #define string_hash_lookup(t, string, create, copy) \
333c88b1d6cSniklas   ((struct string_hash_entry *) \
334c88b1d6cSniklas    bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
335c88b1d6cSniklas 
336c88b1d6cSniklas /* Add a symbol to the stabs debugging information we are building.  */
337c88b1d6cSniklas 
338c074d1c9Sdrahn static bfd_boolean
stab_write_symbol(struct stab_write_handle * info,int type,int desc,bfd_vma value,const char * string)339*007c2a45Smiod stab_write_symbol (struct stab_write_handle *info, int type, int desc,
340*007c2a45Smiod 		   bfd_vma value, const char *string)
341c88b1d6cSniklas {
342c88b1d6cSniklas   bfd_size_type strx;
343c88b1d6cSniklas   bfd_byte sym[STAB_SYMBOL_SIZE];
344c88b1d6cSniklas 
345c88b1d6cSniklas   if (string == NULL)
346c88b1d6cSniklas     strx = 0;
347c88b1d6cSniklas   else
348c88b1d6cSniklas     {
349c88b1d6cSniklas       struct string_hash_entry *h;
350c88b1d6cSniklas 
351c074d1c9Sdrahn       h = string_hash_lookup (&info->strhash, string, TRUE, TRUE);
352c88b1d6cSniklas       if (h == NULL)
353c88b1d6cSniklas 	{
354b305b0f1Sespie 	  non_fatal (_("string_hash_lookup failed: %s"),
355c88b1d6cSniklas 		     bfd_errmsg (bfd_get_error ()));
356c074d1c9Sdrahn 	  return FALSE;
357c88b1d6cSniklas 	}
358c88b1d6cSniklas       if (h->index != -1)
359c88b1d6cSniklas 	strx = h->index;
360c88b1d6cSniklas       else
361c88b1d6cSniklas 	{
362c88b1d6cSniklas 	  strx = info->strings_size;
363c88b1d6cSniklas 	  h->index = strx;
3644361b62eSniklas 	  if (info->last_string == NULL)
3654361b62eSniklas 	    info->strings = h;
3664361b62eSniklas 	  else
3674361b62eSniklas 	    info->last_string->next = h;
3684361b62eSniklas 	  info->last_string = h;
3694361b62eSniklas 	  info->strings_size += strlen (string) + 1;
370c88b1d6cSniklas 	}
371c88b1d6cSniklas     }
372c88b1d6cSniklas 
373c88b1d6cSniklas   /* This presumes 32 bit values.  */
374c88b1d6cSniklas   bfd_put_32 (info->abfd, strx, sym);
375c88b1d6cSniklas   bfd_put_8 (info->abfd, type, sym + 4);
376c88b1d6cSniklas   bfd_put_8 (info->abfd, 0, sym + 5);
377c88b1d6cSniklas   bfd_put_16 (info->abfd, desc, sym + 6);
378c88b1d6cSniklas   bfd_put_32 (info->abfd, value, sym + 8);
379c88b1d6cSniklas 
380c88b1d6cSniklas   if (info->symbols_size + STAB_SYMBOL_SIZE > info->symbols_alloc)
381c88b1d6cSniklas     {
382c88b1d6cSniklas       info->symbols_alloc *= 2;
383c88b1d6cSniklas       info->symbols = (bfd_byte *) xrealloc (info->symbols,
384c88b1d6cSniklas 					     info->symbols_alloc);
385c88b1d6cSniklas     }
386c88b1d6cSniklas 
387c88b1d6cSniklas   memcpy (info->symbols + info->symbols_size, sym, STAB_SYMBOL_SIZE);
388c88b1d6cSniklas 
389c88b1d6cSniklas   info->symbols_size += STAB_SYMBOL_SIZE;
390c88b1d6cSniklas 
391c074d1c9Sdrahn   return TRUE;
392c88b1d6cSniklas }
393c88b1d6cSniklas 
394c88b1d6cSniklas /* Push a string on to the type stack.  */
395c88b1d6cSniklas 
396c074d1c9Sdrahn static bfd_boolean
stab_push_string(struct stab_write_handle * info,const char * string,long index,bfd_boolean definition,unsigned int size)397*007c2a45Smiod stab_push_string (struct stab_write_handle *info, const char *string,
398*007c2a45Smiod 		  long index, bfd_boolean definition, unsigned int size)
399c88b1d6cSniklas {
400c88b1d6cSniklas   struct stab_type_stack *s;
401c88b1d6cSniklas 
402c88b1d6cSniklas   s = (struct stab_type_stack *) xmalloc (sizeof *s);
403c88b1d6cSniklas   s->string = xstrdup (string);
404c88b1d6cSniklas   s->index = index;
405c88b1d6cSniklas   s->definition = definition;
406c88b1d6cSniklas   s->size = size;
407c88b1d6cSniklas 
408c88b1d6cSniklas   s->fields = NULL;
409c88b1d6cSniklas   s->baseclasses = NULL;
410c88b1d6cSniklas   s->methods = NULL;
411c88b1d6cSniklas   s->vtable = NULL;
412c88b1d6cSniklas 
413c88b1d6cSniklas   s->next = info->type_stack;
414c88b1d6cSniklas   info->type_stack = s;
415c88b1d6cSniklas 
416c074d1c9Sdrahn   return TRUE;
417c88b1d6cSniklas }
418c88b1d6cSniklas 
419c88b1d6cSniklas /* Push a type index which has already been defined.  */
420c88b1d6cSniklas 
421c074d1c9Sdrahn static bfd_boolean
stab_push_defined_type(struct stab_write_handle * info,long index,unsigned int size)422*007c2a45Smiod stab_push_defined_type (struct stab_write_handle *info, long index,
423*007c2a45Smiod 			unsigned int size)
424c88b1d6cSniklas {
425c88b1d6cSniklas   char buf[20];
426c88b1d6cSniklas 
427c88b1d6cSniklas   sprintf (buf, "%ld", index);
428c074d1c9Sdrahn   return stab_push_string (info, buf, index, FALSE, size);
429c88b1d6cSniklas }
430c88b1d6cSniklas 
431c88b1d6cSniklas /* Pop a type off the type stack.  The caller is responsible for
432c88b1d6cSniklas    freeing the string.  */
433c88b1d6cSniklas 
434c88b1d6cSniklas static char *
stab_pop_type(struct stab_write_handle * info)435*007c2a45Smiod stab_pop_type (struct stab_write_handle *info)
436c88b1d6cSniklas {
437c88b1d6cSniklas   struct stab_type_stack *s;
438c88b1d6cSniklas   char *ret;
439c88b1d6cSniklas 
440c88b1d6cSniklas   s = info->type_stack;
441c88b1d6cSniklas   assert (s != NULL);
442c88b1d6cSniklas 
443c88b1d6cSniklas   info->type_stack = s->next;
444c88b1d6cSniklas 
445c88b1d6cSniklas   ret = s->string;
446c88b1d6cSniklas 
447c88b1d6cSniklas   free (s);
448c88b1d6cSniklas 
449c88b1d6cSniklas   return ret;
450c88b1d6cSniklas }
451c88b1d6cSniklas 
452c88b1d6cSniklas /* The general routine to write out stabs in sections debugging
453c88b1d6cSniklas    information.  This accumulates the stabs symbols and the strings in
454c88b1d6cSniklas    two obstacks.  We can't easily write out the information as we go
455c88b1d6cSniklas    along, because we need to know the section sizes before we can
456c88b1d6cSniklas    write out the section contents.  ABFD is the BFD and DHANDLE is the
457c88b1d6cSniklas    handle for the debugging information.  This sets *PSYMS to point to
458c88b1d6cSniklas    the symbols, *PSYMSIZE the size of the symbols, *PSTRINGS to the
459c88b1d6cSniklas    strings, and *PSTRINGSIZE to the size of the strings.  */
460c88b1d6cSniklas 
461c074d1c9Sdrahn bfd_boolean
write_stabs_in_sections_debugging_info(bfd * abfd,void * dhandle,bfd_byte ** psyms,bfd_size_type * psymsize,bfd_byte ** pstrings,bfd_size_type * pstringsize)462*007c2a45Smiod write_stabs_in_sections_debugging_info (bfd *abfd, void *dhandle,
463*007c2a45Smiod 					bfd_byte **psyms,
464*007c2a45Smiod 					bfd_size_type *psymsize,
465*007c2a45Smiod 					bfd_byte **pstrings,
466*007c2a45Smiod 					bfd_size_type *pstringsize)
467c88b1d6cSniklas {
468c88b1d6cSniklas   struct stab_write_handle info;
4694361b62eSniklas   struct string_hash_entry *h;
4704361b62eSniklas   bfd_byte *p;
471c88b1d6cSniklas 
472c88b1d6cSniklas   info.abfd = abfd;
473c88b1d6cSniklas 
474c88b1d6cSniklas   info.symbols_size = 0;
475c88b1d6cSniklas   info.symbols_alloc = 500;
476c88b1d6cSniklas   info.symbols = (bfd_byte *) xmalloc (info.symbols_alloc);
477c88b1d6cSniklas 
4784361b62eSniklas   info.strings = NULL;
4794361b62eSniklas   info.last_string = NULL;
4804361b62eSniklas   /* Reserve 1 byte for a null byte.  */
481c88b1d6cSniklas   info.strings_size = 1;
482c88b1d6cSniklas 
483c88b1d6cSniklas   if (! bfd_hash_table_init (&info.strhash.table, string_hash_newfunc)
484c88b1d6cSniklas       || ! bfd_hash_table_init (&info.typedef_hash.table, string_hash_newfunc))
485c88b1d6cSniklas     {
486b305b0f1Sespie       non_fatal ("bfd_hash_table_init_failed: %s",
487c88b1d6cSniklas 		 bfd_errmsg (bfd_get_error ()));
488c074d1c9Sdrahn       return FALSE;
489c88b1d6cSniklas     }
490c88b1d6cSniklas 
491c88b1d6cSniklas   info.type_stack = NULL;
492c88b1d6cSniklas   info.type_index = 1;
493c88b1d6cSniklas   memset (&info.type_cache, 0, sizeof info.type_cache);
494c88b1d6cSniklas   info.so_offset = -1;
495c88b1d6cSniklas   info.fun_offset = -1;
496c88b1d6cSniklas   info.last_text_address = 0;
497c88b1d6cSniklas   info.nesting = 0;
498c88b1d6cSniklas   info.fnaddr = 0;
499c88b1d6cSniklas   info.pending_lbrac = (bfd_vma) -1;
500c88b1d6cSniklas 
501c88b1d6cSniklas   /* The initial symbol holds the string size.  */
502c88b1d6cSniklas   if (! stab_write_symbol (&info, 0, 0, 0, (const char *) NULL))
503c074d1c9Sdrahn     return FALSE;
504c88b1d6cSniklas 
505c88b1d6cSniklas   /* Output an initial N_SO symbol.  */
506c88b1d6cSniklas   info.so_offset = info.symbols_size;
507c88b1d6cSniklas   if (! stab_write_symbol (&info, N_SO, 0, 0, bfd_get_filename (abfd)))
508c074d1c9Sdrahn     return FALSE;
509c88b1d6cSniklas 
510*007c2a45Smiod   if (! debug_write (dhandle, &stab_fns, (void *) &info))
511c074d1c9Sdrahn     return FALSE;
512c88b1d6cSniklas 
513c88b1d6cSniklas   assert (info.pending_lbrac == (bfd_vma) -1);
514c88b1d6cSniklas 
515c88b1d6cSniklas   /* Output a trailing N_SO.  */
516c88b1d6cSniklas   if (! stab_write_symbol (&info, N_SO, 0, info.last_text_address,
517c88b1d6cSniklas 			   (const char *) NULL))
518c074d1c9Sdrahn     return FALSE;
519c88b1d6cSniklas 
520c88b1d6cSniklas   /* Put the string size in the initial symbol.  */
521c88b1d6cSniklas   bfd_put_32 (abfd, info.strings_size, info.symbols + 8);
522c88b1d6cSniklas 
523c88b1d6cSniklas   *psyms = info.symbols;
524c88b1d6cSniklas   *psymsize = info.symbols_size;
525c88b1d6cSniklas 
526c88b1d6cSniklas   *pstringsize = info.strings_size;
5274361b62eSniklas   *pstrings = (bfd_byte *) xmalloc (info.strings_size);
5284361b62eSniklas 
5294361b62eSniklas   p = *pstrings;
5304361b62eSniklas   *p++ = '\0';
5314361b62eSniklas   for (h = info.strings; h != NULL; h = h->next)
5324361b62eSniklas     {
533b305b0f1Sespie       strcpy ((char *) p, h->root.string);
534b305b0f1Sespie       p += strlen ((char *) p) + 1;
5354361b62eSniklas     }
536c88b1d6cSniklas 
537c074d1c9Sdrahn   return TRUE;
538c88b1d6cSniklas }
539c88b1d6cSniklas 
540c88b1d6cSniklas /* Start writing out information for a compilation unit.  */
541c88b1d6cSniklas 
542c074d1c9Sdrahn static bfd_boolean
stab_start_compilation_unit(void * p,const char * filename)543*007c2a45Smiod stab_start_compilation_unit (void *p, const char *filename)
544c88b1d6cSniklas {
545c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
546c88b1d6cSniklas 
547c88b1d6cSniklas   /* We would normally output an N_SO symbol here.  However, that
548c88b1d6cSniklas      would force us to reset all of our type information.  I think we
549c88b1d6cSniklas      will be better off just outputting an N_SOL symbol, and not
550c88b1d6cSniklas      worrying about splitting information between files.  */
551c88b1d6cSniklas 
552c88b1d6cSniklas   info->lineno_filename = filename;
553c88b1d6cSniklas 
554c88b1d6cSniklas   return stab_write_symbol (info, N_SOL, 0, 0, filename);
555c88b1d6cSniklas }
556c88b1d6cSniklas 
557c88b1d6cSniklas /* Start writing out information for a particular source file.  */
558c88b1d6cSniklas 
559c074d1c9Sdrahn static bfd_boolean
stab_start_source(void * p,const char * filename)560*007c2a45Smiod stab_start_source (void *p, const char *filename)
561c88b1d6cSniklas {
562c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
563c88b1d6cSniklas 
564c88b1d6cSniklas   /* FIXME: The symbol's value is supposed to be the text section
565c88b1d6cSniklas      address.  However, we would have to fill it in later, and gdb
566c88b1d6cSniklas      doesn't care, so we don't bother with it.  */
567c88b1d6cSniklas 
568c88b1d6cSniklas   info->lineno_filename = filename;
569c88b1d6cSniklas 
570c88b1d6cSniklas   return stab_write_symbol (info, N_SOL, 0, 0, filename);
571c88b1d6cSniklas }
572c88b1d6cSniklas 
573c88b1d6cSniklas /* Push an empty type.  This shouldn't normally happen.  We just use a
574c88b1d6cSniklas    void type.  */
575c88b1d6cSniklas 
576c074d1c9Sdrahn static bfd_boolean
stab_empty_type(void * p)577*007c2a45Smiod stab_empty_type (void *p)
578c88b1d6cSniklas {
579c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
580c88b1d6cSniklas 
581c88b1d6cSniklas   /* We don't call stab_void_type if the type is not yet defined,
582c88b1d6cSniklas      because that might screw up the typedef.  */
583c88b1d6cSniklas 
584c88b1d6cSniklas   if (info->type_cache.void_type != 0)
585c88b1d6cSniklas     return stab_push_defined_type (info, info->type_cache.void_type, 0);
586c88b1d6cSniklas   else
587c88b1d6cSniklas     {
588c88b1d6cSniklas       long index;
589c88b1d6cSniklas       char buf[40];
590c88b1d6cSniklas 
591c88b1d6cSniklas       index = info->type_index;
592c88b1d6cSniklas       ++info->type_index;
593c88b1d6cSniklas 
594c88b1d6cSniklas       sprintf (buf, "%ld=%ld", index, index);
595c88b1d6cSniklas 
596c074d1c9Sdrahn       return stab_push_string (info, buf, index, FALSE, 0);
597c88b1d6cSniklas     }
598c88b1d6cSniklas }
599c88b1d6cSniklas 
600c88b1d6cSniklas /* Push a void type.  */
601c88b1d6cSniklas 
602c074d1c9Sdrahn static bfd_boolean
stab_void_type(void * p)603*007c2a45Smiod stab_void_type (void *p)
604c88b1d6cSniklas {
605c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
606c88b1d6cSniklas 
607c88b1d6cSniklas   if (info->type_cache.void_type != 0)
608c88b1d6cSniklas     return stab_push_defined_type (info, info->type_cache.void_type, 0);
609c88b1d6cSniklas   else
610c88b1d6cSniklas     {
611c88b1d6cSniklas       long index;
612c88b1d6cSniklas       char buf[40];
613c88b1d6cSniklas 
614c88b1d6cSniklas       index = info->type_index;
615c88b1d6cSniklas       ++info->type_index;
616c88b1d6cSniklas 
617c88b1d6cSniklas       info->type_cache.void_type = index;
618c88b1d6cSniklas 
619c88b1d6cSniklas       sprintf (buf, "%ld=%ld", index, index);
620c88b1d6cSniklas 
621c074d1c9Sdrahn       return stab_push_string (info, buf, index, TRUE, 0);
622c88b1d6cSniklas     }
623c88b1d6cSniklas }
624c88b1d6cSniklas 
625c88b1d6cSniklas /* Push an integer type.  */
626c88b1d6cSniklas 
627c074d1c9Sdrahn static bfd_boolean
stab_int_type(void * p,unsigned int size,bfd_boolean unsignedp)628*007c2a45Smiod stab_int_type (void *p, unsigned int size, bfd_boolean unsignedp)
629c88b1d6cSniklas {
630c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
631c88b1d6cSniklas   long *cache;
632c88b1d6cSniklas 
633c88b1d6cSniklas   if (size <= 0 || (size > sizeof (long) && size != 8))
634c88b1d6cSniklas     {
635b305b0f1Sespie       non_fatal (_("stab_int_type: bad size %u"), size);
636c074d1c9Sdrahn       return FALSE;
637c88b1d6cSniklas     }
638c88b1d6cSniklas 
639c88b1d6cSniklas   if (unsignedp)
640c88b1d6cSniklas     cache = info->type_cache.signed_integer_types;
641c88b1d6cSniklas   else
642c88b1d6cSniklas     cache = info->type_cache.unsigned_integer_types;
643c88b1d6cSniklas 
644c88b1d6cSniklas   if (cache[size - 1] != 0)
645c88b1d6cSniklas     return stab_push_defined_type (info, cache[size - 1], size);
646c88b1d6cSniklas   else
647c88b1d6cSniklas     {
648c88b1d6cSniklas       long index;
649c88b1d6cSniklas       char buf[100];
650c88b1d6cSniklas 
651c88b1d6cSniklas       index = info->type_index;
652c88b1d6cSniklas       ++info->type_index;
653c88b1d6cSniklas 
654c88b1d6cSniklas       cache[size - 1] = index;
655c88b1d6cSniklas 
656c88b1d6cSniklas       sprintf (buf, "%ld=r%ld;", index, index);
657c88b1d6cSniklas       if (unsignedp)
658c88b1d6cSniklas 	{
659c88b1d6cSniklas 	  strcat (buf, "0;");
660c88b1d6cSniklas 	  if (size < sizeof (long))
661c88b1d6cSniklas 	    sprintf (buf + strlen (buf), "%ld;", ((long) 1 << (size * 8)) - 1);
662c88b1d6cSniklas 	  else if (size == sizeof (long))
663c88b1d6cSniklas 	    strcat (buf, "-1;");
664c88b1d6cSniklas 	  else if (size == 8)
665c88b1d6cSniklas 	    strcat (buf, "01777777777777777777777;");
666c88b1d6cSniklas 	  else
667c88b1d6cSniklas 	    abort ();
668c88b1d6cSniklas 	}
669c88b1d6cSniklas       else
670c88b1d6cSniklas 	{
671c88b1d6cSniklas 	  if (size <= sizeof (long))
672c88b1d6cSniklas 	    sprintf (buf + strlen (buf), "%ld;%ld;",
673c88b1d6cSniklas 		     (long) - ((unsigned long) 1 << (size * 8 - 1)),
674c88b1d6cSniklas 		     (long) (((unsigned long) 1 << (size * 8 - 1)) - 1));
675c88b1d6cSniklas 	  else if (size == 8)
676c88b1d6cSniklas 	    strcat (buf, "01000000000000000000000;0777777777777777777777;");
677c88b1d6cSniklas 	  else
678c88b1d6cSniklas 	    abort ();
679c88b1d6cSniklas 	}
680c88b1d6cSniklas 
681c074d1c9Sdrahn       return stab_push_string (info, buf, index, TRUE, size);
682c88b1d6cSniklas     }
683c88b1d6cSniklas }
684c88b1d6cSniklas 
685c88b1d6cSniklas /* Push a floating point type.  */
686c88b1d6cSniklas 
687c074d1c9Sdrahn static bfd_boolean
stab_float_type(void * p,unsigned int size)688*007c2a45Smiod stab_float_type (void *p, unsigned int size)
689c88b1d6cSniklas {
690c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
691c88b1d6cSniklas 
692c88b1d6cSniklas   if (size > 0
693c88b1d6cSniklas       && size - 1 < (sizeof info->type_cache.float_types
694c88b1d6cSniklas 		     / sizeof info->type_cache.float_types[0])
695c88b1d6cSniklas       && info->type_cache.float_types[size - 1] != 0)
696c88b1d6cSniklas     return stab_push_defined_type (info,
697c88b1d6cSniklas 				   info->type_cache.float_types[size - 1],
698c88b1d6cSniklas 				   size);
699c88b1d6cSniklas   else
700c88b1d6cSniklas     {
701c88b1d6cSniklas       long index;
702c88b1d6cSniklas       char *int_type;
703c88b1d6cSniklas       char buf[50];
704c88b1d6cSniklas 
705c88b1d6cSniklas       /* Floats are defined as a subrange of int.  */
706c074d1c9Sdrahn       if (! stab_int_type (info, 4, FALSE))
707c074d1c9Sdrahn 	return FALSE;
708c88b1d6cSniklas       int_type = stab_pop_type (info);
709c88b1d6cSniklas 
710c88b1d6cSniklas       index = info->type_index;
711c88b1d6cSniklas       ++info->type_index;
712c88b1d6cSniklas 
713c88b1d6cSniklas       if (size > 0
714c88b1d6cSniklas 	  && size - 1 < (sizeof info->type_cache.float_types
715c88b1d6cSniklas 			 / sizeof info->type_cache.float_types[0]))
716c88b1d6cSniklas 	info->type_cache.float_types[size - 1] = index;
717c88b1d6cSniklas 
718c88b1d6cSniklas       sprintf (buf, "%ld=r%s;%u;0;", index, int_type, size);
719c88b1d6cSniklas 
720c88b1d6cSniklas       free (int_type);
721c88b1d6cSniklas 
722c074d1c9Sdrahn       return stab_push_string (info, buf, index, TRUE, size);
723c88b1d6cSniklas     }
724c88b1d6cSniklas }
725c88b1d6cSniklas 
726c88b1d6cSniklas /* Push a complex type.  */
727c88b1d6cSniklas 
728c074d1c9Sdrahn static bfd_boolean
stab_complex_type(void * p,unsigned int size)729*007c2a45Smiod stab_complex_type (void *p, unsigned int size)
730c88b1d6cSniklas {
731c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
732c88b1d6cSniklas   char buf[50];
733c88b1d6cSniklas   long index;
734c88b1d6cSniklas 
735c88b1d6cSniklas   index = info->type_index;
736c88b1d6cSniklas   ++info->type_index;
737c88b1d6cSniklas 
738c88b1d6cSniklas   sprintf (buf, "%ld=r%ld;%u;0;", index, index, size);
739c88b1d6cSniklas 
740c074d1c9Sdrahn   return stab_push_string (info, buf, index, TRUE, size * 2);
741c88b1d6cSniklas }
742c88b1d6cSniklas 
743c074d1c9Sdrahn /* Push a bfd_boolean type.  We use an XCOFF predefined type, since gdb
744c88b1d6cSniklas    always recognizes them.  */
745c88b1d6cSniklas 
746c074d1c9Sdrahn static bfd_boolean
stab_bool_type(void * p,unsigned int size)747*007c2a45Smiod stab_bool_type (void *p, unsigned int size)
748c88b1d6cSniklas {
749c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
750c88b1d6cSniklas   long index;
751c88b1d6cSniklas 
752c88b1d6cSniklas   switch (size)
753c88b1d6cSniklas     {
754c88b1d6cSniklas     case 1:
755c88b1d6cSniklas       index = -21;
756c88b1d6cSniklas       break;
757c88b1d6cSniklas 
758c88b1d6cSniklas     case 2:
759c88b1d6cSniklas       index = -22;
760c88b1d6cSniklas       break;
761c88b1d6cSniklas 
762c88b1d6cSniklas     default:
763c88b1d6cSniklas     case 4:
764c88b1d6cSniklas       index = -16;
765c88b1d6cSniklas       break;
766c88b1d6cSniklas 
767c88b1d6cSniklas     case 8:
768c88b1d6cSniklas       index = -33;
769c88b1d6cSniklas       break;
770c88b1d6cSniklas     }
771c88b1d6cSniklas 
772c88b1d6cSniklas   return stab_push_defined_type (info, index, size);
773c88b1d6cSniklas }
774c88b1d6cSniklas 
775c88b1d6cSniklas /* Push an enum type.  */
776c88b1d6cSniklas 
777c074d1c9Sdrahn static bfd_boolean
stab_enum_type(void * p,const char * tag,const char ** names,bfd_signed_vma * vals)778*007c2a45Smiod stab_enum_type (void *p, const char *tag, const char **names,
779*007c2a45Smiod 		bfd_signed_vma *vals)
780c88b1d6cSniklas {
781c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
782c88b1d6cSniklas   size_t len;
783c88b1d6cSniklas   const char **pn;
784c88b1d6cSniklas   char *buf;
785c88b1d6cSniklas   long index = 0;
786c88b1d6cSniklas   bfd_signed_vma *pv;
787c88b1d6cSniklas 
788c88b1d6cSniklas   if (names == NULL)
789c88b1d6cSniklas     {
790c88b1d6cSniklas       assert (tag != NULL);
791c88b1d6cSniklas 
792c88b1d6cSniklas       buf = (char *) xmalloc (10 + strlen (tag));
793c88b1d6cSniklas       sprintf (buf, "xe%s:", tag);
794c88b1d6cSniklas       /* FIXME: The size is just a guess.  */
795c074d1c9Sdrahn       if (! stab_push_string (info, buf, 0, FALSE, 4))
796c074d1c9Sdrahn 	return FALSE;
797c88b1d6cSniklas       free (buf);
798c074d1c9Sdrahn       return TRUE;
799c88b1d6cSniklas     }
800c88b1d6cSniklas 
801c88b1d6cSniklas   len = 10;
802c88b1d6cSniklas   if (tag != NULL)
803c88b1d6cSniklas     len += strlen (tag);
804c88b1d6cSniklas   for (pn = names; *pn != NULL; pn++)
805c88b1d6cSniklas     len += strlen (*pn) + 20;
806c88b1d6cSniklas 
807c88b1d6cSniklas   buf = (char *) xmalloc (len);
808c88b1d6cSniklas 
809c88b1d6cSniklas   if (tag == NULL)
810c88b1d6cSniklas     strcpy (buf, "e");
811c88b1d6cSniklas   else
812c88b1d6cSniklas     {
813c88b1d6cSniklas       index = info->type_index;
814c88b1d6cSniklas       ++info->type_index;
815c88b1d6cSniklas       sprintf (buf, "%s:T%ld=e", tag, index);
816c88b1d6cSniklas     }
817c88b1d6cSniklas 
818c88b1d6cSniklas   for (pn = names, pv = vals; *pn != NULL; pn++, pv++)
819c88b1d6cSniklas     sprintf (buf + strlen (buf), "%s:%ld,", *pn, (long) *pv);
820c88b1d6cSniklas   strcat (buf, ";");
821c88b1d6cSniklas 
822c88b1d6cSniklas   if (tag == NULL)
823c88b1d6cSniklas     {
824c88b1d6cSniklas       /* FIXME: The size is just a guess.  */
825c074d1c9Sdrahn       if (! stab_push_string (info, buf, 0, FALSE, 4))
826c074d1c9Sdrahn 	return FALSE;
827c88b1d6cSniklas     }
828c88b1d6cSniklas   else
829c88b1d6cSniklas     {
830c88b1d6cSniklas       /* FIXME: The size is just a guess.  */
831c88b1d6cSniklas       if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)
832c88b1d6cSniklas 	  || ! stab_push_defined_type (info, index, 4))
833c074d1c9Sdrahn 	return FALSE;
834c88b1d6cSniklas     }
835c88b1d6cSniklas 
836c88b1d6cSniklas   free (buf);
837c88b1d6cSniklas 
838c074d1c9Sdrahn   return TRUE;
839c88b1d6cSniklas }
840c88b1d6cSniklas 
841c88b1d6cSniklas /* Push a modification of the top type on the stack.  Cache the
842c88b1d6cSniklas    results in CACHE and CACHE_ALLOC.  */
843c88b1d6cSniklas 
844c074d1c9Sdrahn static bfd_boolean
stab_modify_type(struct stab_write_handle * info,int mod,unsigned int size,long ** cache,size_t * cache_alloc)845*007c2a45Smiod stab_modify_type (struct stab_write_handle *info, int mod,
846*007c2a45Smiod 		  unsigned int size, long **cache, size_t *cache_alloc)
847c88b1d6cSniklas {
848c88b1d6cSniklas   long targindex;
849c88b1d6cSniklas   long index;
850c88b1d6cSniklas   char *s, *buf;
851c88b1d6cSniklas 
852c88b1d6cSniklas   assert (info->type_stack != NULL);
853c88b1d6cSniklas   targindex = info->type_stack->index;
854c88b1d6cSniklas 
855c88b1d6cSniklas   if (targindex <= 0
856c88b1d6cSniklas       || cache == NULL)
857c88b1d6cSniklas     {
858c074d1c9Sdrahn       bfd_boolean definition;
859c88b1d6cSniklas 
860c88b1d6cSniklas       /* Either the target type has no index, or we aren't caching
861c88b1d6cSniklas          this modifier.  Either way we have no way of recording the
862c88b1d6cSniklas          new type, so we don't bother to define one.  */
863c88b1d6cSniklas       definition = info->type_stack->definition;
864c88b1d6cSniklas       s = stab_pop_type (info);
865c88b1d6cSniklas       buf = (char *) xmalloc (strlen (s) + 2);
866c88b1d6cSniklas       sprintf (buf, "%c%s", mod, s);
867c88b1d6cSniklas       free (s);
868c88b1d6cSniklas       if (! stab_push_string (info, buf, 0, definition, size))
869c074d1c9Sdrahn 	return FALSE;
870c88b1d6cSniklas       free (buf);
871c88b1d6cSniklas     }
872c88b1d6cSniklas   else
873c88b1d6cSniklas     {
874b305b0f1Sespie       if ((size_t) targindex >= *cache_alloc)
875c88b1d6cSniklas 	{
876c88b1d6cSniklas 	  size_t alloc;
877c88b1d6cSniklas 
878c88b1d6cSniklas 	  alloc = *cache_alloc;
879c88b1d6cSniklas 	  if (alloc == 0)
880c88b1d6cSniklas 	    alloc = 10;
881b305b0f1Sespie 	  while ((size_t) targindex >= alloc)
882c88b1d6cSniklas 	    alloc *= 2;
883c88b1d6cSniklas 	  *cache = (long *) xrealloc (*cache, alloc * sizeof (long));
884c88b1d6cSniklas 	  memset (*cache + *cache_alloc, 0,
885c88b1d6cSniklas 		  (alloc - *cache_alloc) * sizeof (long));
886c88b1d6cSniklas 	  *cache_alloc = alloc;
887c88b1d6cSniklas 	}
888c88b1d6cSniklas 
889c88b1d6cSniklas       index = (*cache)[targindex];
8904361b62eSniklas       if (index != 0 && ! info->type_stack->definition)
891c88b1d6cSniklas 	{
8924361b62eSniklas 	  /* We have already defined a modification of this type, and
8934361b62eSniklas              the entry on the type stack is not a definition, so we
8944361b62eSniklas              can safely discard it (we may have a definition on the
8954361b62eSniklas              stack, even if we already defined a modification, if it
8964361b62eSniklas              is a struct which we did not define at the time it was
8974361b62eSniklas              referenced).  */
898c88b1d6cSniklas 	  free (stab_pop_type (info));
899c88b1d6cSniklas 	  if (! stab_push_defined_type (info, index, size))
900c074d1c9Sdrahn 	    return FALSE;
901c88b1d6cSniklas 	}
902c88b1d6cSniklas       else
903c88b1d6cSniklas 	{
904c88b1d6cSniklas 	  index = info->type_index;
905c88b1d6cSniklas 	  ++info->type_index;
906c88b1d6cSniklas 
907c88b1d6cSniklas 	  s = stab_pop_type (info);
908c88b1d6cSniklas 	  buf = (char *) xmalloc (strlen (s) + 20);
909c88b1d6cSniklas 	  sprintf (buf, "%ld=%c%s", index, mod, s);
910c88b1d6cSniklas 	  free (s);
911c88b1d6cSniklas 
912c88b1d6cSniklas 	  (*cache)[targindex] = index;
913c88b1d6cSniklas 
914c074d1c9Sdrahn 	  if (! stab_push_string (info, buf, index, TRUE, size))
915c074d1c9Sdrahn 	    return FALSE;
916c88b1d6cSniklas 
917c88b1d6cSniklas 	  free (buf);
918c88b1d6cSniklas 	}
919c88b1d6cSniklas     }
920c88b1d6cSniklas 
921c074d1c9Sdrahn   return TRUE;
922c88b1d6cSniklas }
923c88b1d6cSniklas 
924c88b1d6cSniklas /* Push a pointer type.  */
925c88b1d6cSniklas 
926c074d1c9Sdrahn static bfd_boolean
stab_pointer_type(void * p)927*007c2a45Smiod stab_pointer_type (void *p)
928c88b1d6cSniklas {
929c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
930c88b1d6cSniklas 
931c88b1d6cSniklas   /* FIXME: The size should depend upon the architecture.  */
932c88b1d6cSniklas   return stab_modify_type (info, '*', 4, &info->type_cache.pointer_types,
933c88b1d6cSniklas 			   &info->type_cache.pointer_types_alloc);
934c88b1d6cSniklas }
935c88b1d6cSniklas 
936c88b1d6cSniklas /* Push a function type.  */
937c88b1d6cSniklas 
938c074d1c9Sdrahn static bfd_boolean
stab_function_type(void * p,int argcount,bfd_boolean varargs ATTRIBUTE_UNUSED)939*007c2a45Smiod stab_function_type (void *p, int argcount,
940*007c2a45Smiod 		    bfd_boolean varargs ATTRIBUTE_UNUSED)
941c88b1d6cSniklas {
942c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
943c88b1d6cSniklas   int i;
944c88b1d6cSniklas 
945c88b1d6cSniklas   /* We have no way to represent the argument types, so we just
946c88b1d6cSniklas      discard them.  However, if they define new types, we must output
947c88b1d6cSniklas      them.  We do this by producing empty typedefs.  */
948c88b1d6cSniklas   for (i = 0; i < argcount; i++)
949c88b1d6cSniklas     {
950c88b1d6cSniklas       if (! info->type_stack->definition)
951c88b1d6cSniklas 	free (stab_pop_type (info));
952c88b1d6cSniklas       else
953c88b1d6cSniklas 	{
954c88b1d6cSniklas 	  char *s, *buf;
955c88b1d6cSniklas 
956c88b1d6cSniklas 	  s = stab_pop_type (info);
957c88b1d6cSniklas 
958c88b1d6cSniklas 	  buf = (char *) xmalloc (strlen (s) + 3);
959c88b1d6cSniklas 	  sprintf (buf, ":t%s", s);
960c88b1d6cSniklas 	  free (s);
961c88b1d6cSniklas 
962c88b1d6cSniklas 	  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
963c074d1c9Sdrahn 	    return FALSE;
964c88b1d6cSniklas 
965c88b1d6cSniklas 	  free (buf);
966c88b1d6cSniklas 	}
967c88b1d6cSniklas     }
968c88b1d6cSniklas 
969c88b1d6cSniklas   return stab_modify_type (info, 'f', 0, &info->type_cache.function_types,
970c88b1d6cSniklas 			   &info->type_cache.function_types_alloc);
971c88b1d6cSniklas }
972c88b1d6cSniklas 
973c88b1d6cSniklas /* Push a reference type.  */
974c88b1d6cSniklas 
975c074d1c9Sdrahn static bfd_boolean
stab_reference_type(void * p)976*007c2a45Smiod stab_reference_type (void *p)
977c88b1d6cSniklas {
978c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
979c88b1d6cSniklas 
980c88b1d6cSniklas   /* FIXME: The size should depend upon the architecture.  */
981c88b1d6cSniklas   return stab_modify_type (info, '&', 4, &info->type_cache.reference_types,
982c88b1d6cSniklas 			   &info->type_cache.reference_types_alloc);
983c88b1d6cSniklas }
984c88b1d6cSniklas 
985c88b1d6cSniklas /* Push a range type.  */
986c88b1d6cSniklas 
987c074d1c9Sdrahn static bfd_boolean
stab_range_type(void * p,bfd_signed_vma low,bfd_signed_vma high)988*007c2a45Smiod stab_range_type (void *p, bfd_signed_vma low, bfd_signed_vma high)
989c88b1d6cSniklas {
990c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
991c074d1c9Sdrahn   bfd_boolean definition;
992c88b1d6cSniklas   unsigned int size;
993c88b1d6cSniklas   char *s, *buf;
994c88b1d6cSniklas 
995c88b1d6cSniklas   definition = info->type_stack->definition;
996c88b1d6cSniklas   size = info->type_stack->size;
997c88b1d6cSniklas 
998c88b1d6cSniklas   s = stab_pop_type (info);
999c88b1d6cSniklas   buf = (char *) xmalloc (strlen (s) + 100);
1000c88b1d6cSniklas   sprintf (buf, "r%s;%ld;%ld;", s, (long) low, (long) high);
1001c88b1d6cSniklas   free (s);
1002c88b1d6cSniklas 
1003c88b1d6cSniklas   if (! stab_push_string (info, buf, 0, definition, size))
1004c074d1c9Sdrahn     return FALSE;
1005c88b1d6cSniklas 
1006c88b1d6cSniklas   free (buf);
1007c88b1d6cSniklas 
1008c074d1c9Sdrahn   return TRUE;
1009c88b1d6cSniklas }
1010c88b1d6cSniklas 
1011c88b1d6cSniklas /* Push an array type.  */
1012c88b1d6cSniklas 
1013c074d1c9Sdrahn static bfd_boolean
stab_array_type(void * p,bfd_signed_vma low,bfd_signed_vma high,bfd_boolean stringp)1014*007c2a45Smiod stab_array_type (void *p, bfd_signed_vma low, bfd_signed_vma high,
1015*007c2a45Smiod 		 bfd_boolean stringp)
1016c88b1d6cSniklas {
1017c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1018c074d1c9Sdrahn   bfd_boolean definition;
1019c88b1d6cSniklas   unsigned int element_size;
1020c88b1d6cSniklas   char *range, *element, *buf;
1021c88b1d6cSniklas   long index;
1022c88b1d6cSniklas   unsigned int size;
1023c88b1d6cSniklas 
1024c88b1d6cSniklas   definition = info->type_stack->definition;
1025c88b1d6cSniklas   range = stab_pop_type (info);
1026c88b1d6cSniklas 
1027c88b1d6cSniklas   definition = definition || info->type_stack->definition;
1028c88b1d6cSniklas   element_size = info->type_stack->size;
1029c88b1d6cSniklas   element = stab_pop_type (info);
1030c88b1d6cSniklas 
1031c88b1d6cSniklas   buf = (char *) xmalloc (strlen (range) + strlen (element) + 100);
1032c88b1d6cSniklas 
1033c88b1d6cSniklas   if (! stringp)
1034c88b1d6cSniklas     {
1035c88b1d6cSniklas       index = 0;
1036c88b1d6cSniklas       *buf = '\0';
1037c88b1d6cSniklas     }
1038c88b1d6cSniklas   else
1039c88b1d6cSniklas     {
1040c88b1d6cSniklas       /* We need to define a type in order to include the string
1041c88b1d6cSniklas          attribute.  */
1042c88b1d6cSniklas       index = info->type_index;
1043c88b1d6cSniklas       ++info->type_index;
1044c074d1c9Sdrahn       definition = TRUE;
1045c88b1d6cSniklas       sprintf (buf, "%ld=@S;", index);
1046c88b1d6cSniklas     }
1047c88b1d6cSniklas 
10486a4c786fSespie   sprintf (buf + strlen (buf), "ar%s;%ld;%ld;%s",
10496a4c786fSespie 	   range, (long) low, (long) high, element);
1050c88b1d6cSniklas   free (range);
1051c88b1d6cSniklas   free (element);
1052c88b1d6cSniklas 
10534361b62eSniklas   if (high < low)
1054c88b1d6cSniklas     size = 0;
1055c88b1d6cSniklas   else
1056c88b1d6cSniklas     size = element_size * ((high - low) + 1);
1057c88b1d6cSniklas   if (! stab_push_string (info, buf, index, definition, size))
1058c074d1c9Sdrahn     return FALSE;
1059c88b1d6cSniklas 
1060c88b1d6cSniklas   free (buf);
1061c88b1d6cSniklas 
1062c074d1c9Sdrahn   return TRUE;
1063c88b1d6cSniklas }
1064c88b1d6cSniklas 
1065c88b1d6cSniklas /* Push a set type.  */
1066c88b1d6cSniklas 
1067c074d1c9Sdrahn static bfd_boolean
stab_set_type(void * p,bfd_boolean bitstringp)1068*007c2a45Smiod stab_set_type (void *p, bfd_boolean bitstringp)
1069c88b1d6cSniklas {
1070c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1071c074d1c9Sdrahn   bfd_boolean definition;
1072c88b1d6cSniklas   char *s, *buf;
1073c88b1d6cSniklas   long index;
1074c88b1d6cSniklas 
1075c88b1d6cSniklas   definition = info->type_stack->definition;
1076c88b1d6cSniklas 
1077c88b1d6cSniklas   s = stab_pop_type (info);
1078c88b1d6cSniklas   buf = (char *) xmalloc (strlen (s) + 30);
1079c88b1d6cSniklas 
1080c88b1d6cSniklas   if (! bitstringp)
1081c88b1d6cSniklas     {
1082c88b1d6cSniklas       *buf = '\0';
1083c88b1d6cSniklas       index = 0;
1084c88b1d6cSniklas     }
1085c88b1d6cSniklas   else
1086c88b1d6cSniklas     {
1087c88b1d6cSniklas       /* We need to define a type in order to include the string
1088c88b1d6cSniklas          attribute.  */
1089c88b1d6cSniklas       index = info->type_index;
1090c88b1d6cSniklas       ++info->type_index;
1091c074d1c9Sdrahn       definition = TRUE;
1092c88b1d6cSniklas       sprintf (buf, "%ld=@S;", index);
1093c88b1d6cSniklas     }
1094c88b1d6cSniklas 
1095c88b1d6cSniklas   sprintf (buf + strlen (buf), "S%s", s);
1096c88b1d6cSniklas   free (s);
1097c88b1d6cSniklas 
1098c88b1d6cSniklas   if (! stab_push_string (info, buf, index, definition, 0))
1099c074d1c9Sdrahn     return FALSE;
1100c88b1d6cSniklas 
1101c88b1d6cSniklas   free (buf);
1102c88b1d6cSniklas 
1103c074d1c9Sdrahn   return TRUE;
1104c88b1d6cSniklas }
1105c88b1d6cSniklas 
1106c88b1d6cSniklas /* Push an offset type.  */
1107c88b1d6cSniklas 
1108c074d1c9Sdrahn static bfd_boolean
stab_offset_type(void * p)1109*007c2a45Smiod stab_offset_type (void *p)
1110c88b1d6cSniklas {
1111c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1112c074d1c9Sdrahn   bfd_boolean definition;
1113c88b1d6cSniklas   char *target, *base, *buf;
1114c88b1d6cSniklas 
1115c88b1d6cSniklas   definition = info->type_stack->definition;
1116c88b1d6cSniklas   target = stab_pop_type (info);
1117c88b1d6cSniklas 
1118c88b1d6cSniklas   definition = definition || info->type_stack->definition;
1119c88b1d6cSniklas   base = stab_pop_type (info);
1120c88b1d6cSniklas 
1121c88b1d6cSniklas   buf = (char *) xmalloc (strlen (target) + strlen (base) + 3);
1122c88b1d6cSniklas   sprintf (buf, "@%s,%s", base, target);
1123c88b1d6cSniklas   free (base);
1124c88b1d6cSniklas   free (target);
1125c88b1d6cSniklas 
1126c88b1d6cSniklas   if (! stab_push_string (info, buf, 0, definition, 0))
1127c074d1c9Sdrahn     return FALSE;
1128c88b1d6cSniklas 
1129c88b1d6cSniklas   free (buf);
1130c88b1d6cSniklas 
1131c074d1c9Sdrahn   return TRUE;
1132c88b1d6cSniklas }
1133c88b1d6cSniklas 
1134c88b1d6cSniklas /* Push a method type.  */
1135c88b1d6cSniklas 
1136c074d1c9Sdrahn static bfd_boolean
stab_method_type(void * p,bfd_boolean domainp,int argcount,bfd_boolean varargs)1137*007c2a45Smiod stab_method_type (void *p, bfd_boolean domainp, int argcount,
1138*007c2a45Smiod 		  bfd_boolean varargs)
1139c88b1d6cSniklas {
1140c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1141c074d1c9Sdrahn   bfd_boolean definition;
1142c88b1d6cSniklas   char *domain, *return_type, *buf;
1143c88b1d6cSniklas   char **args;
1144c88b1d6cSniklas   int i;
1145c88b1d6cSniklas   size_t len;
1146c88b1d6cSniklas 
1147c88b1d6cSniklas   /* We don't bother with stub method types, because that would
1148c88b1d6cSniklas      require a mangler for C++ argument types.  This will waste space
1149c88b1d6cSniklas      in the debugging output.  */
1150c88b1d6cSniklas 
1151c88b1d6cSniklas   /* We need a domain.  I'm not sure DOMAINP can ever be false,
1152c88b1d6cSniklas      anyhow.  */
1153c88b1d6cSniklas   if (! domainp)
1154c88b1d6cSniklas     {
1155c88b1d6cSniklas       if (! stab_empty_type (p))
1156c074d1c9Sdrahn 	return FALSE;
1157c88b1d6cSniklas     }
1158c88b1d6cSniklas 
1159c88b1d6cSniklas   definition = info->type_stack->definition;
1160c88b1d6cSniklas   domain = stab_pop_type (info);
1161c88b1d6cSniklas 
1162c88b1d6cSniklas   /* A non-varargs function is indicated by making the last parameter
1163c88b1d6cSniklas      type be void.  */
1164c88b1d6cSniklas 
1165c88b1d6cSniklas   if (argcount < 0)
1166c88b1d6cSniklas     {
1167c88b1d6cSniklas       args = NULL;
1168c88b1d6cSniklas       argcount = 0;
1169c88b1d6cSniklas     }
1170c88b1d6cSniklas   else if (argcount == 0)
1171c88b1d6cSniklas     {
1172c88b1d6cSniklas       if (varargs)
1173c88b1d6cSniklas 	args = NULL;
1174c88b1d6cSniklas       else
1175c88b1d6cSniklas 	{
1176c88b1d6cSniklas 	  args = (char **) xmalloc (1 * sizeof (*args));
1177c88b1d6cSniklas 	  if (! stab_empty_type (p))
1178c074d1c9Sdrahn 	    return FALSE;
1179c88b1d6cSniklas 	  definition = definition || info->type_stack->definition;
1180c88b1d6cSniklas 	  args[0] = stab_pop_type (info);
1181c88b1d6cSniklas 	  argcount = 1;
1182c88b1d6cSniklas 	}
1183c88b1d6cSniklas     }
1184c88b1d6cSniklas   else
1185c88b1d6cSniklas     {
1186c88b1d6cSniklas       args = (char **) xmalloc ((argcount + 1) * sizeof (*args));
1187c88b1d6cSniklas       for (i = argcount - 1; i >= 0; i--)
1188c88b1d6cSniklas 	{
1189c88b1d6cSniklas 	  definition = definition || info->type_stack->definition;
1190c88b1d6cSniklas 	  args[i] = stab_pop_type (info);
1191c88b1d6cSniklas 	}
1192c88b1d6cSniklas       if (! varargs)
1193c88b1d6cSniklas 	{
1194c88b1d6cSniklas 	  if (! stab_empty_type (p))
1195c074d1c9Sdrahn 	    return FALSE;
1196c88b1d6cSniklas 	  definition = definition || info->type_stack->definition;
1197c88b1d6cSniklas 	  args[argcount] = stab_pop_type (info);
1198c88b1d6cSniklas 	  ++argcount;
1199c88b1d6cSniklas 	}
1200c88b1d6cSniklas     }
1201c88b1d6cSniklas 
1202c88b1d6cSniklas   definition = definition || info->type_stack->definition;
1203c88b1d6cSniklas   return_type = stab_pop_type (info);
1204c88b1d6cSniklas 
1205c88b1d6cSniklas   len = strlen (domain) + strlen (return_type) + 10;
1206c88b1d6cSniklas   for (i = 0; i < argcount; i++)
1207c88b1d6cSniklas     len += strlen (args[i]);
1208c88b1d6cSniklas 
1209c88b1d6cSniklas   buf = (char *) xmalloc (len);
1210c88b1d6cSniklas 
1211c88b1d6cSniklas   sprintf (buf, "#%s,%s", domain, return_type);
1212c88b1d6cSniklas   free (domain);
1213c88b1d6cSniklas   free (return_type);
1214c88b1d6cSniklas   for (i = 0; i < argcount; i++)
1215c88b1d6cSniklas     {
1216c88b1d6cSniklas       strcat (buf, ",");
1217c88b1d6cSniklas       strcat (buf, args[i]);
1218c88b1d6cSniklas       free (args[i]);
1219c88b1d6cSniklas     }
1220c88b1d6cSniklas   strcat (buf, ";");
1221c88b1d6cSniklas 
1222c88b1d6cSniklas   if (args != NULL)
1223c88b1d6cSniklas     free (args);
1224c88b1d6cSniklas 
1225c88b1d6cSniklas   if (! stab_push_string (info, buf, 0, definition, 0))
1226c074d1c9Sdrahn     return FALSE;
1227c88b1d6cSniklas 
1228c88b1d6cSniklas   free (buf);
1229c88b1d6cSniklas 
1230c074d1c9Sdrahn   return TRUE;
1231c88b1d6cSniklas }
1232c88b1d6cSniklas 
1233c88b1d6cSniklas /* Push a const version of a type.  */
1234c88b1d6cSniklas 
1235c074d1c9Sdrahn static bfd_boolean
stab_const_type(void * p)1236*007c2a45Smiod stab_const_type (void *p)
1237c88b1d6cSniklas {
1238c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1239c88b1d6cSniklas 
1240c88b1d6cSniklas   return stab_modify_type (info, 'k', info->type_stack->size,
1241c88b1d6cSniklas 			   (long **) NULL, (size_t *) NULL);
1242c88b1d6cSniklas }
1243c88b1d6cSniklas 
1244c88b1d6cSniklas /* Push a volatile version of a type.  */
1245c88b1d6cSniklas 
1246c074d1c9Sdrahn static bfd_boolean
stab_volatile_type(void * p)1247*007c2a45Smiod stab_volatile_type (void *p)
1248c88b1d6cSniklas {
1249c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1250c88b1d6cSniklas 
1251c88b1d6cSniklas   return stab_modify_type (info, 'B', info->type_stack->size,
1252c88b1d6cSniklas 			   (long **) NULL, (size_t *) NULL);
1253c88b1d6cSniklas }
1254c88b1d6cSniklas 
1255c88b1d6cSniklas /* Get the type index to use for a struct/union/class ID.  This should
1256c88b1d6cSniklas    return -1 if it fails.  */
1257c88b1d6cSniklas 
1258c88b1d6cSniklas static long
stab_get_struct_index(struct stab_write_handle * info,const char * tag,unsigned int id,enum debug_type_kind kind,unsigned int * psize)1259*007c2a45Smiod stab_get_struct_index (struct stab_write_handle *info, const char *tag,
1260*007c2a45Smiod 		       unsigned int id, enum debug_type_kind kind,
1261*007c2a45Smiod 		       unsigned int *psize)
1262c88b1d6cSniklas {
1263c88b1d6cSniklas   if (id >= info->type_cache.struct_types_alloc)
1264c88b1d6cSniklas     {
1265c88b1d6cSniklas       size_t alloc;
1266c88b1d6cSniklas 
1267c88b1d6cSniklas       alloc = info->type_cache.struct_types_alloc;
1268c88b1d6cSniklas       if (alloc == 0)
1269c88b1d6cSniklas 	alloc = 10;
1270c88b1d6cSniklas       while (id >= alloc)
1271c88b1d6cSniklas 	alloc *= 2;
1272c88b1d6cSniklas       info->type_cache.struct_types =
1273c88b1d6cSniklas 	(struct stab_tag *) xrealloc (info->type_cache.struct_types,
1274c88b1d6cSniklas 				      alloc * sizeof (struct stab_tag));
1275c88b1d6cSniklas       memset ((info->type_cache.struct_types
1276c88b1d6cSniklas 	       + info->type_cache.struct_types_alloc),
1277c88b1d6cSniklas 	      0,
1278c88b1d6cSniklas 	      ((alloc - info->type_cache.struct_types_alloc)
1279c88b1d6cSniklas 	       * sizeof (struct stab_tag)));
1280c88b1d6cSniklas       info->type_cache.struct_types_alloc = alloc;
1281c88b1d6cSniklas     }
1282c88b1d6cSniklas 
1283c88b1d6cSniklas   if (info->type_cache.struct_types[id].index == 0)
1284c88b1d6cSniklas     {
1285c88b1d6cSniklas       info->type_cache.struct_types[id].index = info->type_index;
1286c88b1d6cSniklas       ++info->type_index;
1287c88b1d6cSniklas       info->type_cache.struct_types[id].tag = tag;
1288c88b1d6cSniklas       info->type_cache.struct_types[id].kind = kind;
1289c88b1d6cSniklas     }
1290c88b1d6cSniklas 
1291c88b1d6cSniklas   if (kind == DEBUG_KIND_ILLEGAL)
1292c88b1d6cSniklas     {
1293c88b1d6cSniklas       /* This is a definition of the struct.  */
1294c88b1d6cSniklas       info->type_cache.struct_types[id].kind = kind;
1295c88b1d6cSniklas       info->type_cache.struct_types[id].size = *psize;
1296c88b1d6cSniklas     }
1297c88b1d6cSniklas   else
1298c88b1d6cSniklas     *psize = info->type_cache.struct_types[id].size;
1299c88b1d6cSniklas 
1300c88b1d6cSniklas   return info->type_cache.struct_types[id].index;
1301c88b1d6cSniklas }
1302c88b1d6cSniklas 
1303c88b1d6cSniklas /* Start outputting a struct.  We ignore the tag, and handle it in
1304c88b1d6cSniklas    stab_tag.  */
1305c88b1d6cSniklas 
1306c074d1c9Sdrahn static bfd_boolean
stab_start_struct_type(void * p,const char * tag,unsigned int id,bfd_boolean structp,unsigned int size)1307*007c2a45Smiod stab_start_struct_type (void *p, const char *tag, unsigned int id,
1308*007c2a45Smiod 			bfd_boolean structp, unsigned int size)
1309c88b1d6cSniklas {
1310c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1311c88b1d6cSniklas   long index;
1312c074d1c9Sdrahn   bfd_boolean definition;
1313c88b1d6cSniklas   char *buf;
1314c88b1d6cSniklas 
1315c88b1d6cSniklas   buf = (char *) xmalloc (40);
1316c88b1d6cSniklas 
1317c88b1d6cSniklas   if (id == 0)
1318c88b1d6cSniklas     {
1319c88b1d6cSniklas       index = 0;
1320c88b1d6cSniklas       *buf = '\0';
1321c074d1c9Sdrahn       definition = FALSE;
1322c88b1d6cSniklas     }
1323c88b1d6cSniklas   else
1324c88b1d6cSniklas     {
1325c88b1d6cSniklas       index = stab_get_struct_index (info, tag, id, DEBUG_KIND_ILLEGAL,
1326c88b1d6cSniklas 				     &size);
1327c88b1d6cSniklas       if (index < 0)
1328c074d1c9Sdrahn 	return FALSE;
1329c88b1d6cSniklas       sprintf (buf, "%ld=", index);
1330c074d1c9Sdrahn       definition = TRUE;
1331c88b1d6cSniklas     }
1332c88b1d6cSniklas 
1333c88b1d6cSniklas   sprintf (buf + strlen (buf), "%c%u",
1334c88b1d6cSniklas 	   structp ? 's' : 'u',
1335c88b1d6cSniklas 	   size);
1336c88b1d6cSniklas 
1337c88b1d6cSniklas   if (! stab_push_string (info, buf, index, definition, size))
1338c074d1c9Sdrahn     return FALSE;
1339c88b1d6cSniklas 
1340c88b1d6cSniklas   info->type_stack->fields = (char *) xmalloc (1);
1341c88b1d6cSniklas   info->type_stack->fields[0] = '\0';
1342c88b1d6cSniklas 
1343c074d1c9Sdrahn   return TRUE;
1344c88b1d6cSniklas }
1345c88b1d6cSniklas 
1346c88b1d6cSniklas /* Add a field to a struct.  */
1347c88b1d6cSniklas 
1348c074d1c9Sdrahn static bfd_boolean
stab_struct_field(void * p,const char * name,bfd_vma bitpos,bfd_vma bitsize,enum debug_visibility visibility)1349*007c2a45Smiod stab_struct_field (void *p, const char *name, bfd_vma bitpos,
1350*007c2a45Smiod 		   bfd_vma bitsize, enum debug_visibility visibility)
1351c88b1d6cSniklas {
1352c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1353c074d1c9Sdrahn   bfd_boolean definition;
1354c88b1d6cSniklas   unsigned int size;
1355c88b1d6cSniklas   char *s, *n;
1356c88b1d6cSniklas   const char *vis;
1357c88b1d6cSniklas 
1358c88b1d6cSniklas   definition = info->type_stack->definition;
1359c88b1d6cSniklas   size = info->type_stack->size;
1360c88b1d6cSniklas   s = stab_pop_type (info);
1361c88b1d6cSniklas 
1362c88b1d6cSniklas   /* Add this field to the end of the current struct fields, which is
1363c88b1d6cSniklas      currently on the top of the stack.  */
1364c88b1d6cSniklas 
1365c88b1d6cSniklas   assert (info->type_stack->fields != NULL);
1366c88b1d6cSniklas   n = (char *) xmalloc (strlen (info->type_stack->fields)
1367c88b1d6cSniklas 			+ strlen (name)
1368c88b1d6cSniklas 			+ strlen (s)
1369c88b1d6cSniklas 			+ 50);
1370c88b1d6cSniklas 
1371c88b1d6cSniklas   switch (visibility)
1372c88b1d6cSniklas     {
1373c88b1d6cSniklas     default:
1374c88b1d6cSniklas       abort ();
1375c88b1d6cSniklas 
1376c88b1d6cSniklas     case DEBUG_VISIBILITY_PUBLIC:
1377c88b1d6cSniklas       vis = "";
1378c88b1d6cSniklas       break;
1379c88b1d6cSniklas 
1380c88b1d6cSniklas     case DEBUG_VISIBILITY_PRIVATE:
1381c88b1d6cSniklas       vis = "/0";
1382c88b1d6cSniklas       break;
1383c88b1d6cSniklas 
1384c88b1d6cSniklas     case DEBUG_VISIBILITY_PROTECTED:
1385c88b1d6cSniklas       vis = "/1";
1386c88b1d6cSniklas       break;
1387c88b1d6cSniklas     }
1388c88b1d6cSniklas 
1389c88b1d6cSniklas   if (bitsize == 0)
1390c88b1d6cSniklas     {
1391c88b1d6cSniklas       bitsize = size * 8;
1392c88b1d6cSniklas       if (bitsize == 0)
1393b305b0f1Sespie 	non_fatal (_("%s: warning: unknown size for field `%s' in struct"),
1394c88b1d6cSniklas 		   bfd_get_filename (info->abfd), name);
1395c88b1d6cSniklas     }
1396c88b1d6cSniklas 
1397c88b1d6cSniklas   sprintf (n, "%s%s:%s%s,%ld,%ld;", info->type_stack->fields, name, vis, s,
1398c88b1d6cSniklas 	   (long) bitpos, (long) bitsize);
1399c88b1d6cSniklas 
1400c88b1d6cSniklas   free (info->type_stack->fields);
1401c88b1d6cSniklas   info->type_stack->fields = n;
1402c88b1d6cSniklas 
1403c88b1d6cSniklas   if (definition)
1404c074d1c9Sdrahn     info->type_stack->definition = TRUE;
1405c88b1d6cSniklas 
1406c074d1c9Sdrahn   return TRUE;
1407c88b1d6cSniklas }
1408c88b1d6cSniklas 
1409c88b1d6cSniklas /* Finish up a struct.  */
1410c88b1d6cSniklas 
1411c074d1c9Sdrahn static bfd_boolean
stab_end_struct_type(void * p)1412*007c2a45Smiod stab_end_struct_type (void *p)
1413c88b1d6cSniklas {
1414c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1415c074d1c9Sdrahn   bfd_boolean definition;
1416c88b1d6cSniklas   long index;
1417c88b1d6cSniklas   unsigned int size;
1418c88b1d6cSniklas   char *fields, *first, *buf;
1419c88b1d6cSniklas 
1420c88b1d6cSniklas   assert (info->type_stack != NULL && info->type_stack->fields != NULL);
1421c88b1d6cSniklas 
1422c88b1d6cSniklas   definition = info->type_stack->definition;
1423c88b1d6cSniklas   index = info->type_stack->index;
1424c88b1d6cSniklas   size = info->type_stack->size;
1425c88b1d6cSniklas   fields = info->type_stack->fields;
1426c88b1d6cSniklas   first = stab_pop_type (info);
1427c88b1d6cSniklas 
1428c88b1d6cSniklas   buf = (char *) xmalloc (strlen (first) + strlen (fields) + 2);
1429c88b1d6cSniklas   sprintf (buf, "%s%s;", first, fields);
1430c88b1d6cSniklas   free (first);
1431c88b1d6cSniklas   free (fields);
1432c88b1d6cSniklas 
1433c88b1d6cSniklas   if (! stab_push_string (info, buf, index, definition, size))
1434c074d1c9Sdrahn     return FALSE;
1435c88b1d6cSniklas 
1436c88b1d6cSniklas   free (buf);
1437c88b1d6cSniklas 
1438c074d1c9Sdrahn   return TRUE;
1439c88b1d6cSniklas }
1440c88b1d6cSniklas 
1441c88b1d6cSniklas /* Start outputting a class.  */
1442c88b1d6cSniklas 
1443c074d1c9Sdrahn static bfd_boolean
stab_start_class_type(void * p,const char * tag,unsigned int id,bfd_boolean structp,unsigned int size,bfd_boolean vptr,bfd_boolean ownvptr)1444*007c2a45Smiod stab_start_class_type (void *p, const char *tag, unsigned int id, bfd_boolean structp, unsigned int size, bfd_boolean vptr, bfd_boolean ownvptr)
1445c88b1d6cSniklas {
1446c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1447c074d1c9Sdrahn   bfd_boolean definition;
1448c88b1d6cSniklas   char *vstring;
1449c88b1d6cSniklas 
1450c88b1d6cSniklas   if (! vptr || ownvptr)
1451c88b1d6cSniklas     {
1452c074d1c9Sdrahn       definition = FALSE;
1453c88b1d6cSniklas       vstring = NULL;
1454c88b1d6cSniklas     }
1455c88b1d6cSniklas   else
1456c88b1d6cSniklas     {
1457c88b1d6cSniklas       definition = info->type_stack->definition;
1458c88b1d6cSniklas       vstring = stab_pop_type (info);
1459c88b1d6cSniklas     }
1460c88b1d6cSniklas 
1461c88b1d6cSniklas   if (! stab_start_struct_type (p, tag, id, structp, size))
1462c074d1c9Sdrahn     return FALSE;
1463c88b1d6cSniklas 
1464c88b1d6cSniklas   if (vptr)
1465c88b1d6cSniklas     {
1466c88b1d6cSniklas       char *vtable;
1467c88b1d6cSniklas 
1468c88b1d6cSniklas       if (ownvptr)
1469c88b1d6cSniklas 	{
1470c88b1d6cSniklas 	  assert (info->type_stack->index > 0);
1471c88b1d6cSniklas 	  vtable = (char *) xmalloc (20);
1472c88b1d6cSniklas 	  sprintf (vtable, "~%%%ld", info->type_stack->index);
1473c88b1d6cSniklas 	}
1474c88b1d6cSniklas       else
1475c88b1d6cSniklas 	{
1476c88b1d6cSniklas 	  vtable = (char *) xmalloc (strlen (vstring) + 3);
1477c88b1d6cSniklas 	  sprintf (vtable, "~%%%s", vstring);
1478c88b1d6cSniklas 	  free (vstring);
1479c88b1d6cSniklas 	}
1480c88b1d6cSniklas 
1481c88b1d6cSniklas       info->type_stack->vtable = vtable;
1482c88b1d6cSniklas     }
1483c88b1d6cSniklas 
1484c88b1d6cSniklas   if (definition)
1485c074d1c9Sdrahn     info->type_stack->definition = TRUE;
1486c88b1d6cSniklas 
1487c074d1c9Sdrahn   return TRUE;
1488c88b1d6cSniklas }
1489c88b1d6cSniklas 
1490c88b1d6cSniklas /* Add a static member to the class on the type stack.  */
1491c88b1d6cSniklas 
1492c074d1c9Sdrahn static bfd_boolean
stab_class_static_member(void * p,const char * name,const char * physname,enum debug_visibility visibility)1493*007c2a45Smiod stab_class_static_member (void *p, const char *name, const char *physname,
1494*007c2a45Smiod 			  enum debug_visibility visibility)
1495c88b1d6cSniklas {
1496c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1497c074d1c9Sdrahn   bfd_boolean definition;
1498c88b1d6cSniklas   char *s, *n;
1499c88b1d6cSniklas   const char *vis;
1500c88b1d6cSniklas 
1501c88b1d6cSniklas   definition = info->type_stack->definition;
1502c88b1d6cSniklas   s = stab_pop_type (info);
1503c88b1d6cSniklas 
1504c88b1d6cSniklas   /* Add this field to the end of the current struct fields, which is
1505c88b1d6cSniklas      currently on the top of the stack.  */
1506c88b1d6cSniklas 
1507c88b1d6cSniklas   assert (info->type_stack->fields != NULL);
1508c88b1d6cSniklas   n = (char *) xmalloc (strlen (info->type_stack->fields)
1509c88b1d6cSniklas 			+ strlen (name)
1510c88b1d6cSniklas 			+ strlen (s)
1511c88b1d6cSniklas 			+ strlen (physname)
1512c88b1d6cSniklas 			+ 10);
1513c88b1d6cSniklas 
1514c88b1d6cSniklas   switch (visibility)
1515c88b1d6cSniklas     {
1516c88b1d6cSniklas     default:
1517c88b1d6cSniklas       abort ();
1518c88b1d6cSniklas 
1519c88b1d6cSniklas     case DEBUG_VISIBILITY_PUBLIC:
1520c88b1d6cSniklas       vis = "";
1521c88b1d6cSniklas       break;
1522c88b1d6cSniklas 
1523c88b1d6cSniklas     case DEBUG_VISIBILITY_PRIVATE:
1524c88b1d6cSniklas       vis = "/0";
1525c88b1d6cSniklas       break;
1526c88b1d6cSniklas 
1527c88b1d6cSniklas     case DEBUG_VISIBILITY_PROTECTED:
1528c88b1d6cSniklas       vis = "/1";
1529c88b1d6cSniklas       break;
1530c88b1d6cSniklas     }
1531c88b1d6cSniklas 
1532c88b1d6cSniklas   sprintf (n, "%s%s:%s%s:%s;", info->type_stack->fields, name, vis, s,
1533c88b1d6cSniklas 	   physname);
1534c88b1d6cSniklas 
1535c88b1d6cSniklas   free (info->type_stack->fields);
1536c88b1d6cSniklas   info->type_stack->fields = n;
1537c88b1d6cSniklas 
1538c88b1d6cSniklas   if (definition)
1539c074d1c9Sdrahn     info->type_stack->definition = TRUE;
1540c88b1d6cSniklas 
1541c074d1c9Sdrahn   return TRUE;
1542c88b1d6cSniklas }
1543c88b1d6cSniklas 
1544c88b1d6cSniklas /* Add a base class to the class on the type stack.  */
1545c88b1d6cSniklas 
1546c074d1c9Sdrahn static bfd_boolean
stab_class_baseclass(void * p,bfd_vma bitpos,bfd_boolean virtual,enum debug_visibility visibility)1547*007c2a45Smiod stab_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
1548*007c2a45Smiod 		      enum debug_visibility visibility)
1549c88b1d6cSniklas {
1550c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1551c074d1c9Sdrahn   bfd_boolean definition;
1552c88b1d6cSniklas   char *s;
1553c88b1d6cSniklas   char *buf;
1554c88b1d6cSniklas   unsigned int c;
1555c88b1d6cSniklas   char **baseclasses;
1556c88b1d6cSniklas 
1557c88b1d6cSniklas   definition = info->type_stack->definition;
1558c88b1d6cSniklas   s = stab_pop_type (info);
1559c88b1d6cSniklas 
1560c88b1d6cSniklas   /* Build the base class specifier.  */
1561c88b1d6cSniklas 
1562c88b1d6cSniklas   buf = (char *) xmalloc (strlen (s) + 25);
1563c88b1d6cSniklas   buf[0] = virtual ? '1' : '0';
1564c88b1d6cSniklas   switch (visibility)
1565c88b1d6cSniklas     {
1566c88b1d6cSniklas     default:
1567c88b1d6cSniklas       abort ();
1568c88b1d6cSniklas 
1569c88b1d6cSniklas     case DEBUG_VISIBILITY_PRIVATE:
1570c88b1d6cSniklas       buf[1] = '0';
1571c88b1d6cSniklas       break;
1572c88b1d6cSniklas 
1573c88b1d6cSniklas     case DEBUG_VISIBILITY_PROTECTED:
1574c88b1d6cSniklas       buf[1] = '1';
1575c88b1d6cSniklas       break;
1576c88b1d6cSniklas 
1577c88b1d6cSniklas     case DEBUG_VISIBILITY_PUBLIC:
1578c88b1d6cSniklas       buf[1] = '2';
1579c88b1d6cSniklas       break;
1580c88b1d6cSniklas     }
1581c88b1d6cSniklas 
1582c88b1d6cSniklas   sprintf (buf + 2, "%ld,%s;", (long) bitpos, s);
1583c88b1d6cSniklas   free (s);
1584c88b1d6cSniklas 
1585c88b1d6cSniklas   /* Add the new baseclass to the existing ones.  */
1586c88b1d6cSniklas 
1587c88b1d6cSniklas   assert (info->type_stack != NULL && info->type_stack->fields != NULL);
1588c88b1d6cSniklas 
1589c88b1d6cSniklas   if (info->type_stack->baseclasses == NULL)
1590c88b1d6cSniklas     c = 0;
1591c88b1d6cSniklas   else
1592c88b1d6cSniklas     {
1593c88b1d6cSniklas       c = 0;
1594c88b1d6cSniklas       while (info->type_stack->baseclasses[c] != NULL)
1595c88b1d6cSniklas 	++c;
1596c88b1d6cSniklas     }
1597c88b1d6cSniklas 
1598c88b1d6cSniklas   baseclasses = (char **) xrealloc (info->type_stack->baseclasses,
1599c88b1d6cSniklas 				    (c + 2) * sizeof (*baseclasses));
1600c88b1d6cSniklas   baseclasses[c] = buf;
1601c88b1d6cSniklas   baseclasses[c + 1] = NULL;
1602c88b1d6cSniklas 
1603c88b1d6cSniklas   info->type_stack->baseclasses = baseclasses;
1604c88b1d6cSniklas 
1605c88b1d6cSniklas   if (definition)
1606c074d1c9Sdrahn     info->type_stack->definition = TRUE;
1607c88b1d6cSniklas 
1608c074d1c9Sdrahn   return TRUE;
1609c88b1d6cSniklas }
1610c88b1d6cSniklas 
1611c88b1d6cSniklas /* Start adding a method to the class on the type stack.  */
1612c88b1d6cSniklas 
1613c074d1c9Sdrahn static bfd_boolean
stab_class_start_method(void * p,const char * name)1614*007c2a45Smiod stab_class_start_method (void *p, const char *name)
1615c88b1d6cSniklas {
1616c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1617c88b1d6cSniklas   char *m;
1618c88b1d6cSniklas 
1619c88b1d6cSniklas   assert (info->type_stack != NULL && info->type_stack->fields != NULL);
1620c88b1d6cSniklas 
1621c88b1d6cSniklas   if (info->type_stack->methods == NULL)
1622c88b1d6cSniklas     {
1623c88b1d6cSniklas       m = (char *) xmalloc (strlen (name) + 3);
1624c88b1d6cSniklas       *m = '\0';
1625c88b1d6cSniklas     }
1626c88b1d6cSniklas   else
1627c88b1d6cSniklas     {
1628c88b1d6cSniklas       m = (char *) xrealloc (info->type_stack->methods,
1629c88b1d6cSniklas 			     (strlen (info->type_stack->methods)
1630c88b1d6cSniklas 			      + strlen (name)
1631c88b1d6cSniklas 			      + 4));
1632c88b1d6cSniklas     }
1633c88b1d6cSniklas 
1634c88b1d6cSniklas   sprintf (m + strlen (m), "%s::", name);
1635c88b1d6cSniklas 
1636c88b1d6cSniklas   info->type_stack->methods = m;
1637c88b1d6cSniklas 
1638c074d1c9Sdrahn   return TRUE;
1639c88b1d6cSniklas }
1640c88b1d6cSniklas 
1641c88b1d6cSniklas /* Add a variant, either static or not, to the current method.  */
1642c88b1d6cSniklas 
1643c074d1c9Sdrahn static bfd_boolean
stab_class_method_var(struct stab_write_handle * info,const char * physname,enum debug_visibility visibility,bfd_boolean staticp,bfd_boolean constp,bfd_boolean volatilep,bfd_vma voffset,bfd_boolean contextp)1644*007c2a45Smiod stab_class_method_var (struct stab_write_handle *info, const char *physname,
1645*007c2a45Smiod 		       enum debug_visibility visibility,
1646*007c2a45Smiod 		       bfd_boolean staticp, bfd_boolean constp,
1647*007c2a45Smiod 		       bfd_boolean volatilep, bfd_vma voffset,
1648*007c2a45Smiod 		       bfd_boolean contextp)
1649c88b1d6cSniklas {
1650c074d1c9Sdrahn   bfd_boolean definition;
1651c88b1d6cSniklas   char *type;
1652c88b1d6cSniklas   char *context = NULL;
1653c88b1d6cSniklas   char visc, qualc, typec;
1654c88b1d6cSniklas 
1655c88b1d6cSniklas   definition = info->type_stack->definition;
1656c88b1d6cSniklas   type = stab_pop_type (info);
1657c88b1d6cSniklas 
1658c88b1d6cSniklas   if (contextp)
1659c88b1d6cSniklas     {
1660c88b1d6cSniklas       definition = definition || info->type_stack->definition;
1661c88b1d6cSniklas       context = stab_pop_type (info);
1662c88b1d6cSniklas     }
1663c88b1d6cSniklas 
1664c88b1d6cSniklas   assert (info->type_stack != NULL && info->type_stack->methods != NULL);
1665c88b1d6cSniklas 
1666c88b1d6cSniklas   switch (visibility)
1667c88b1d6cSniklas     {
1668c88b1d6cSniklas     default:
1669c88b1d6cSniklas       abort ();
1670c88b1d6cSniklas 
1671c88b1d6cSniklas     case DEBUG_VISIBILITY_PRIVATE:
1672c88b1d6cSniklas       visc = '0';
1673c88b1d6cSniklas       break;
1674c88b1d6cSniklas 
1675c88b1d6cSniklas     case DEBUG_VISIBILITY_PROTECTED:
1676c88b1d6cSniklas       visc = '1';
1677c88b1d6cSniklas       break;
1678c88b1d6cSniklas 
1679c88b1d6cSniklas     case DEBUG_VISIBILITY_PUBLIC:
1680c88b1d6cSniklas       visc = '2';
1681c88b1d6cSniklas       break;
1682c88b1d6cSniklas     }
1683c88b1d6cSniklas 
1684c88b1d6cSniklas   if (constp)
1685c88b1d6cSniklas     {
1686c88b1d6cSniklas       if (volatilep)
1687c88b1d6cSniklas 	qualc = 'D';
1688c88b1d6cSniklas       else
1689c88b1d6cSniklas 	qualc = 'B';
1690c88b1d6cSniklas     }
1691c88b1d6cSniklas   else
1692c88b1d6cSniklas     {
1693c88b1d6cSniklas       if (volatilep)
1694c88b1d6cSniklas 	qualc = 'C';
1695c88b1d6cSniklas       else
1696c88b1d6cSniklas 	qualc = 'A';
1697c88b1d6cSniklas     }
1698c88b1d6cSniklas 
1699c88b1d6cSniklas   if (staticp)
1700c88b1d6cSniklas     typec = '?';
1701c88b1d6cSniklas   else if (! contextp)
1702c88b1d6cSniklas     typec = '.';
1703c88b1d6cSniklas   else
1704c88b1d6cSniklas     typec = '*';
1705c88b1d6cSniklas 
1706c88b1d6cSniklas   info->type_stack->methods =
1707c88b1d6cSniklas     (char *) xrealloc (info->type_stack->methods,
1708c88b1d6cSniklas 		       (strlen (info->type_stack->methods)
1709c88b1d6cSniklas 			+ strlen (type)
1710c88b1d6cSniklas 			+ strlen (physname)
1711c88b1d6cSniklas 			+ (contextp ? strlen (context) : 0)
1712c88b1d6cSniklas 			+ 40));
1713c88b1d6cSniklas 
1714c88b1d6cSniklas   sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
1715c88b1d6cSniklas 	   "%s:%s;%c%c%c", type, physname, visc, qualc, typec);
1716c88b1d6cSniklas   free (type);
1717c88b1d6cSniklas 
1718c88b1d6cSniklas   if (contextp)
1719c88b1d6cSniklas     {
1720c88b1d6cSniklas       sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
1721c88b1d6cSniklas 	       "%ld;%s;", (long) voffset, context);
1722c88b1d6cSniklas       free (context);
1723c88b1d6cSniklas     }
1724c88b1d6cSniklas 
1725c88b1d6cSniklas   if (definition)
1726c074d1c9Sdrahn     info->type_stack->definition = TRUE;
1727c88b1d6cSniklas 
1728c074d1c9Sdrahn   return TRUE;
1729c88b1d6cSniklas }
1730c88b1d6cSniklas 
1731c88b1d6cSniklas /* Add a variant to the current method.  */
1732c88b1d6cSniklas 
1733c074d1c9Sdrahn static bfd_boolean
stab_class_method_variant(void * p,const char * physname,enum debug_visibility visibility,bfd_boolean constp,bfd_boolean volatilep,bfd_vma voffset,bfd_boolean contextp)1734*007c2a45Smiod stab_class_method_variant (void *p, const char *physname,
1735*007c2a45Smiod 			   enum debug_visibility visibility,
1736*007c2a45Smiod 			   bfd_boolean constp, bfd_boolean volatilep,
1737*007c2a45Smiod 			   bfd_vma voffset, bfd_boolean contextp)
1738c88b1d6cSniklas {
1739c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1740c88b1d6cSniklas 
1741c074d1c9Sdrahn   return stab_class_method_var (info, physname, visibility, FALSE, constp,
1742c88b1d6cSniklas 				volatilep, voffset, contextp);
1743c88b1d6cSniklas }
1744c88b1d6cSniklas 
1745c88b1d6cSniklas /* Add a static variant to the current method.  */
1746c88b1d6cSniklas 
1747c074d1c9Sdrahn static bfd_boolean
stab_class_static_method_variant(void * p,const char * physname,enum debug_visibility visibility,bfd_boolean constp,bfd_boolean volatilep)1748*007c2a45Smiod stab_class_static_method_variant (void *p, const char *physname,
1749*007c2a45Smiod 				  enum debug_visibility visibility,
1750*007c2a45Smiod 				  bfd_boolean constp, bfd_boolean volatilep)
1751c88b1d6cSniklas {
1752c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1753c88b1d6cSniklas 
1754c074d1c9Sdrahn   return stab_class_method_var (info, physname, visibility, TRUE, constp,
1755c074d1c9Sdrahn 				volatilep, 0, FALSE);
1756c88b1d6cSniklas }
1757c88b1d6cSniklas 
1758c88b1d6cSniklas /* Finish up a method.  */
1759c88b1d6cSniklas 
1760c074d1c9Sdrahn static bfd_boolean
stab_class_end_method(void * p)1761*007c2a45Smiod stab_class_end_method (void *p)
1762c88b1d6cSniklas {
1763c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1764c88b1d6cSniklas 
1765c88b1d6cSniklas   assert (info->type_stack != NULL && info->type_stack->methods != NULL);
1766c88b1d6cSniklas 
1767c88b1d6cSniklas   /* We allocated enough room on info->type_stack->methods to add the
1768c88b1d6cSniklas      trailing semicolon.  */
1769c88b1d6cSniklas   strcat (info->type_stack->methods, ";");
1770c88b1d6cSniklas 
1771c074d1c9Sdrahn   return TRUE;
1772c88b1d6cSniklas }
1773c88b1d6cSniklas 
1774c88b1d6cSniklas /* Finish up a class.  */
1775c88b1d6cSniklas 
1776c074d1c9Sdrahn static bfd_boolean
stab_end_class_type(void * p)1777*007c2a45Smiod stab_end_class_type (void *p)
1778c88b1d6cSniklas {
1779c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1780c88b1d6cSniklas   size_t len;
1781b305b0f1Sespie   unsigned int i = 0;
1782c88b1d6cSniklas   char *buf;
1783c88b1d6cSniklas 
1784c88b1d6cSniklas   assert (info->type_stack != NULL && info->type_stack->fields != NULL);
1785c88b1d6cSniklas 
1786c88b1d6cSniklas   /* Work out the size we need to allocate for the class definition.  */
1787c88b1d6cSniklas 
1788c88b1d6cSniklas   len = (strlen (info->type_stack->string)
1789c88b1d6cSniklas 	 + strlen (info->type_stack->fields)
1790c88b1d6cSniklas 	 + 10);
1791c88b1d6cSniklas   if (info->type_stack->baseclasses != NULL)
1792c88b1d6cSniklas     {
1793c88b1d6cSniklas       len += 20;
1794c88b1d6cSniklas       for (i = 0; info->type_stack->baseclasses[i] != NULL; i++)
1795c88b1d6cSniklas 	len += strlen (info->type_stack->baseclasses[i]);
1796c88b1d6cSniklas     }
1797c88b1d6cSniklas   if (info->type_stack->methods != NULL)
1798c88b1d6cSniklas     len += strlen (info->type_stack->methods);
1799c88b1d6cSniklas   if (info->type_stack->vtable != NULL)
1800c88b1d6cSniklas     len += strlen (info->type_stack->vtable);
1801c88b1d6cSniklas 
1802c88b1d6cSniklas   /* Build the class definition.  */
1803c88b1d6cSniklas 
1804c88b1d6cSniklas   buf = (char *) xmalloc (len);
1805c88b1d6cSniklas 
1806c88b1d6cSniklas   strcpy (buf, info->type_stack->string);
1807c88b1d6cSniklas 
1808c88b1d6cSniklas   if (info->type_stack->baseclasses != NULL)
1809c88b1d6cSniklas     {
1810c88b1d6cSniklas       sprintf (buf + strlen (buf), "!%u,", i);
1811c88b1d6cSniklas       for (i = 0; info->type_stack->baseclasses[i] != NULL; i++)
1812c88b1d6cSniklas 	{
1813c88b1d6cSniklas 	  strcat (buf, info->type_stack->baseclasses[i]);
1814c88b1d6cSniklas 	  free (info->type_stack->baseclasses[i]);
1815c88b1d6cSniklas 	}
1816c88b1d6cSniklas       free (info->type_stack->baseclasses);
1817c88b1d6cSniklas       info->type_stack->baseclasses = NULL;
1818c88b1d6cSniklas     }
1819c88b1d6cSniklas 
1820c88b1d6cSniklas   strcat (buf, info->type_stack->fields);
1821c88b1d6cSniklas   free (info->type_stack->fields);
1822c88b1d6cSniklas   info->type_stack->fields = NULL;
1823c88b1d6cSniklas 
1824c88b1d6cSniklas   if (info->type_stack->methods != NULL)
1825c88b1d6cSniklas     {
1826c88b1d6cSniklas       strcat (buf, info->type_stack->methods);
1827c88b1d6cSniklas       free (info->type_stack->methods);
1828c88b1d6cSniklas       info->type_stack->methods = NULL;
1829c88b1d6cSniklas     }
1830c88b1d6cSniklas 
1831c88b1d6cSniklas   strcat (buf, ";");
1832c88b1d6cSniklas 
1833c88b1d6cSniklas   if (info->type_stack->vtable != NULL)
1834c88b1d6cSniklas     {
1835c88b1d6cSniklas       strcat (buf, info->type_stack->vtable);
1836c88b1d6cSniklas       free (info->type_stack->vtable);
1837c88b1d6cSniklas       info->type_stack->vtable = NULL;
1838c88b1d6cSniklas     }
1839c88b1d6cSniklas 
1840c88b1d6cSniklas   /* Replace the string on the top of the stack with the complete
1841c88b1d6cSniklas      class definition.  */
1842c88b1d6cSniklas   free (info->type_stack->string);
1843c88b1d6cSniklas   info->type_stack->string = buf;
1844c88b1d6cSniklas 
1845c074d1c9Sdrahn   return TRUE;
1846c88b1d6cSniklas }
1847c88b1d6cSniklas 
1848c88b1d6cSniklas /* Push a typedef which was previously defined.  */
1849c88b1d6cSniklas 
1850c074d1c9Sdrahn static bfd_boolean
stab_typedef_type(void * p,const char * name)1851*007c2a45Smiod stab_typedef_type (void *p, const char *name)
1852c88b1d6cSniklas {
1853c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1854c88b1d6cSniklas   struct string_hash_entry *h;
1855c88b1d6cSniklas 
1856c074d1c9Sdrahn   h = string_hash_lookup (&info->typedef_hash, name, FALSE, FALSE);
1857c88b1d6cSniklas   assert (h != NULL && h->index > 0);
1858c88b1d6cSniklas 
1859c88b1d6cSniklas   return stab_push_defined_type (info, h->index, h->size);
1860c88b1d6cSniklas }
1861c88b1d6cSniklas 
1862c88b1d6cSniklas /* Push a struct, union or class tag.  */
1863c88b1d6cSniklas 
1864c074d1c9Sdrahn static bfd_boolean
stab_tag_type(void * p,const char * name,unsigned int id,enum debug_type_kind kind)1865*007c2a45Smiod stab_tag_type (void *p, const char *name, unsigned int id,
1866*007c2a45Smiod 	       enum debug_type_kind kind)
1867c88b1d6cSniklas {
1868c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1869c88b1d6cSniklas   long index;
1870c88b1d6cSniklas   unsigned int size;
1871c88b1d6cSniklas 
1872c88b1d6cSniklas   index = stab_get_struct_index (info, name, id, kind, &size);
1873c88b1d6cSniklas   if (index < 0)
1874c074d1c9Sdrahn     return FALSE;
1875c88b1d6cSniklas 
1876c88b1d6cSniklas   return stab_push_defined_type (info, index, size);
1877c88b1d6cSniklas }
1878c88b1d6cSniklas 
1879c88b1d6cSniklas /* Define a typedef.  */
1880c88b1d6cSniklas 
1881c074d1c9Sdrahn static bfd_boolean
stab_typdef(void * p,const char * name)1882*007c2a45Smiod stab_typdef (void *p, const char *name)
1883c88b1d6cSniklas {
1884c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1885c88b1d6cSniklas   long index;
1886c88b1d6cSniklas   unsigned int size;
1887c88b1d6cSniklas   char *s, *buf;
1888c88b1d6cSniklas   struct string_hash_entry *h;
1889c88b1d6cSniklas 
1890c88b1d6cSniklas   index = info->type_stack->index;
1891c88b1d6cSniklas   size = info->type_stack->size;
1892c88b1d6cSniklas   s = stab_pop_type (info);
1893c88b1d6cSniklas 
1894c88b1d6cSniklas   buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
1895c88b1d6cSniklas 
1896c88b1d6cSniklas   if (index > 0)
1897c88b1d6cSniklas     sprintf (buf, "%s:t%s", name, s);
1898c88b1d6cSniklas   else
1899c88b1d6cSniklas     {
1900c88b1d6cSniklas       index = info->type_index;
1901c88b1d6cSniklas       ++info->type_index;
1902c88b1d6cSniklas       sprintf (buf, "%s:t%ld=%s", name, index, s);
1903c88b1d6cSniklas     }
1904c88b1d6cSniklas 
1905c88b1d6cSniklas   free (s);
1906c88b1d6cSniklas 
1907c88b1d6cSniklas   if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
1908c074d1c9Sdrahn     return FALSE;
1909c88b1d6cSniklas 
1910c88b1d6cSniklas   free (buf);
1911c88b1d6cSniklas 
1912c074d1c9Sdrahn   h = string_hash_lookup (&info->typedef_hash, name, TRUE, FALSE);
1913c88b1d6cSniklas   if (h == NULL)
1914c88b1d6cSniklas     {
1915b305b0f1Sespie       non_fatal (_("string_hash_lookup failed: %s"),
1916c88b1d6cSniklas 		 bfd_errmsg (bfd_get_error ()));
1917c074d1c9Sdrahn       return FALSE;
1918c88b1d6cSniklas     }
1919c88b1d6cSniklas 
1920c88b1d6cSniklas   /* I don't think we care about redefinitions.  */
1921c88b1d6cSniklas 
1922c88b1d6cSniklas   h->index = index;
1923c88b1d6cSniklas   h->size = size;
1924c88b1d6cSniklas 
1925c074d1c9Sdrahn   return TRUE;
1926c88b1d6cSniklas }
1927c88b1d6cSniklas 
1928c88b1d6cSniklas /* Define a tag.  */
1929c88b1d6cSniklas 
1930c074d1c9Sdrahn static bfd_boolean
stab_tag(void * p,const char * tag)1931*007c2a45Smiod stab_tag (void *p, const char *tag)
1932c88b1d6cSniklas {
1933c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1934c88b1d6cSniklas   char *s, *buf;
1935c88b1d6cSniklas 
1936c88b1d6cSniklas   s = stab_pop_type (info);
1937c88b1d6cSniklas 
1938c88b1d6cSniklas   buf = (char *) xmalloc (strlen (tag) + strlen (s) + 3);
1939c88b1d6cSniklas 
1940c88b1d6cSniklas   sprintf (buf, "%s:T%s", tag, s);
1941c88b1d6cSniklas   free (s);
1942c88b1d6cSniklas 
1943c88b1d6cSniklas   if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
1944c074d1c9Sdrahn     return FALSE;
1945c88b1d6cSniklas 
1946c88b1d6cSniklas   free (buf);
1947c88b1d6cSniklas 
1948c074d1c9Sdrahn   return TRUE;
1949c88b1d6cSniklas }
1950c88b1d6cSniklas 
1951c88b1d6cSniklas /* Define an integer constant.  */
1952c88b1d6cSniklas 
1953c074d1c9Sdrahn static bfd_boolean
stab_int_constant(void * p,const char * name,bfd_vma val)1954*007c2a45Smiod stab_int_constant (void *p, const char *name, bfd_vma val)
1955c88b1d6cSniklas {
1956c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1957c88b1d6cSniklas   char *buf;
1958c88b1d6cSniklas 
1959c88b1d6cSniklas   buf = (char *) xmalloc (strlen (name) + 20);
1960c88b1d6cSniklas   sprintf (buf, "%s:c=i%ld", name, (long) val);
1961c88b1d6cSniklas 
1962c88b1d6cSniklas   if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
1963c074d1c9Sdrahn     return FALSE;
1964c88b1d6cSniklas 
1965c88b1d6cSniklas   free (buf);
1966c88b1d6cSniklas 
1967c074d1c9Sdrahn   return TRUE;
1968c88b1d6cSniklas }
1969c88b1d6cSniklas 
1970c88b1d6cSniklas /* Define a floating point constant.  */
1971c88b1d6cSniklas 
1972c074d1c9Sdrahn static bfd_boolean
stab_float_constant(void * p,const char * name,double val)1973*007c2a45Smiod stab_float_constant (void *p, const char *name, double val)
1974c88b1d6cSniklas {
1975c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1976c88b1d6cSniklas   char *buf;
1977c88b1d6cSniklas 
1978c88b1d6cSniklas   buf = (char *) xmalloc (strlen (name) + 20);
1979c88b1d6cSniklas   sprintf (buf, "%s:c=f%g", name, val);
1980c88b1d6cSniklas 
1981c88b1d6cSniklas   if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
1982c074d1c9Sdrahn     return FALSE;
1983c88b1d6cSniklas 
1984c88b1d6cSniklas   free (buf);
1985c88b1d6cSniklas 
1986c074d1c9Sdrahn   return TRUE;
1987c88b1d6cSniklas }
1988c88b1d6cSniklas 
1989c88b1d6cSniklas /* Define a typed constant.  */
1990c88b1d6cSniklas 
1991c074d1c9Sdrahn static bfd_boolean
stab_typed_constant(void * p,const char * name,bfd_vma val)1992*007c2a45Smiod stab_typed_constant (void *p, const char *name, bfd_vma val)
1993c88b1d6cSniklas {
1994c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
1995c88b1d6cSniklas   char *s, *buf;
1996c88b1d6cSniklas 
1997c88b1d6cSniklas   s = stab_pop_type (info);
1998c88b1d6cSniklas 
1999c88b1d6cSniklas   buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
2000c88b1d6cSniklas   sprintf (buf, "%s:c=e%s,%ld", name, s, (long) val);
2001c88b1d6cSniklas   free (s);
2002c88b1d6cSniklas 
2003c88b1d6cSniklas   if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
2004c074d1c9Sdrahn     return FALSE;
2005c88b1d6cSniklas 
2006c88b1d6cSniklas   free (buf);
2007c88b1d6cSniklas 
2008c074d1c9Sdrahn   return TRUE;
2009c88b1d6cSniklas }
2010c88b1d6cSniklas 
2011c88b1d6cSniklas /* Record a variable.  */
2012c88b1d6cSniklas 
2013c074d1c9Sdrahn static bfd_boolean
stab_variable(void * p,const char * name,enum debug_var_kind kind,bfd_vma val)2014*007c2a45Smiod stab_variable (void *p, const char *name, enum debug_var_kind kind,
2015*007c2a45Smiod 	       bfd_vma val)
2016c88b1d6cSniklas {
2017c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
2018c88b1d6cSniklas   char *s, *buf;
2019c88b1d6cSniklas   int stab_type;
2020c88b1d6cSniklas   const char *kindstr;
2021c88b1d6cSniklas 
2022c88b1d6cSniklas   s = stab_pop_type (info);
2023c88b1d6cSniklas 
2024c88b1d6cSniklas   switch (kind)
2025c88b1d6cSniklas     {
2026c88b1d6cSniklas     default:
2027c88b1d6cSniklas       abort ();
2028c88b1d6cSniklas 
2029c88b1d6cSniklas     case DEBUG_GLOBAL:
2030c88b1d6cSniklas       stab_type = N_GSYM;
2031c88b1d6cSniklas       kindstr = "G";
2032c88b1d6cSniklas       break;
2033c88b1d6cSniklas 
2034c88b1d6cSniklas     case DEBUG_STATIC:
2035c88b1d6cSniklas       stab_type = N_STSYM;
2036c88b1d6cSniklas       kindstr = "S";
2037c88b1d6cSniklas       break;
2038c88b1d6cSniklas 
2039c88b1d6cSniklas     case DEBUG_LOCAL_STATIC:
2040c88b1d6cSniklas       stab_type = N_STSYM;
2041c88b1d6cSniklas       kindstr = "V";
2042c88b1d6cSniklas       break;
2043c88b1d6cSniklas 
2044c88b1d6cSniklas     case DEBUG_LOCAL:
2045c88b1d6cSniklas       stab_type = N_LSYM;
2046c88b1d6cSniklas       kindstr = "";
2047c88b1d6cSniklas 
2048c88b1d6cSniklas       /* Make sure that this is a type reference or definition.  */
2049c074d1c9Sdrahn       if (! ISDIGIT (*s))
2050c88b1d6cSniklas 	{
2051c88b1d6cSniklas 	  char *n;
2052c88b1d6cSniklas 	  long index;
2053c88b1d6cSniklas 
2054c88b1d6cSniklas 	  index = info->type_index;
2055c88b1d6cSniklas 	  ++info->type_index;
2056c88b1d6cSniklas 	  n = (char *) xmalloc (strlen (s) + 20);
2057c88b1d6cSniklas 	  sprintf (n, "%ld=%s", index, s);
2058c88b1d6cSniklas 	  free (s);
2059c88b1d6cSniklas 	  s = n;
2060c88b1d6cSniklas 	}
2061c88b1d6cSniklas       break;
2062c88b1d6cSniklas 
2063c88b1d6cSniklas     case DEBUG_REGISTER:
2064c88b1d6cSniklas       stab_type = N_RSYM;
2065c88b1d6cSniklas       kindstr = "r";
2066c88b1d6cSniklas       break;
2067c88b1d6cSniklas     }
2068c88b1d6cSniklas 
2069c88b1d6cSniklas   buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
2070c88b1d6cSniklas   sprintf (buf, "%s:%s%s", name, kindstr, s);
2071c88b1d6cSniklas   free (s);
2072c88b1d6cSniklas 
2073c88b1d6cSniklas   if (! stab_write_symbol (info, stab_type, 0, val, buf))
2074c074d1c9Sdrahn     return FALSE;
2075c88b1d6cSniklas 
2076c88b1d6cSniklas   free (buf);
2077c88b1d6cSniklas 
2078c074d1c9Sdrahn   return TRUE;
2079c88b1d6cSniklas }
2080c88b1d6cSniklas 
2081c88b1d6cSniklas /* Start outputting a function.  */
2082c88b1d6cSniklas 
2083c074d1c9Sdrahn static bfd_boolean
stab_start_function(void * p,const char * name,bfd_boolean globalp)2084*007c2a45Smiod stab_start_function (void *p, const char *name, bfd_boolean globalp)
2085c88b1d6cSniklas {
2086c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
2087c88b1d6cSniklas   char *rettype, *buf;
2088c88b1d6cSniklas 
2089c88b1d6cSniklas   assert (info->nesting == 0 && info->fun_offset == -1);
2090c88b1d6cSniklas 
2091c88b1d6cSniklas   rettype = stab_pop_type (info);
2092c88b1d6cSniklas 
2093c88b1d6cSniklas   buf = (char *) xmalloc (strlen (name) + strlen (rettype) + 3);
2094c88b1d6cSniklas   sprintf (buf, "%s:%c%s", name,
2095c88b1d6cSniklas 	   globalp ? 'F' : 'f',
2096c88b1d6cSniklas 	   rettype);
2097c88b1d6cSniklas 
2098c88b1d6cSniklas   /* We don't know the value now, so we set it in start_block.  */
2099c88b1d6cSniklas   info->fun_offset = info->symbols_size;
2100c88b1d6cSniklas 
2101c88b1d6cSniklas   if (! stab_write_symbol (info, N_FUN, 0, 0, buf))
2102c074d1c9Sdrahn     return FALSE;
2103c88b1d6cSniklas 
2104c88b1d6cSniklas   free (buf);
2105c88b1d6cSniklas 
2106c074d1c9Sdrahn   return TRUE;
2107c88b1d6cSniklas }
2108c88b1d6cSniklas 
2109c88b1d6cSniklas /* Output a function parameter.  */
2110c88b1d6cSniklas 
2111c074d1c9Sdrahn static bfd_boolean
stab_function_parameter(void * p,const char * name,enum debug_parm_kind kind,bfd_vma val)2112*007c2a45Smiod stab_function_parameter (void *p, const char *name, enum debug_parm_kind kind, bfd_vma val)
2113c88b1d6cSniklas {
2114c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
2115c88b1d6cSniklas   char *s, *buf;
2116c88b1d6cSniklas   int stab_type;
2117c88b1d6cSniklas   char kindc;
2118c88b1d6cSniklas 
2119c88b1d6cSniklas   s = stab_pop_type (info);
2120c88b1d6cSniklas 
2121c88b1d6cSniklas   switch (kind)
2122c88b1d6cSniklas     {
2123c88b1d6cSniklas     default:
2124c88b1d6cSniklas       abort ();
2125c88b1d6cSniklas 
2126c88b1d6cSniklas     case DEBUG_PARM_STACK:
2127c88b1d6cSniklas       stab_type = N_PSYM;
2128c88b1d6cSniklas       kindc = 'p';
2129c88b1d6cSniklas       break;
2130c88b1d6cSniklas 
2131c88b1d6cSniklas     case DEBUG_PARM_REG:
2132c88b1d6cSniklas       stab_type = N_RSYM;
2133c88b1d6cSniklas       kindc = 'P';
2134c88b1d6cSniklas       break;
2135c88b1d6cSniklas 
2136c88b1d6cSniklas     case DEBUG_PARM_REFERENCE:
2137c88b1d6cSniklas       stab_type = N_PSYM;
2138c88b1d6cSniklas       kindc = 'v';
2139c88b1d6cSniklas       break;
2140c88b1d6cSniklas 
2141c88b1d6cSniklas     case DEBUG_PARM_REF_REG:
2142c88b1d6cSniklas       stab_type = N_RSYM;
2143c88b1d6cSniklas       kindc = 'a';
2144c88b1d6cSniklas       break;
2145c88b1d6cSniklas     }
2146c88b1d6cSniklas 
2147c88b1d6cSniklas   buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
2148c88b1d6cSniklas   sprintf (buf, "%s:%c%s", name, kindc, s);
2149c88b1d6cSniklas   free (s);
2150c88b1d6cSniklas 
2151c88b1d6cSniklas   if (! stab_write_symbol (info, stab_type, 0, val, buf))
2152c074d1c9Sdrahn     return FALSE;
2153c88b1d6cSniklas 
2154c88b1d6cSniklas   free (buf);
2155c88b1d6cSniklas 
2156c074d1c9Sdrahn   return TRUE;
2157c88b1d6cSniklas }
2158c88b1d6cSniklas 
2159c88b1d6cSniklas /* Start a block.  */
2160c88b1d6cSniklas 
2161c074d1c9Sdrahn static bfd_boolean
stab_start_block(void * p,bfd_vma addr)2162*007c2a45Smiod stab_start_block (void *p, bfd_vma addr)
2163c88b1d6cSniklas {
2164c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
2165c88b1d6cSniklas 
2166c88b1d6cSniklas   /* Fill in any slots which have been waiting for the first known
2167c88b1d6cSniklas      text address.  */
2168c88b1d6cSniklas 
2169c88b1d6cSniklas   if (info->so_offset != -1)
2170c88b1d6cSniklas     {
2171c88b1d6cSniklas       bfd_put_32 (info->abfd, addr, info->symbols + info->so_offset + 8);
2172c88b1d6cSniklas       info->so_offset = -1;
2173c88b1d6cSniklas     }
2174c88b1d6cSniklas 
2175c88b1d6cSniklas   if (info->fun_offset != -1)
2176c88b1d6cSniklas     {
2177c88b1d6cSniklas       bfd_put_32 (info->abfd, addr, info->symbols + info->fun_offset + 8);
2178c88b1d6cSniklas       info->fun_offset = -1;
2179c88b1d6cSniklas     }
2180c88b1d6cSniklas 
2181c88b1d6cSniklas   ++info->nesting;
2182c88b1d6cSniklas 
2183c88b1d6cSniklas   /* We will be called with a top level block surrounding the
2184c88b1d6cSniklas      function, but stabs information does not output that block, so we
2185c88b1d6cSniklas      ignore it.  */
2186c88b1d6cSniklas 
2187c88b1d6cSniklas   if (info->nesting == 1)
2188c88b1d6cSniklas     {
2189c88b1d6cSniklas       info->fnaddr = addr;
2190c074d1c9Sdrahn       return TRUE;
2191c88b1d6cSniklas     }
2192c88b1d6cSniklas 
2193c88b1d6cSniklas   /* We have to output the LBRAC symbol after any variables which are
2194c88b1d6cSniklas      declared inside the block.  We postpone the LBRAC until the next
2195c88b1d6cSniklas      start_block or end_block.  */
2196c88b1d6cSniklas 
2197c88b1d6cSniklas   /* If we have postponed an LBRAC, output it now.  */
2198c88b1d6cSniklas   if (info->pending_lbrac != (bfd_vma) -1)
2199c88b1d6cSniklas     {
2200c88b1d6cSniklas       if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac,
2201c88b1d6cSniklas 			       (const char *) NULL))
2202c074d1c9Sdrahn 	return FALSE;
2203c88b1d6cSniklas     }
2204c88b1d6cSniklas 
2205c88b1d6cSniklas   /* Remember the address and output it later.  */
2206c88b1d6cSniklas 
2207c88b1d6cSniklas   info->pending_lbrac = addr - info->fnaddr;
2208c88b1d6cSniklas 
2209c074d1c9Sdrahn   return TRUE;
2210c88b1d6cSniklas }
2211c88b1d6cSniklas 
2212c88b1d6cSniklas /* End a block.  */
2213c88b1d6cSniklas 
2214c074d1c9Sdrahn static bfd_boolean
stab_end_block(void * p,bfd_vma addr)2215*007c2a45Smiod stab_end_block (void *p, bfd_vma addr)
2216c88b1d6cSniklas {
2217c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
2218c88b1d6cSniklas 
2219c88b1d6cSniklas   if (addr > info->last_text_address)
2220c88b1d6cSniklas     info->last_text_address = addr;
2221c88b1d6cSniklas 
2222c88b1d6cSniklas   /* If we have postponed an LBRAC, output it now.  */
2223c88b1d6cSniklas   if (info->pending_lbrac != (bfd_vma) -1)
2224c88b1d6cSniklas     {
2225c88b1d6cSniklas       if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac,
2226c88b1d6cSniklas 			       (const char *) NULL))
2227c074d1c9Sdrahn 	return FALSE;
2228c88b1d6cSniklas       info->pending_lbrac = (bfd_vma) -1;
2229c88b1d6cSniklas     }
2230c88b1d6cSniklas 
2231c88b1d6cSniklas   assert (info->nesting > 0);
2232c88b1d6cSniklas 
2233c88b1d6cSniklas   --info->nesting;
2234c88b1d6cSniklas 
2235c88b1d6cSniklas   /* We ignore the outermost block.  */
2236c88b1d6cSniklas   if (info->nesting == 0)
2237c074d1c9Sdrahn     return TRUE;
2238c88b1d6cSniklas 
2239c88b1d6cSniklas   return stab_write_symbol (info, N_RBRAC, 0, addr - info->fnaddr,
2240c88b1d6cSniklas 			    (const char *) NULL);
2241c88b1d6cSniklas }
2242c88b1d6cSniklas 
2243c88b1d6cSniklas /* End a function.  */
2244c88b1d6cSniklas 
2245c074d1c9Sdrahn static bfd_boolean
stab_end_function(void * p ATTRIBUTE_UNUSED)2246*007c2a45Smiod stab_end_function (void *p ATTRIBUTE_UNUSED)
2247c88b1d6cSniklas {
2248c074d1c9Sdrahn   return TRUE;
2249c88b1d6cSniklas }
2250c88b1d6cSniklas 
2251c88b1d6cSniklas /* Output a line number.  */
2252c88b1d6cSniklas 
2253c074d1c9Sdrahn static bfd_boolean
stab_lineno(void * p,const char * file,unsigned long lineno,bfd_vma addr)2254*007c2a45Smiod stab_lineno (void *p, const char *file, unsigned long lineno, bfd_vma addr)
2255c88b1d6cSniklas {
2256c88b1d6cSniklas   struct stab_write_handle *info = (struct stab_write_handle *) p;
2257c88b1d6cSniklas 
2258c88b1d6cSniklas   assert (info->lineno_filename != NULL);
2259c88b1d6cSniklas 
2260c88b1d6cSniklas   if (addr > info->last_text_address)
2261c88b1d6cSniklas     info->last_text_address = addr;
2262c88b1d6cSniklas 
2263c88b1d6cSniklas   if (strcmp (file, info->lineno_filename) != 0)
2264c88b1d6cSniklas     {
2265c88b1d6cSniklas       if (! stab_write_symbol (info, N_SOL, 0, addr, file))
2266c074d1c9Sdrahn 	return FALSE;
2267c88b1d6cSniklas       info->lineno_filename = file;
2268c88b1d6cSniklas     }
2269c88b1d6cSniklas 
2270c88b1d6cSniklas   return stab_write_symbol (info, N_SLINE, lineno, addr - info->fnaddr,
2271c88b1d6cSniklas 			    (const char *) NULL);
2272c88b1d6cSniklas }
2273