4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * In this mode, we generate forthdebug macros as requested by the input
31 * template, the format of which is given below.
33 * These templates have the following elements:
37 * Given the name of a structure, union, or enum type, a forthdebug macro
38 * is created that will dump the members of the type. The type can be
39 * specified as a standalone structure, union, or enum, or it can be
40 * described relative to another structure or union as "type.member".
42 * By default, all struct members, union members, or enum values, as
43 * appropriate, will be printed. An alternate form allows specific members
44 * of struct or union types to be printed. Both forms must be followed by a
45 * blank line. In the specific-member case, an optional format specifier can
46 * be provided that will be used to dump the contents of the member.
47 * Builtins `d' and `x' can be used to dump the member in decimal or
48 * hexadecimal, respectively. Alternatively, a custom formatter can be
51 * 2. Model-specific sections
53 * `model_start' / `model_end' pairs function as an #ifdef for the ctfstabs
54 * tool. They take, as an argument, either `ilp32' or `lp64'. If a 64-bit
55 * macro is being generated (if a 64-bit object file is being used), lines
56 * between `lp64' model pairs will be processed, but lines between `ilp32'
57 * pairs will be omitted. The reverse is true for 32-bit macros.
61 * Portions of the input template file enclosed within `forth_start' /
62 * `forth_end' pairs and between `verbatim_begin' / `verbatim_end' pairs
63 * will be copied as-is to the output file.
67 * Lines beginning with backslashes are ignored.
71 * \ dump the `foo' structure
74 * \ dump the `a' and `b' members of the `bar' structure. dump member `b'
80 * \ dump the `big' member of the `baz' structure in 64-bit macros, and
81 * \ the `small' member in 32-bit macros.
90 * \ copy `literal 1' and `literal 2' to the output file
98 * For a more complex example, see common.fdbg.
106 #include "ctf_headers.h"
107 #include "ctfstabs.h"
112 char *fth_curtype
; /* name of the type being processed */
113 static fth_type_ops_t
*fth_type_ops
; /* see forth.h */
115 static char *fth_model
; /* the current macro type - for model_start */
116 static int fth_ignoring
; /* in a non-matching model_start/end pair */
117 static int fth_copying
; /* in a verbatim_* or forth_* pair */
120 fth_init(char *model
)
129 fth_null_header(ctf_id_t tid
)
136 fth_null_members(char *memfilter
, char *format
)
142 fth_null_trailer(void)
147 static fth_type_ops_t fth_null_ops
= {
155 find_member_cb(const char *memname
, ctf_id_t tid
, ulong_t off
, void *arg
)
157 char *memtofind
= arg
;
159 if (strcmp(memname
, memtofind
) == 0)
165 /* find the tid of a specified member */
167 find_member(ctf_id_t tid
, char *memname
)
169 return (ctf_member_iter(ctf
, tid
, find_member_cb
, memname
));
175 * Once we figure out the type of the thing that we're supposed to dump (struct,
176 * union, or enum), we select the proper type-specific ops-vector for dumping.
179 fth_section_init(char *fullname
)
181 ctf_id_t ltid
= 0, tid
;
182 char *curtype
, *lpart
, *part
, *npart
;
185 curtype
= xstrdup(fullname
);
187 part
= strtok(fullname
, ".");
190 * First figure out what sort of type we're looking at. Life would be
191 * simple if we were only going to get type names, but it's not - we
192 * could also get `type.member'. In that case, we need to figure out
193 * (and dump) the type of `member' instead.
197 /* First part - the struct name */
198 if ((tid
= find_type(part
)) == CTF_ERR
||
199 (tid
= ctf_type_resolve(ctf
, tid
)) == CTF_ERR
||
200 (kind
= ctf_type_kind(ctf
, tid
)) == CTF_ERR
) {
202 return (parse_warn("Couldn't find %s: %s",
203 part
, ctf_errmsg(ctf_errno(ctf
))));
206 /* Second (or more) part - the member name */
207 if (lkind
!= CTF_K_STRUCT
&& lkind
!= CTF_K_UNION
) {
209 return (parse_warn("%s isn't a struct/union",
213 if ((tid
= find_member(ltid
, part
)) <= 0) {
215 return (parse_warn("%s isn't a member of %s",
219 if ((kind
= ctf_type_kind(ctf
, tid
)) == CTF_ERR
) {
221 return (parse_warn("Can't get kind for %s",
227 * Stop if there aren't any more parts. We use `npart' here
228 * because we don't want to clobber part - we need it later.
230 if ((npart
= strtok(NULL
, ".")) == NULL
)
241 * Pick the right ops vector for dumping.
246 fth_type_ops
= &fth_struct_ops
;
250 fth_type_ops
= &fth_enum_ops
;
254 fth_type_ops
= &fth_null_ops
;
256 return (parse_warn("%s isn't a struct, union, or enum", part
));
259 fth_curtype
= curtype
;
261 return (fth_type_ops
->fto_header(tid
));
265 fth_section_add_member(char *name
, char *format
)
267 if (fth_curtype
== NULL
)
268 return (fth_section_init(name
));
270 if (fth_type_ops
->fto_members(name
, format
) < 0)
277 fth_section_end(void)
279 if (fth_curtype
== NULL
)
282 if (fth_type_ops
->fto_trailer() < 0)
292 fth_process_line(char *line
)
295 char *word
, *name
, *c
;
299 if (strlen(line
) == 0) {
300 if (fth_section_end() < 0)
303 if (fth_copying
== 1 || nblank
++ == 1)
304 (void) fprintf(out
, "\n");
313 if (strcmp(line
, "model_end") == 0) {
318 if (fth_ignoring
== 1)
321 word
= "model_start ";
322 if (strncmp(line
, word
, strlen(word
)) == 0) {
323 for (c
= line
+ strlen(word
); isspace(*c
); c
++);
324 if (strlen(c
) == strlen(fth_model
) &&
325 strncmp(c
, fth_model
, strlen(fth_model
)) == 0)
332 if (strcmp(line
, "verbatim_end") == 0 ||
333 strcmp(line
, "forth_end") == 0) {
334 char *start
= (strcmp(line
, "verbatim_end") == 0 ?
335 "verbatim_begin" : "forth_start");
337 if (fth_copying
== 0) {
338 (void) parse_warn("Found %s without matching %s",
340 if (fth_curtype
!= NULL
)
341 (void) fth_section_end();
348 if (fth_copying
== 1) {
349 (void) fprintf(out
, "%s\n", line
);
353 if (strcmp(line
, "verbatim_begin") == 0 ||
354 strcmp(line
, "forth_start") == 0) {
355 if (fth_curtype
!= NULL
) {
356 (void) parse_warn("Expected blank line between %s "
357 "macro and %s", fth_curtype
, line
);
358 return (fth_section_end());
365 for (n
= 1, word
= strtok(line
, " \t"); word
!= NULL
;
366 word
= strtok(NULL
, " \t"), n
++) {
372 (void) parse_warn("Too many words");
375 return (fth_section_add_member(name
, format
));
381 return (fth_section_end());
384 proc_ops_t fth_ops
= {