1 /*
2  * CDDL HEADER START
3  *
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
7  * with the License.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 #ifdef HAVE_NBTOOL_CONFIG_H
23 #include "nbtool_config.h"
24 #endif
25 /*
26  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 #pragma ident       "%Z%%M%   %I%       %E% SMI"
31 
32 /*
33  * CTF Declaration Stack
34  *
35  * In order to implement ctf_type_name(), we must convert a type graph back
36  * into a C type declaration.  Unfortunately, a type graph represents a storage
37  * class ordering of the type whereas a type declaration must obey the C rules
38  * for operator precedence, and the two orderings are frequently in conflict.
39  * For example, consider these CTF type graphs and their C declarations:
40  *
41  * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
42  * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
43  *
44  * In each case, parentheses are used to raise operator * to higher lexical
45  * precedence, so the string form of the C declaration cannot be constructed by
46  * walking the type graph links and forming the string from left to right.
47  *
48  * The functions in this file build a set of stacks from the type graph nodes
49  * corresponding to the C operator precedence levels in the appropriate order.
50  * The code in ctf_type_name() can then iterate over the levels and nodes in
51  * lexical precedence order and construct the final C declaration string.
52  */
53 
54 #include <ctf_impl.h>
55 
56 void
ctf_decl_init(ctf_decl_t * cd,char * buf,size_t len)57 ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
58 {
59           int i;
60 
61           memset(cd, 0, sizeof (ctf_decl_t));
62 
63           for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
64                     cd->cd_order[i] = CTF_PREC_BASE - 1;
65 
66           cd->cd_qualp = CTF_PREC_BASE;
67           cd->cd_ordp = CTF_PREC_BASE;
68 
69           cd->cd_buf = buf;
70           cd->cd_ptr = buf;
71           cd->cd_end = buf + len;
72 }
73 
74 void
ctf_decl_fini(ctf_decl_t * cd)75 ctf_decl_fini(ctf_decl_t *cd)
76 {
77           ctf_decl_node_t *cdp, *ndp;
78           int i;
79 
80           for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
81                     for (cdp = ctf_list_next(&cd->cd_nodes[i]);
82                         cdp != NULL; cdp = ndp) {
83                               ndp = ctf_list_next(cdp);
84                               ctf_free(cdp, sizeof (ctf_decl_node_t));
85                     }
86           }
87 }
88 
89 void
ctf_decl_push(ctf_decl_t * cd,ctf_file_t * fp,ctf_id_t type)90 ctf_decl_push(ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type)
91 {
92           ctf_decl_node_t *cdp;
93           ctf_decl_prec_t prec;
94           uint_t ctype, kind, n = 1;
95           int is_qual = 0;
96 
97           const void *tp;
98           ctf_arinfo_t ar;
99 
100           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) {
101                     cd->cd_err = fp->ctf_errno;
102                     return;
103           }
104 
105           ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
106           ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
107 
108           switch (kind) {
109           case CTF_K_ARRAY:
110                     (void) ctf_array_info(fp, type, &ar);
111                     ctf_decl_push(cd, fp, ar.ctr_contents);
112                     n = ar.ctr_nelems;
113                     prec = CTF_PREC_ARRAY;
114                     break;
115 
116           case CTF_K_TYPEDEF:
117                     if (ctf_type_rname(fp, tp)[0] == '\0') {
118                               ctf_decl_push(cd, fp, ctype);
119                               return;
120                     }
121                     prec = CTF_PREC_BASE;
122                     break;
123 
124           case CTF_K_FUNCTION:
125                     ctf_decl_push(cd, fp, ctype);
126                     prec = CTF_PREC_FUNCTION;
127                     break;
128 
129           case CTF_K_POINTER:
130                     ctf_decl_push(cd, fp, ctype);
131                     prec = CTF_PREC_POINTER;
132                     break;
133 
134           case CTF_K_VOLATILE:
135           case CTF_K_CONST:
136           case CTF_K_RESTRICT:
137                     ctf_decl_push(cd, fp, ctype);
138                     prec = cd->cd_qualp;
139                     is_qual++;
140                     break;
141 
142           default:
143                     prec = CTF_PREC_BASE;
144           }
145 
146           if ((cdp = ctf_alloc(sizeof (ctf_decl_node_t))) == NULL) {
147                     cd->cd_err = EAGAIN;
148                     return;
149           }
150 
151           cdp->cd_type = type;
152           cdp->cd_kind = kind;
153           cdp->cd_n = n;
154 
155           if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
156                     cd->cd_order[prec] = cd->cd_ordp++;
157 
158           /*
159            * Reset cd_qualp to the highest precedence level that we've seen so
160            * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
161            */
162           if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
163                     cd->cd_qualp = prec;
164 
165           /*
166            * C array declarators are ordered inside out so prepend them.  Also by
167            * convention qualifiers of base types precede the type specifier (e.g.
168            * const int vs. int const) even though the two forms are equivalent.
169            */
170           if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
171                     ctf_list_prepend(&cd->cd_nodes[prec], cdp);
172           else
173                     ctf_list_append(&cd->cd_nodes[prec], cdp);
174 }
175 
176 /*PRINTFLIKE2*/
177 void
ctf_decl_sprintf(ctf_decl_t * cd,const char * format,...)178 ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
179 {
180           size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
181           va_list ap;
182           size_t n;
183 
184           va_start(ap, format);
185           n = vsnprintf(cd->cd_ptr, len, format, ap);
186           va_end(ap);
187 
188           cd->cd_ptr += MIN(n, len);
189           cd->cd_len += n;
190 }
191