tyname.c revision 1.16
1/* $NetBSD: tyname.c,v 1.16 2020/12/29 13:33:03 rillig Exp $ */ 2 3/*- 4 * Copyright (c) 2005 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#if HAVE_NBTOOL_CONFIG_H 33#include "nbtool_config.h" 34#endif 35 36#include <sys/cdefs.h> 37#if defined(__RCSID) && !defined(lint) 38__RCSID("$NetBSD: tyname.c,v 1.16 2020/12/29 13:33:03 rillig Exp $"); 39#endif 40 41#include <limits.h> 42#include <string.h> 43#include <stdlib.h> 44#include <err.h> 45 46#include PASS 47 48#ifndef LERROR 49#define LERROR(fmt, args...) \ 50 do { \ 51 (void)warnx("%s, %d: " fmt, __FILE__, __LINE__, ##args); \ 52 abort(); \ 53 } while (/*CONSTCOND*/0) 54#endif 55 56const char * 57basic_type_name(tspec_t t) 58{ 59 switch (t) { 60 case BOOL: return "_Bool"; 61 case CHAR: return "char"; 62 case UCHAR: return "unsigned char"; 63 case SCHAR: return "signed char"; 64 case SHORT: return "short"; 65 case USHORT: return "unsigned short"; 66 case INT: return "int"; 67 case UINT: return "unsigned int"; 68 case LONG: return "long"; 69 case ULONG: return "unsigned long"; 70 case QUAD: return "long long"; 71 case UQUAD: return "unsigned long long"; 72#ifdef INT128_SIZE 73 case INT128: return "__int128_t"; 74 case UINT128: return "__uint128_t"; 75#endif 76 case FLOAT: return "float"; 77 case DOUBLE: return "double"; 78 case LDOUBLE: return "long double"; 79 case VOID: return "void"; 80 case PTR: return "pointer"; 81 case ENUM: return "enum"; 82 case STRUCT: return "struct"; 83 case UNION: return "union"; 84 case FUNC: return "function"; 85 case ARRAY: return "array"; 86 case FCOMPLEX: return "float _Complex"; 87 case DCOMPLEX: return "double _Complex"; 88 case LCOMPLEX: return "long double _Complex"; 89 case COMPLEX: return "_Complex"; 90 default: 91 LERROR("basic_type_name(%d)", t); 92 return NULL; 93 } 94} 95 96int 97sametype(const type_t *t1, const type_t *t2) 98{ 99 tspec_t t; 100 101 if (t1->t_tspec != t2->t_tspec) 102 return 0; 103 104 /* Ignore const/void */ 105 106 switch (t = t1->t_tspec) { 107 case BOOL: 108 case CHAR: 109 case UCHAR: 110 case SCHAR: 111 case SHORT: 112 case USHORT: 113 case INT: 114 case UINT: 115 case LONG: 116 case ULONG: 117 case QUAD: 118 case UQUAD: 119#ifdef INT128_SIZE 120 case INT128: 121 case UINT128: 122#endif 123 case FLOAT: 124 case DOUBLE: 125 case LDOUBLE: 126 case VOID: 127 case FUNC: 128 case COMPLEX: 129 case FCOMPLEX: 130 case DCOMPLEX: 131 case LCOMPLEX: 132 return 1; 133 case ARRAY: 134 if (t1->t_dim != t2->t_dim) 135 return 0; 136 /*FALLTHROUGH*/ 137 case PTR: 138 return sametype(t1->t_subt, t2->t_subt); 139 case ENUM: 140#ifdef t_enum 141 return strcmp(t1->t_enum->etag->s_name, 142 t2->t_enum->etag->s_name) == 0; 143#else 144 return 1; 145#endif 146 case STRUCT: 147 case UNION: 148#ifdef t_str 149 return strcmp(t1->t_str->stag->s_name, 150 t2->t_str->stag->s_name) == 0; 151#else 152 return 1; 153#endif 154 default: 155 LERROR("tyname(%d)", t); 156 return 0; 157 } 158} 159 160const char * 161tyname(char *buf, size_t bufsiz, const type_t *tp) 162{ 163 tspec_t t; 164 const char *s; 165 char lbuf[64]; 166 char cv[20]; 167 168 if (tp == NULL) 169 return "(null)"; 170 if ((t = tp->t_tspec) == INT && tp->t_isenum) 171 t = ENUM; 172 173 s = basic_type_name(t); 174 175 cv[0] = '\0'; 176 if (tp->t_const) 177 (void)strcat(cv, "const "); 178 if (tp->t_volatile) 179 (void)strcat(cv, "volatile "); 180 181 switch (t) { 182 case BOOL: 183 case CHAR: 184 case UCHAR: 185 case SCHAR: 186 case SHORT: 187 case USHORT: 188 case INT: 189 case UINT: 190 case LONG: 191 case ULONG: 192 case QUAD: 193 case UQUAD: 194#ifdef INT128_SIZE 195 case INT128: 196 case UINT128: 197#endif 198 case FLOAT: 199 case DOUBLE: 200 case LDOUBLE: 201 case VOID: 202 case FUNC: 203 case COMPLEX: 204 case FCOMPLEX: 205 case DCOMPLEX: 206 case LCOMPLEX: 207 (void)snprintf(buf, bufsiz, "%s%s", cv, s); 208 break; 209 case PTR: 210 (void)snprintf(buf, bufsiz, "%s%s to %s", cv, s, 211 tyname(lbuf, sizeof(lbuf), tp->t_subt)); 212 break; 213 case ENUM: 214 (void)snprintf(buf, bufsiz, "%s%s %s", cv, s, 215#ifdef t_enum 216 tp->t_enum->etag->s_name 217#else 218 tp->t_isuniqpos ? "*anonymous*" : tp->t_tag->h_name 219#endif 220 ); 221 break; 222 case STRUCT: 223 case UNION: 224 (void)snprintf(buf, bufsiz, "%s%s %s", cv, s, 225#ifdef t_str 226 tp->t_str->stag->s_name 227#else 228 tp->t_isuniqpos ? "*anonymous*" : tp->t_tag->h_name 229#endif 230 ); 231 break; 232 case ARRAY: 233 (void)snprintf(buf, bufsiz, "%s%s of %s[%d]", cv, s, 234 tyname(lbuf, sizeof(lbuf), tp->t_subt), tp->t_dim); 235 break; 236 default: 237 LERROR("tyname(%d)", t); 238 } 239 return buf; 240} 241