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 } 72 73 void 74 ctf_decl_push (ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type) 75 { 76 ctf_decl_node_t *cdp; 77 ctf_decl_prec_t prec; 78 uint32_t kind, n = 1; 79 int is_qual = 0; 80 81 const ctf_type_t *tp; 82 ctf_arinfo_t ar; 83 84 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) 85 { 86 cd->cd_err = fp->ctf_errno; 87 return; 88 } 89 90 switch (kind = LCTF_INFO_KIND (fp, tp->ctt_info)) 91 { 92 case CTF_K_ARRAY: 93 (void) ctf_array_info (fp, type, &ar); 94 ctf_decl_push (cd, fp, ar.ctr_contents); 95 n = ar.ctr_nelems; 96 prec = CTF_PREC_ARRAY; 97 break; 98 99 case CTF_K_TYPEDEF: 100 if (ctf_strptr (fp, tp->ctt_name)[0] == '\0') 101 { 102 ctf_decl_push (cd, fp, tp->ctt_type); 103 return; 104 } 105 prec = CTF_PREC_BASE; 106 break; 107 108 case CTF_K_FUNCTION: 109 ctf_decl_push (cd, fp, tp->ctt_type); 110 prec = CTF_PREC_FUNCTION; 111 break; 112 113 case CTF_K_POINTER: 114 ctf_decl_push (cd, fp, tp->ctt_type); 115 prec = CTF_PREC_POINTER; 116 break; 117 118 case CTF_K_SLICE: 119 ctf_decl_push (cd, fp, ctf_type_reference (fp, type)); 120 prec = CTF_PREC_BASE; 121 break; 122 123 case CTF_K_VOLATILE: 124 case CTF_K_CONST: 125 case CTF_K_RESTRICT: 126 ctf_decl_push (cd, fp, tp->ctt_type); 127 prec = cd->cd_qualp; 128 is_qual++; 129 break; 130 131 default: 132 prec = CTF_PREC_BASE; 133 } 134 135 if ((cdp = malloc (sizeof (ctf_decl_node_t))) == NULL) 136 { 137 cd->cd_err = EAGAIN; 138 return; 139 } 140 141 cdp->cd_type = type; 142 cdp->cd_kind = kind; 143 cdp->cd_n = n; 144 145 if (ctf_list_next (&cd->cd_nodes[prec]) == NULL) 146 cd->cd_order[prec] = cd->cd_ordp++; 147 148 /* Reset cd_qualp to the highest precedence level that we've seen so 149 far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER). */ 150 151 if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY) 152 cd->cd_qualp = prec; 153 154 /* C array declarators are ordered inside out so prepend them. Also by 155 convention qualifiers of base types precede the type specifier (e.g. 156 const int vs. int const) even though the two forms are equivalent. */ 157 158 if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE)) 159 ctf_list_prepend (&cd->cd_nodes[prec], cdp); 160 else 161 ctf_list_append (&cd->cd_nodes[prec], cdp); 162 } 163 164 _libctf_printflike_ (2, 3) 165 void ctf_decl_sprintf (ctf_decl_t *cd, const char *format, ...) 166 { 167 va_list ap; 168 char *str; 169 int n; 170 171 if (cd->cd_enomem) 172 return; 173 174 va_start (ap, format); 175 n = vasprintf (&str, format, ap); 176 va_end (ap); 177 178 if (n > 0) 179 { 180 char *newbuf; 181 if ((newbuf = ctf_str_append (cd->cd_buf, str)) != NULL) 182 cd->cd_buf = newbuf; 183 } 184 185 /* Sticky error condition. */ 186 if (n < 0 || cd->cd_buf == NULL) 187 { 188 free (cd->cd_buf); 189 cd->cd_buf = NULL; 190 cd->cd_enomem = 1; 191 } 192 193 free (str); 194 } 195 196 char *ctf_decl_buf (ctf_decl_t *cd) 197 { 198 return cd->cd_buf; 199 } 200