18dffb485Schristos /* C declarator syntax glue. 2*c9055873Schristos Copyright (C) 2019-2024 Free Software Foundation, Inc. 38dffb485Schristos 48dffb485Schristos This file is part of libctf. 58dffb485Schristos 68dffb485Schristos libctf is free software; you can redistribute it and/or modify it under 78dffb485Schristos the terms of the GNU General Public License as published by the Free 88dffb485Schristos Software Foundation; either version 3, or (at your option) any later 98dffb485Schristos version. 108dffb485Schristos 118dffb485Schristos This program is distributed in the hope that it will be useful, but 128dffb485Schristos WITHOUT ANY WARRANTY; without even the implied warranty of 138dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 148dffb485Schristos See the GNU General Public License for more details. 158dffb485Schristos 168dffb485Schristos You should have received a copy of the GNU General Public License 178dffb485Schristos along with this program; see the file COPYING. If not see 188dffb485Schristos <http://www.gnu.org/licenses/>. */ 198dffb485Schristos 208dffb485Schristos /* CTF Declaration Stack 218dffb485Schristos 228dffb485Schristos In order to implement ctf_type_name(), we must convert a type graph back 238dffb485Schristos into a C type declaration. Unfortunately, a type graph represents a storage 248dffb485Schristos class ordering of the type whereas a type declaration must obey the C rules 258dffb485Schristos for operator precedence, and the two orderings are frequently in conflict. 268dffb485Schristos For example, consider these CTF type graphs and their C declarations: 278dffb485Schristos 288dffb485Schristos CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER : int (*)() 298dffb485Schristos CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER : int (*)[] 308dffb485Schristos 318dffb485Schristos In each case, parentheses are used to raise operator * to higher lexical 328dffb485Schristos precedence, so the string form of the C declaration cannot be constructed by 338dffb485Schristos walking the type graph links and forming the string from left to right. 348dffb485Schristos 358dffb485Schristos The functions in this file build a set of stacks from the type graph nodes 368dffb485Schristos corresponding to the C operator precedence levels in the appropriate order. 378dffb485Schristos The code in ctf_type_name() can then iterate over the levels and nodes in 388dffb485Schristos lexical precedence order and construct the final C declaration string. */ 398dffb485Schristos 408dffb485Schristos #include <ctf-impl.h> 418dffb485Schristos #include <string.h> 428dffb485Schristos 438dffb485Schristos void 448dffb485Schristos ctf_decl_init (ctf_decl_t *cd) 458dffb485Schristos { 468dffb485Schristos int i; 478dffb485Schristos 488dffb485Schristos memset (cd, 0, sizeof (ctf_decl_t)); 498dffb485Schristos 508dffb485Schristos for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) 518dffb485Schristos cd->cd_order[i] = CTF_PREC_BASE - 1; 528dffb485Schristos 538dffb485Schristos cd->cd_qualp = CTF_PREC_BASE; 548dffb485Schristos cd->cd_ordp = CTF_PREC_BASE; 558dffb485Schristos } 568dffb485Schristos 578dffb485Schristos void 588dffb485Schristos ctf_decl_fini (ctf_decl_t *cd) 598dffb485Schristos { 608dffb485Schristos ctf_decl_node_t *cdp, *ndp; 618dffb485Schristos int i; 628dffb485Schristos 638dffb485Schristos for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) 648dffb485Schristos { 658dffb485Schristos for (cdp = ctf_list_next (&cd->cd_nodes[i]); cdp != NULL; cdp = ndp) 668dffb485Schristos { 678dffb485Schristos ndp = ctf_list_next (cdp); 688dffb485Schristos free (cdp); 698dffb485Schristos } 708dffb485Schristos } 718dffb485Schristos free (cd->cd_buf); 728dffb485Schristos } 738dffb485Schristos 748dffb485Schristos void 754b169a6bSchristos ctf_decl_push (ctf_decl_t *cd, ctf_dict_t *fp, ctf_id_t type) 768dffb485Schristos { 778dffb485Schristos ctf_decl_node_t *cdp; 788dffb485Schristos ctf_decl_prec_t prec; 798dffb485Schristos uint32_t kind, n = 1; 808dffb485Schristos int is_qual = 0; 818dffb485Schristos 828dffb485Schristos const ctf_type_t *tp; 838dffb485Schristos ctf_arinfo_t ar; 848dffb485Schristos 858dffb485Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) 868dffb485Schristos { 878dffb485Schristos cd->cd_err = fp->ctf_errno; 888dffb485Schristos return; 898dffb485Schristos } 908dffb485Schristos 918dffb485Schristos switch (kind = LCTF_INFO_KIND (fp, tp->ctt_info)) 928dffb485Schristos { 938dffb485Schristos case CTF_K_ARRAY: 948dffb485Schristos (void) ctf_array_info (fp, type, &ar); 958dffb485Schristos ctf_decl_push (cd, fp, ar.ctr_contents); 968dffb485Schristos n = ar.ctr_nelems; 978dffb485Schristos prec = CTF_PREC_ARRAY; 988dffb485Schristos break; 998dffb485Schristos 1008dffb485Schristos case CTF_K_TYPEDEF: 1018dffb485Schristos if (ctf_strptr (fp, tp->ctt_name)[0] == '\0') 1028dffb485Schristos { 1038dffb485Schristos ctf_decl_push (cd, fp, tp->ctt_type); 1048dffb485Schristos return; 1058dffb485Schristos } 1068dffb485Schristos prec = CTF_PREC_BASE; 1078dffb485Schristos break; 1088dffb485Schristos 1098dffb485Schristos case CTF_K_FUNCTION: 1108dffb485Schristos ctf_decl_push (cd, fp, tp->ctt_type); 1118dffb485Schristos prec = CTF_PREC_FUNCTION; 1128dffb485Schristos break; 1138dffb485Schristos 1148dffb485Schristos case CTF_K_POINTER: 1158dffb485Schristos ctf_decl_push (cd, fp, tp->ctt_type); 1168dffb485Schristos prec = CTF_PREC_POINTER; 1178dffb485Schristos break; 1188dffb485Schristos 1198dffb485Schristos case CTF_K_SLICE: 1204b169a6bSchristos /* Slices themselves have no print representation and should not appear in 1214b169a6bSchristos the decl stack. */ 1228dffb485Schristos ctf_decl_push (cd, fp, ctf_type_reference (fp, type)); 1234b169a6bSchristos return; 1248dffb485Schristos 1258dffb485Schristos case CTF_K_VOLATILE: 1268dffb485Schristos case CTF_K_CONST: 1278dffb485Schristos case CTF_K_RESTRICT: 1288dffb485Schristos ctf_decl_push (cd, fp, tp->ctt_type); 1298dffb485Schristos prec = cd->cd_qualp; 1308dffb485Schristos is_qual++; 1318dffb485Schristos break; 1328dffb485Schristos 1338dffb485Schristos default: 1348dffb485Schristos prec = CTF_PREC_BASE; 1358dffb485Schristos } 1368dffb485Schristos 1378dffb485Schristos if ((cdp = malloc (sizeof (ctf_decl_node_t))) == NULL) 1388dffb485Schristos { 1398dffb485Schristos cd->cd_err = EAGAIN; 1408dffb485Schristos return; 1418dffb485Schristos } 1428dffb485Schristos 1438dffb485Schristos cdp->cd_type = type; 1448dffb485Schristos cdp->cd_kind = kind; 1458dffb485Schristos cdp->cd_n = n; 1468dffb485Schristos 1478dffb485Schristos if (ctf_list_next (&cd->cd_nodes[prec]) == NULL) 1488dffb485Schristos cd->cd_order[prec] = cd->cd_ordp++; 1498dffb485Schristos 1508dffb485Schristos /* Reset cd_qualp to the highest precedence level that we've seen so 1518dffb485Schristos far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER). */ 1528dffb485Schristos 1538dffb485Schristos if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY) 1548dffb485Schristos cd->cd_qualp = prec; 1558dffb485Schristos 1564b169a6bSchristos /* By convention qualifiers of base types precede the type specifier (e.g. 1578dffb485Schristos const int vs. int const) even though the two forms are equivalent. */ 1588dffb485Schristos 1594b169a6bSchristos if (is_qual && prec == CTF_PREC_BASE) 1608dffb485Schristos ctf_list_prepend (&cd->cd_nodes[prec], cdp); 1618dffb485Schristos else 1628dffb485Schristos ctf_list_append (&cd->cd_nodes[prec], cdp); 1638dffb485Schristos } 1648dffb485Schristos 1658dffb485Schristos _libctf_printflike_ (2, 3) 1668dffb485Schristos void ctf_decl_sprintf (ctf_decl_t *cd, const char *format, ...) 1678dffb485Schristos { 1688dffb485Schristos va_list ap; 1698dffb485Schristos char *str; 1708dffb485Schristos int n; 1718dffb485Schristos 1728dffb485Schristos if (cd->cd_enomem) 1738dffb485Schristos return; 1748dffb485Schristos 1758dffb485Schristos va_start (ap, format); 1768dffb485Schristos n = vasprintf (&str, format, ap); 1778dffb485Schristos va_end (ap); 1788dffb485Schristos 1798dffb485Schristos if (n > 0) 1808dffb485Schristos { 1818dffb485Schristos char *newbuf; 1828dffb485Schristos if ((newbuf = ctf_str_append (cd->cd_buf, str)) != NULL) 1838dffb485Schristos cd->cd_buf = newbuf; 1848dffb485Schristos } 1858dffb485Schristos 1868dffb485Schristos /* Sticky error condition. */ 1878dffb485Schristos if (n < 0 || cd->cd_buf == NULL) 1888dffb485Schristos { 1898dffb485Schristos free (cd->cd_buf); 1908dffb485Schristos cd->cd_buf = NULL; 1918dffb485Schristos cd->cd_enomem = 1; 1928dffb485Schristos } 1938dffb485Schristos 1948dffb485Schristos free (str); 1958dffb485Schristos } 1968dffb485Schristos 1978dffb485Schristos char *ctf_decl_buf (ctf_decl_t *cd) 1988dffb485Schristos { 1998dffb485Schristos char *buf = cd->cd_buf; 2008dffb485Schristos cd->cd_buf = NULL; 2018dffb485Schristos return buf; 2028dffb485Schristos } 203