]> Git Repo - binutils.git/blob - libctf/ctf-decl.c
bfd, include, ld, binutils, libctf: CTF should use the dynstr/sym
[binutils.git] / libctf / ctf-decl.c
1 /* C declarator syntax glue.
2    Copyright (C) 2019-2020 Free Software Foundation, Inc.
3
4    This file is part of libctf.
5
6    libctf is free software; you can redistribute it and/or modify it under
7    the terms of the GNU General Public License as published by the Free
8    Software Foundation; either version 3, or (at your option) any later
9    version.
10
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14    See the GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; see the file COPYING.  If not see
18    <http://www.gnu.org/licenses/>.  */
19
20 /* CTF Declaration Stack
21
22    In order to implement ctf_type_name(), we must convert a type graph back
23    into a C type declaration.  Unfortunately, a type graph represents a storage
24    class ordering of the type whereas a type declaration must obey the C rules
25    for operator precedence, and the two orderings are frequently in conflict.
26    For example, consider these CTF type graphs and their C declarations:
27
28    CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
29    CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
30
31    In each case, parentheses are used to raise operator * to higher lexical
32    precedence, so the string form of the C declaration cannot be constructed by
33    walking the type graph links and forming the string from left to right.
34
35    The functions in this file build a set of stacks from the type graph nodes
36    corresponding to the C operator precedence levels in the appropriate order.
37    The code in ctf_type_name() can then iterate over the levels and nodes in
38    lexical precedence order and construct the final C declaration string.  */
39
40 #include <ctf-impl.h>
41 #include <string.h>
42
43 void
44 ctf_decl_init (ctf_decl_t *cd)
45 {
46   int i;
47
48   memset (cd, 0, sizeof (ctf_decl_t));
49
50   for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
51     cd->cd_order[i] = CTF_PREC_BASE - 1;
52
53   cd->cd_qualp = CTF_PREC_BASE;
54   cd->cd_ordp = CTF_PREC_BASE;
55 }
56
57 void
58 ctf_decl_fini (ctf_decl_t *cd)
59 {
60   ctf_decl_node_t *cdp, *ndp;
61   int i;
62
63   for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
64     {
65       for (cdp = ctf_list_next (&cd->cd_nodes[i]); cdp != NULL; cdp = ndp)
66         {
67           ndp = ctf_list_next (cdp);
68           free (cdp);
69         }
70     }
71   free (cd->cd_buf);
72 }
73
74 void
75 ctf_decl_push (ctf_decl_t *cd, ctf_dict_t *fp, ctf_id_t type)
76 {
77   ctf_decl_node_t *cdp;
78   ctf_decl_prec_t prec;
79   uint32_t kind, n = 1;
80   int is_qual = 0;
81
82   const ctf_type_t *tp;
83   ctf_arinfo_t ar;
84
85   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
86     {
87       cd->cd_err = fp->ctf_errno;
88       return;
89     }
90
91   switch (kind = LCTF_INFO_KIND (fp, tp->ctt_info))
92     {
93     case CTF_K_ARRAY:
94       (void) ctf_array_info (fp, type, &ar);
95       ctf_decl_push (cd, fp, ar.ctr_contents);
96       n = ar.ctr_nelems;
97       prec = CTF_PREC_ARRAY;
98       break;
99
100     case CTF_K_TYPEDEF:
101       if (ctf_strptr (fp, tp->ctt_name)[0] == '\0')
102         {
103           ctf_decl_push (cd, fp, tp->ctt_type);
104           return;
105         }
106       prec = CTF_PREC_BASE;
107       break;
108
109     case CTF_K_FUNCTION:
110       ctf_decl_push (cd, fp, tp->ctt_type);
111       prec = CTF_PREC_FUNCTION;
112       break;
113
114     case CTF_K_POINTER:
115       ctf_decl_push (cd, fp, tp->ctt_type);
116       prec = CTF_PREC_POINTER;
117       break;
118
119     case CTF_K_SLICE:
120       ctf_decl_push (cd, fp, ctf_type_reference (fp, type));
121       prec = CTF_PREC_BASE;
122       break;
123
124     case CTF_K_VOLATILE:
125     case CTF_K_CONST:
126     case CTF_K_RESTRICT:
127       ctf_decl_push (cd, fp, tp->ctt_type);
128       prec = cd->cd_qualp;
129       is_qual++;
130       break;
131
132     default:
133       prec = CTF_PREC_BASE;
134     }
135
136   if ((cdp = malloc (sizeof (ctf_decl_node_t))) == NULL)
137     {
138       cd->cd_err = EAGAIN;
139       return;
140     }
141
142   cdp->cd_type = type;
143   cdp->cd_kind = kind;
144   cdp->cd_n = n;
145
146   if (ctf_list_next (&cd->cd_nodes[prec]) == NULL)
147     cd->cd_order[prec] = cd->cd_ordp++;
148
149   /* Reset cd_qualp to the highest precedence level that we've seen so
150      far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).  */
151
152   if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
153     cd->cd_qualp = prec;
154
155   /* C array declarators are ordered inside out so prepend them.  Also by
156      convention qualifiers of base types precede the type specifier (e.g.
157      const int vs. int const) even though the two forms are equivalent.  */
158
159   if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
160     ctf_list_prepend (&cd->cd_nodes[prec], cdp);
161   else
162     ctf_list_append (&cd->cd_nodes[prec], cdp);
163 }
164
165 _libctf_printflike_ (2, 3)
166 void ctf_decl_sprintf (ctf_decl_t *cd, const char *format, ...)
167 {
168   va_list ap;
169   char *str;
170   int n;
171
172   if (cd->cd_enomem)
173     return;
174
175   va_start (ap, format);
176   n = vasprintf (&str, format, ap);
177   va_end (ap);
178
179   if (n > 0)
180     {
181       char *newbuf;
182       if ((newbuf = ctf_str_append (cd->cd_buf, str)) != NULL)
183         cd->cd_buf = newbuf;
184     }
185
186   /* Sticky error condition.  */
187   if (n < 0 || cd->cd_buf == NULL)
188     {
189       free (cd->cd_buf);
190       cd->cd_buf = NULL;
191       cd->cd_enomem = 1;
192     }
193
194   free (str);
195 }
196
197 char *ctf_decl_buf (ctf_decl_t *cd)
198 {
199   char *buf = cd->cd_buf;
200   cd->cd_buf = NULL;
201   return buf;
202 }
This page took 0.036475 seconds and 4 git commands to generate.