11f5207b7SJohn Levon /*
21f5207b7SJohn Levon  * Copyright (C) 2009 Dan Carpenter.
31f5207b7SJohn Levon  *
41f5207b7SJohn Levon  * This program is free software; you can redistribute it and/or
51f5207b7SJohn Levon  * modify it under the terms of the GNU General Public License
61f5207b7SJohn Levon  * as published by the Free Software Foundation; either version 2
71f5207b7SJohn Levon  * of the License, or (at your option) any later version.
81f5207b7SJohn Levon  *
91f5207b7SJohn Levon  * This program is distributed in the hope that it will be useful,
101f5207b7SJohn Levon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
111f5207b7SJohn Levon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
121f5207b7SJohn Levon  * GNU General Public License for more details.
131f5207b7SJohn Levon  *
141f5207b7SJohn Levon  * You should have received a copy of the GNU General Public License
151f5207b7SJohn Levon  * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
161f5207b7SJohn Levon  */
171f5207b7SJohn Levon 
181f5207b7SJohn Levon /*
191f5207b7SJohn Levon  * The idea here is that you have an expression and you
201f5207b7SJohn Levon  * want to know what the type is for that.
211f5207b7SJohn Levon  */
221f5207b7SJohn Levon 
231f5207b7SJohn Levon #include "smatch.h"
241f5207b7SJohn Levon #include "smatch_slist.h"
251f5207b7SJohn Levon 
get_real_base_type(struct symbol * sym)261f5207b7SJohn Levon struct symbol *get_real_base_type(struct symbol *sym)
271f5207b7SJohn Levon {
281f5207b7SJohn Levon 	struct symbol *ret;
291f5207b7SJohn Levon 
301f5207b7SJohn Levon 	if (!sym)
311f5207b7SJohn Levon 		return NULL;
32efe51d0cSJohn Levon 	if (sym->type == SYM_BASETYPE)
33efe51d0cSJohn Levon 		return sym;
341f5207b7SJohn Levon 	ret = get_base_type(sym);
351f5207b7SJohn Levon 	if (!ret)
361f5207b7SJohn Levon 		return NULL;
371f5207b7SJohn Levon 	if (ret->type == SYM_RESTRICT || ret->type == SYM_NODE)
381f5207b7SJohn Levon 		return get_real_base_type(ret);
391f5207b7SJohn Levon 	return ret;
401f5207b7SJohn Levon }
411f5207b7SJohn Levon 
type_bytes(struct symbol * type)421f5207b7SJohn Levon int type_bytes(struct symbol *type)
431f5207b7SJohn Levon {
441f5207b7SJohn Levon 	int bits;
451f5207b7SJohn Levon 
461f5207b7SJohn Levon 	if (type && type->type == SYM_ARRAY)
471f5207b7SJohn Levon 		return array_bytes(type);
481f5207b7SJohn Levon 
491f5207b7SJohn Levon 	bits = type_bits(type);
501f5207b7SJohn Levon 	if (bits < 0)
511f5207b7SJohn Levon 		return 0;
521f5207b7SJohn Levon 	return bits_to_bytes(bits);
531f5207b7SJohn Levon }
541f5207b7SJohn Levon 
array_bytes(struct symbol * type)551f5207b7SJohn Levon int array_bytes(struct symbol *type)
561f5207b7SJohn Levon {
571f5207b7SJohn Levon 	if (!type || type->type != SYM_ARRAY)
581f5207b7SJohn Levon 		return 0;
591f5207b7SJohn Levon 	return bits_to_bytes(type->bit_size);
601f5207b7SJohn Levon }
611f5207b7SJohn Levon 
get_binop_type(struct expression * expr)621f5207b7SJohn Levon static struct symbol *get_binop_type(struct expression *expr)
631f5207b7SJohn Levon {
641f5207b7SJohn Levon 	struct symbol *left, *right;
651f5207b7SJohn Levon 
661f5207b7SJohn Levon 	left = get_type(expr->left);
671f5207b7SJohn Levon 	if (!left)
681f5207b7SJohn Levon 		return NULL;
691f5207b7SJohn Levon 
701f5207b7SJohn Levon 	if (expr->op == SPECIAL_LEFTSHIFT ||
711f5207b7SJohn Levon 	    expr->op == SPECIAL_RIGHTSHIFT) {
721f5207b7SJohn Levon 		if (type_positive_bits(left) < 31)
731f5207b7SJohn Levon 			return &int_ctype;
741f5207b7SJohn Levon 		return left;
751f5207b7SJohn Levon 	}
761f5207b7SJohn Levon 	right = get_type(expr->right);
771f5207b7SJohn Levon 	if (!right)
781f5207b7SJohn Levon 		return NULL;
791f5207b7SJohn Levon 
805a0e240fSJohn Levon 	if (type_is_fp(left)) {
815a0e240fSJohn Levon 		if (type_is_fp(right)) {
825a0e240fSJohn Levon 			if (type_bits(left) > type_bits(right))
835a0e240fSJohn Levon 				return left;
845a0e240fSJohn Levon 			return right;
855a0e240fSJohn Levon 		}
865a0e240fSJohn Levon 		return left;
875a0e240fSJohn Levon 	}
885a0e240fSJohn Levon 
895a0e240fSJohn Levon 	if (type_is_fp(right)) {
905a0e240fSJohn Levon 		if (type_is_fp(left)) {
915a0e240fSJohn Levon 			if (type_bits(right) > type_bits(left))
925a0e240fSJohn Levon 				return right;
935a0e240fSJohn Levon 			return left;
945a0e240fSJohn Levon 		}
955a0e240fSJohn Levon 		return right;
965a0e240fSJohn Levon 	}
975a0e240fSJohn Levon 
98efe51d0cSJohn Levon 	if (expr->op == '-' &&
99efe51d0cSJohn Levon 	    (is_ptr_type(left) && is_ptr_type(right)))
100efe51d0cSJohn Levon 		return ssize_t_ctype;
101efe51d0cSJohn Levon 
1021f5207b7SJohn Levon 	if (left->type == SYM_PTR || left->type == SYM_ARRAY)
1031f5207b7SJohn Levon 		return left;
1041f5207b7SJohn Levon 	if (right->type == SYM_PTR || right->type == SYM_ARRAY)
1051f5207b7SJohn Levon 		return right;
1061f5207b7SJohn Levon 
1071f5207b7SJohn Levon 	if (type_positive_bits(left) < 31 && type_positive_bits(right) < 31)
1081f5207b7SJohn Levon 		return &int_ctype;
1091f5207b7SJohn Levon 
1101f5207b7SJohn Levon 	if (type_positive_bits(left) > type_positive_bits(right))
1111f5207b7SJohn Levon 		return left;
1121f5207b7SJohn Levon 	return right;
1131f5207b7SJohn Levon }
1141f5207b7SJohn Levon 
get_type_symbol(struct expression * expr)1151f5207b7SJohn Levon static struct symbol *get_type_symbol(struct expression *expr)
1161f5207b7SJohn Levon {
1171f5207b7SJohn Levon 	if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol)
1181f5207b7SJohn Levon 		return NULL;
1191f5207b7SJohn Levon 
1201f5207b7SJohn Levon 	return get_real_base_type(expr->symbol);
1211f5207b7SJohn Levon }
1221f5207b7SJohn Levon 
get_member_symbol(struct symbol_list * symbol_list,struct ident * member)1231f5207b7SJohn Levon static struct symbol *get_member_symbol(struct symbol_list *symbol_list, struct ident *member)
1241f5207b7SJohn Levon {
1251f5207b7SJohn Levon 	struct symbol *tmp, *sub;
1261f5207b7SJohn Levon 
1271f5207b7SJohn Levon 	FOR_EACH_PTR(symbol_list, tmp) {
1281f5207b7SJohn Levon 		if (!tmp->ident) {
1291f5207b7SJohn Levon 			sub = get_real_base_type(tmp);
1301f5207b7SJohn Levon 			sub = get_member_symbol(sub->symbol_list, member);
1311f5207b7SJohn Levon 			if (sub)
1321f5207b7SJohn Levon 				return sub;
1331f5207b7SJohn Levon 			continue;
1341f5207b7SJohn Levon 		}
1351f5207b7SJohn Levon 		if (tmp->ident == member)
1361f5207b7SJohn Levon 			return tmp;
1371f5207b7SJohn Levon 	} END_FOR_EACH_PTR(tmp);
1381f5207b7SJohn Levon 
1391f5207b7SJohn Levon 	return NULL;
1401f5207b7SJohn Levon }
1411f5207b7SJohn Levon 
get_symbol_from_deref(struct expression * expr)1421f5207b7SJohn Levon static struct symbol *get_symbol_from_deref(struct expression *expr)
1431f5207b7SJohn Levon {
1441f5207b7SJohn Levon 	struct ident *member;
1451f5207b7SJohn Levon 	struct symbol *sym;
1461f5207b7SJohn Levon 
1471f5207b7SJohn Levon 	if (!expr || expr->type != EXPR_DEREF)
1481f5207b7SJohn Levon 		return NULL;
1491f5207b7SJohn Levon 
1501f5207b7SJohn Levon 	member = expr->member;
1511f5207b7SJohn Levon 	sym = get_type(expr->deref);
1521f5207b7SJohn Levon 	if (!sym) {
1531f5207b7SJohn Levon 		// sm_msg("could not find struct type");
1541f5207b7SJohn Levon 		return NULL;
1551f5207b7SJohn Levon 	}
1561f5207b7SJohn Levon 	if (sym->type == SYM_PTR)
1571f5207b7SJohn Levon 		sym = get_real_base_type(sym);
1581f5207b7SJohn Levon 	sym = get_member_symbol(sym->symbol_list, member);
1591f5207b7SJohn Levon 	if (!sym)
1601f5207b7SJohn Levon 		return NULL;
1611f5207b7SJohn Levon 	return get_real_base_type(sym);
1621f5207b7SJohn Levon }
1631f5207b7SJohn Levon 
handle__builtin_choose_expr(struct expression * expr)1645a0e240fSJohn Levon static struct symbol *handle__builtin_choose_expr(struct expression *expr)
1655a0e240fSJohn Levon {
1665a0e240fSJohn Levon 	struct expression *const_expr, *expr1, *expr2;
1675a0e240fSJohn Levon 	sval_t sval;
1685a0e240fSJohn Levon 
1695a0e240fSJohn Levon 	const_expr = get_argument_from_call_expr(expr->args, 0);
1705a0e240fSJohn Levon 	expr1 = get_argument_from_call_expr(expr->args, 1);
1715a0e240fSJohn Levon 	expr2 = get_argument_from_call_expr(expr->args, 2);
1725a0e240fSJohn Levon 
1735a0e240fSJohn Levon 	if (!get_value(const_expr, &sval) || !expr1 || !expr2)
1745a0e240fSJohn Levon 		return NULL;
1755a0e240fSJohn Levon 	if (sval.value)
1765a0e240fSJohn Levon 		return get_type(expr1);
1775a0e240fSJohn Levon 	else
1785a0e240fSJohn Levon 		return get_type(expr2);
1795a0e240fSJohn Levon }
1805a0e240fSJohn Levon 
get_return_type(struct expression * expr)1811f5207b7SJohn Levon static struct symbol *get_return_type(struct expression *expr)
1821f5207b7SJohn Levon {
1831f5207b7SJohn Levon 	struct symbol *tmp;
1841f5207b7SJohn Levon 
1855a0e240fSJohn Levon 	if (sym_name_is("__builtin_choose_expr", expr->fn))
1865a0e240fSJohn Levon 		return handle__builtin_choose_expr(expr);
1875a0e240fSJohn Levon 
1881f5207b7SJohn Levon 	tmp = get_type(expr->fn);
1891f5207b7SJohn Levon 	if (!tmp)
1901f5207b7SJohn Levon 		return NULL;
1911f5207b7SJohn Levon 	/* this is to handle __builtin_constant_p() */
1921f5207b7SJohn Levon 	if (tmp->type != SYM_FN)
1931f5207b7SJohn Levon 		tmp = get_base_type(tmp);
1941f5207b7SJohn Levon 	return get_real_base_type(tmp);
1951f5207b7SJohn Levon }
1961f5207b7SJohn Levon 
get_expr_stmt_type(struct statement * stmt)1971f5207b7SJohn Levon static struct symbol *get_expr_stmt_type(struct statement *stmt)
1981f5207b7SJohn Levon {
1991f5207b7SJohn Levon 	if (stmt->type != STMT_COMPOUND)
2001f5207b7SJohn Levon 		return NULL;
2011f5207b7SJohn Levon 	stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
2021f5207b7SJohn Levon 	if (stmt->type == STMT_LABEL)
2031f5207b7SJohn Levon 		stmt = stmt->label_statement;
2041f5207b7SJohn Levon 	if (stmt->type != STMT_EXPRESSION)
2051f5207b7SJohn Levon 		return NULL;
2061f5207b7SJohn Levon 	return get_type(stmt->expression);
2071f5207b7SJohn Levon }
2081f5207b7SJohn Levon 
get_select_type(struct expression * expr)2091f5207b7SJohn Levon static struct symbol *get_select_type(struct expression *expr)
2101f5207b7SJohn Levon {
2111f5207b7SJohn Levon 	struct symbol *one, *two;
2121f5207b7SJohn Levon 
2131f5207b7SJohn Levon 	one = get_type(expr->cond_true);
2141f5207b7SJohn Levon 	two = get_type(expr->cond_false);
2151f5207b7SJohn Levon 	if (!one || !two)
2161f5207b7SJohn Levon 		return NULL;
2171f5207b7SJohn Levon 	/*
2181f5207b7SJohn Levon 	 * This is a hack.  If the types are not equiv then we
2191f5207b7SJohn Levon 	 * really don't know the type.  But I think guessing is
2201f5207b7SJohn Levon 	 *  probably Ok here.
2211f5207b7SJohn Levon 	 */
2221f5207b7SJohn Levon 	if (type_positive_bits(one) > type_positive_bits(two))
2231f5207b7SJohn Levon 		return one;
2241f5207b7SJohn Levon 	return two;
2251f5207b7SJohn Levon }
2261f5207b7SJohn Levon 
get_pointer_type(struct expression * expr)2271f5207b7SJohn Levon struct symbol *get_pointer_type(struct expression *expr)
2281f5207b7SJohn Levon {
2291f5207b7SJohn Levon 	struct symbol *sym;
2301f5207b7SJohn Levon 
2311f5207b7SJohn Levon 	sym = get_type(expr);
2321f5207b7SJohn Levon 	if (!sym)
2331f5207b7SJohn Levon 		return NULL;
2341f5207b7SJohn Levon 	if (sym->type == SYM_NODE) {
2351f5207b7SJohn Levon 		sym = get_real_base_type(sym);
2361f5207b7SJohn Levon 		if (!sym)
2371f5207b7SJohn Levon 			return NULL;
2381f5207b7SJohn Levon 	}
2391f5207b7SJohn Levon 	if (sym->type != SYM_PTR && sym->type != SYM_ARRAY)
2401f5207b7SJohn Levon 		return NULL;
2411f5207b7SJohn Levon 	return get_real_base_type(sym);
2421f5207b7SJohn Levon }
2431f5207b7SJohn Levon 
fake_pointer_sym(struct expression * expr)2441f5207b7SJohn Levon static struct symbol *fake_pointer_sym(struct expression *expr)
2451f5207b7SJohn Levon {
2461f5207b7SJohn Levon 	struct symbol *sym;
2471f5207b7SJohn Levon 	struct symbol *base;
2481f5207b7SJohn Levon 
2491f5207b7SJohn Levon 	sym = alloc_symbol(expr->pos, SYM_PTR);
2501f5207b7SJohn Levon 	expr = expr->unop;
2511f5207b7SJohn Levon 	base = get_type(expr);
2521f5207b7SJohn Levon 	if (!base)
2531f5207b7SJohn Levon 		return NULL;
2541f5207b7SJohn Levon 	sym->ctype.base_type = base;
2551f5207b7SJohn Levon 	return sym;
2561f5207b7SJohn Levon }
2571f5207b7SJohn Levon 
get_type_helper(struct expression * expr)2581f5207b7SJohn Levon static struct symbol *get_type_helper(struct expression *expr)
2591f5207b7SJohn Levon {
2601f5207b7SJohn Levon 	struct symbol *ret;
2611f5207b7SJohn Levon 
2621f5207b7SJohn Levon 	expr = strip_parens(expr);
2631f5207b7SJohn Levon 	if (!expr)
2641f5207b7SJohn Levon 		return NULL;
2651f5207b7SJohn Levon 
2661f5207b7SJohn Levon 	if (expr->ctype)
2671f5207b7SJohn Levon 		return expr->ctype;
2681f5207b7SJohn Levon 
2691f5207b7SJohn Levon 	switch (expr->type) {
2701f5207b7SJohn Levon 	case EXPR_STRING:
2711f5207b7SJohn Levon 		ret = &string_ctype;
2721f5207b7SJohn Levon 		break;
2731f5207b7SJohn Levon 	case EXPR_SYMBOL:
2741f5207b7SJohn Levon 		ret = get_type_symbol(expr);
2751f5207b7SJohn Levon 		break;
2761f5207b7SJohn Levon 	case EXPR_DEREF:
2771f5207b7SJohn Levon 		ret = get_symbol_from_deref(expr);
2781f5207b7SJohn Levon 		break;
2791f5207b7SJohn Levon 	case EXPR_PREOP:
2801f5207b7SJohn Levon 	case EXPR_POSTOP:
2811f5207b7SJohn Levon 		if (expr->op == '&')
2821f5207b7SJohn Levon 			ret = fake_pointer_sym(expr);
2831f5207b7SJohn Levon 		else if (expr->op == '*')
2841f5207b7SJohn Levon 			ret = get_pointer_type(expr->unop);
2851f5207b7SJohn Levon 		else
2861f5207b7SJohn Levon 			ret = get_type(expr->unop);
2871f5207b7SJohn Levon 		break;
2881f5207b7SJohn Levon 	case EXPR_ASSIGNMENT:
2891f5207b7SJohn Levon 		ret = get_type(expr->left);
2901f5207b7SJohn Levon 		break;
2911f5207b7SJohn Levon 	case EXPR_CAST:
2921f5207b7SJohn Levon 	case EXPR_FORCE_CAST:
2931f5207b7SJohn Levon 	case EXPR_IMPLIED_CAST:
2941f5207b7SJohn Levon 		ret = get_real_base_type(expr->cast_type);
2951f5207b7SJohn Levon 		break;
2961f5207b7SJohn Levon 	case EXPR_COMPARE:
2971f5207b7SJohn Levon 	case EXPR_BINOP:
2981f5207b7SJohn Levon 		ret = get_binop_type(expr);
2991f5207b7SJohn Levon 		break;
3001f5207b7SJohn Levon 	case EXPR_CALL:
3011f5207b7SJohn Levon 		ret = get_return_type(expr);
3021f5207b7SJohn Levon 		break;
3031f5207b7SJohn Levon 	case EXPR_STATEMENT:
3041f5207b7SJohn Levon 		ret = get_expr_stmt_type(expr->statement);
3051f5207b7SJohn Levon 		break;
3061f5207b7SJohn Levon 	case EXPR_CONDITIONAL:
3071f5207b7SJohn Levon 	case EXPR_SELECT:
3081f5207b7SJohn Levon 		ret = get_select_type(expr);
3091f5207b7SJohn Levon 		break;
3101f5207b7SJohn Levon 	case EXPR_SIZEOF:
3111f5207b7SJohn Levon 		ret = &ulong_ctype;
3121f5207b7SJohn Levon 		break;
3131f5207b7SJohn Levon 	case EXPR_LOGICAL:
3141f5207b7SJohn Levon 		ret = &int_ctype;
3151f5207b7SJohn Levon 		break;
316efe51d0cSJohn Levon 	case EXPR_OFFSETOF:
317efe51d0cSJohn Levon 		ret = &ulong_ctype;
318efe51d0cSJohn Levon 		break;
3191f5207b7SJohn Levon 	default:
3201f5207b7SJohn Levon 		return NULL;
3211f5207b7SJohn Levon 	}
3221f5207b7SJohn Levon 
3231f5207b7SJohn Levon 	if (ret && ret->type == SYM_TYPEOF)
3241f5207b7SJohn Levon 		ret = get_type(ret->initializer);
3251f5207b7SJohn Levon 
3261f5207b7SJohn Levon 	expr->ctype = ret;
3271f5207b7SJohn Levon 	return ret;
3281f5207b7SJohn Levon }
3291f5207b7SJohn Levon 
get_final_type_helper(struct expression * expr)3301f5207b7SJohn Levon static struct symbol *get_final_type_helper(struct expression *expr)
3311f5207b7SJohn Levon {
3321f5207b7SJohn Levon 	/*
333efe51d0cSJohn Levon 	 * The problem is that I wrote a bunch of Smatch to think that
334efe51d0cSJohn Levon 	 * you could do get_type() on an expression and it would give
335efe51d0cSJohn Levon 	 * you what the comparison was type promoted to.  This is wrong
336efe51d0cSJohn Levon 	 * but fixing it is a big of work...  Hence this horrible hack.
3371f5207b7SJohn Levon 	 *
3381f5207b7SJohn Levon 	 */
3391f5207b7SJohn Levon 
3401f5207b7SJohn Levon 	expr = strip_parens(expr);
3411f5207b7SJohn Levon 	if (!expr)
3421f5207b7SJohn Levon 		return NULL;
3431f5207b7SJohn Levon 
344efe51d0cSJohn Levon 	if (expr->type == EXPR_COMPARE)
3451f5207b7SJohn Levon 		return &int_ctype;
3461f5207b7SJohn Levon 
3471f5207b7SJohn Levon 	return NULL;
3481f5207b7SJohn Levon }
3491f5207b7SJohn Levon 
get_type(struct expression * expr)3501f5207b7SJohn Levon struct symbol *get_type(struct expression *expr)
3511f5207b7SJohn Levon {
3521f5207b7SJohn Levon 	return get_type_helper(expr);
3531f5207b7SJohn Levon }
3541f5207b7SJohn Levon 
get_final_type(struct expression * expr)3551f5207b7SJohn Levon struct symbol *get_final_type(struct expression *expr)
3561f5207b7SJohn Levon {
3571f5207b7SJohn Levon 	struct symbol *ret;
3581f5207b7SJohn Levon 
3591f5207b7SJohn Levon 	ret = get_final_type_helper(expr);
3601f5207b7SJohn Levon 	if (ret)
3611f5207b7SJohn Levon 		return ret;
3621f5207b7SJohn Levon 	return get_type_helper(expr);
3631f5207b7SJohn Levon }
3641f5207b7SJohn Levon 
get_promoted_type(struct symbol * left,struct symbol * right)3651f5207b7SJohn Levon struct symbol *get_promoted_type(struct symbol *left, struct symbol *right)
3661f5207b7SJohn Levon {
3671f5207b7SJohn Levon 	struct symbol *ret = &int_ctype;
3681f5207b7SJohn Levon 
3691f5207b7SJohn Levon 	if (type_positive_bits(left) > type_positive_bits(ret))
3701f5207b7SJohn Levon 		ret = left;
3711f5207b7SJohn Levon 	if (type_positive_bits(right) > type_positive_bits(ret))
3721f5207b7SJohn Levon 		ret = right;
3731f5207b7SJohn Levon 
3741f5207b7SJohn Levon 	if (type_is_ptr(left))
3751f5207b7SJohn Levon 		ret = left;
3761f5207b7SJohn Levon 	if (type_is_ptr(right))
3771f5207b7SJohn Levon 		ret = right;
3781f5207b7SJohn Levon 
3791f5207b7SJohn Levon 	return ret;
3801f5207b7SJohn Levon }
3811f5207b7SJohn Levon 
type_signed(struct symbol * base_type)3821f5207b7SJohn Levon int type_signed(struct symbol *base_type)
3831f5207b7SJohn Levon {
3841f5207b7SJohn Levon 	if (!base_type)
3851f5207b7SJohn Levon 		return 0;
3861f5207b7SJohn Levon 	if (base_type->ctype.modifiers & MOD_SIGNED)
3871f5207b7SJohn Levon 		return 1;
3881f5207b7SJohn Levon 	return 0;
3891f5207b7SJohn Levon }
3901f5207b7SJohn Levon 
expr_unsigned(struct expression * expr)3911f5207b7SJohn Levon int expr_unsigned(struct expression *expr)
3921f5207b7SJohn Levon {
3931f5207b7SJohn Levon 	struct symbol *sym;
3941f5207b7SJohn Levon 
3951f5207b7SJohn Levon 	sym = get_type(expr);
3961f5207b7SJohn Levon 	if (!sym)
3971f5207b7SJohn Levon 		return 0;
3981f5207b7SJohn Levon 	if (type_unsigned(sym))
3991f5207b7SJohn Levon 		return 1;
4001f5207b7SJohn Levon 	return 0;
4011f5207b7SJohn Levon }
4021f5207b7SJohn Levon 
expr_signed(struct expression * expr)4031f5207b7SJohn Levon int expr_signed(struct expression *expr)
4041f5207b7SJohn Levon {
4051f5207b7SJohn Levon 	struct symbol *sym;
4061f5207b7SJohn Levon 
4071f5207b7SJohn Levon 	sym = get_type(expr);
4081f5207b7SJohn Levon 	if (!sym)
4091f5207b7SJohn Levon 		return 0;
4101f5207b7SJohn Levon 	if (type_signed(sym))
4111f5207b7SJohn Levon 		return 1;
4121f5207b7SJohn Levon 	return 0;
4131f5207b7SJohn Levon }
4141f5207b7SJohn Levon 
returns_unsigned(struct symbol * sym)4151f5207b7SJohn Levon int returns_unsigned(struct symbol *sym)
4161f5207b7SJohn Levon {
4171f5207b7SJohn Levon 	if (!sym)
4181f5207b7SJohn Levon 		return 0;
4191f5207b7SJohn Levon 	sym = get_base_type(sym);
4201f5207b7SJohn Levon 	if (!sym || sym->type != SYM_FN)
4211f5207b7SJohn Levon 		return 0;
4221f5207b7SJohn Levon 	sym = get_base_type(sym);
4231f5207b7SJohn Levon 	return type_unsigned(sym);
4241f5207b7SJohn Levon }
4251f5207b7SJohn Levon 
is_pointer(struct expression * expr)4261f5207b7SJohn Levon int is_pointer(struct expression *expr)
4271f5207b7SJohn Levon {
428efe51d0cSJohn Levon 	return type_is_ptr(get_type(expr));
4291f5207b7SJohn Levon }
4301f5207b7SJohn Levon 
returns_pointer(struct symbol * sym)4311f5207b7SJohn Levon int returns_pointer(struct symbol *sym)
4321f5207b7SJohn Levon {
4331f5207b7SJohn Levon 	if (!sym)
4341f5207b7SJohn Levon 		return 0;
4351f5207b7SJohn Levon 	sym = get_base_type(sym);
4361f5207b7SJohn Levon 	if (!sym || sym->type != SYM_FN)
4371f5207b7SJohn Levon 		return 0;
4381f5207b7SJohn Levon 	sym = get_base_type(sym);
439c85f09ccSJohn Levon 	if (sym && sym->type == SYM_PTR)
4401f5207b7SJohn Levon 		return 1;
4411f5207b7SJohn Levon 	return 0;
4421f5207b7SJohn Levon }
4431f5207b7SJohn Levon 
fp_max(struct symbol * type)4445a0e240fSJohn Levon static sval_t fp_max(struct symbol *type)
4455a0e240fSJohn Levon {
4465a0e240fSJohn Levon 	sval_t ret = { .type = type };
4475a0e240fSJohn Levon 
4485a0e240fSJohn Levon 	if (type == &float_ctype)
4495a0e240fSJohn Levon 		ret.fvalue = FLT_MAX;
4505a0e240fSJohn Levon 	else if (type == &double_ctype)
4515a0e240fSJohn Levon 		ret.dvalue = DBL_MAX;
4525a0e240fSJohn Levon 	else
4535a0e240fSJohn Levon 		ret.ldvalue = LDBL_MAX;
4545a0e240fSJohn Levon 
4555a0e240fSJohn Levon 	return ret;
4565a0e240fSJohn Levon }
4575a0e240fSJohn Levon 
sval_type_max(struct symbol * base_type)4581f5207b7SJohn Levon sval_t sval_type_max(struct symbol *base_type)
4591f5207b7SJohn Levon {
4601f5207b7SJohn Levon 	sval_t ret;
4611f5207b7SJohn Levon 
4625a0e240fSJohn Levon 	if (type_is_fp(base_type))
4635a0e240fSJohn Levon 		return fp_max(base_type);
4645a0e240fSJohn Levon 
4651f5207b7SJohn Levon 	if (!base_type || !type_bits(base_type))
4661f5207b7SJohn Levon 		base_type = &llong_ctype;
4671f5207b7SJohn Levon 	ret.type = base_type;
4681f5207b7SJohn Levon 
4691f5207b7SJohn Levon 	ret.value = (~0ULL) >> (64 - type_positive_bits(base_type));
4701f5207b7SJohn Levon 	return ret;
4711f5207b7SJohn Levon }
4721f5207b7SJohn Levon 
fp_min(struct symbol * type)4735a0e240fSJohn Levon static sval_t fp_min(struct symbol *type)
4745a0e240fSJohn Levon {
4755a0e240fSJohn Levon 	sval_t ret = { .type = type };
4765a0e240fSJohn Levon 
4775a0e240fSJohn Levon 	if (type == &float_ctype)
4785a0e240fSJohn Levon 		ret.fvalue = -FLT_MAX;
4795a0e240fSJohn Levon 	else if (type == &double_ctype)
4805a0e240fSJohn Levon 		ret.dvalue = -DBL_MAX;
4815a0e240fSJohn Levon 	else
4825a0e240fSJohn Levon 		ret.ldvalue = -LDBL_MAX;
4835a0e240fSJohn Levon 
4845a0e240fSJohn Levon 	return ret;
4855a0e240fSJohn Levon }
4865a0e240fSJohn Levon 
sval_type_min(struct symbol * base_type)4871f5207b7SJohn Levon sval_t sval_type_min(struct symbol *base_type)
4881f5207b7SJohn Levon {
4891f5207b7SJohn Levon 	sval_t ret;
4901f5207b7SJohn Levon 
4915a0e240fSJohn Levon 	if (type_is_fp(base_type))
4925a0e240fSJohn Levon 		return fp_min(base_type);
4935a0e240fSJohn Levon 
4941f5207b7SJohn Levon 	if (!base_type || !type_bits(base_type))
4951f5207b7SJohn Levon 		base_type = &llong_ctype;
4961f5207b7SJohn Levon 	ret.type = base_type;
4971f5207b7SJohn Levon 
498efe51d0cSJohn Levon 	if (type_unsigned(base_type) || is_ptr_type(base_type)) {
4991f5207b7SJohn Levon 		ret.value = 0;
5001f5207b7SJohn Levon 		return ret;
5011f5207b7SJohn Levon 	}
5021f5207b7SJohn Levon 
5031f5207b7SJohn Levon 	ret.value = (~0ULL) << type_positive_bits(base_type);
5041f5207b7SJohn Levon 
5051f5207b7SJohn Levon 	return ret;
5061f5207b7SJohn Levon }
5071f5207b7SJohn Levon 
nr_bits(struct expression * expr)5081f5207b7SJohn Levon int nr_bits(struct expression *expr)
5091f5207b7SJohn Levon {
5101f5207b7SJohn Levon 	struct symbol *type;
5111f5207b7SJohn Levon 
5121f5207b7SJohn Levon 	type = get_type(expr);
5131f5207b7SJohn Levon 	if (!type)
5141f5207b7SJohn Levon 		return 0;
5151f5207b7SJohn Levon 	return type_bits(type);
5161f5207b7SJohn Levon }
5171f5207b7SJohn Levon 
is_void_pointer(struct expression * expr)5181f5207b7SJohn Levon int is_void_pointer(struct expression *expr)
5191f5207b7SJohn Levon {
5201f5207b7SJohn Levon 	struct symbol *type;
5211f5207b7SJohn Levon 
5221f5207b7SJohn Levon 	type = get_type(expr);
5231f5207b7SJohn Levon 	if (!type || type->type != SYM_PTR)
5241f5207b7SJohn Levon 		return 0;
5251f5207b7SJohn Levon 	type = get_real_base_type(type);
5261f5207b7SJohn Levon 	if (type == &void_ctype)
5271f5207b7SJohn Levon 		return 1;
5281f5207b7SJohn Levon 	return 0;
5291f5207b7SJohn Levon }
5301f5207b7SJohn Levon 
is_char_pointer(struct expression * expr)5311f5207b7SJohn Levon int is_char_pointer(struct expression *expr)
5321f5207b7SJohn Levon {
5331f5207b7SJohn Levon 	struct symbol *type;
5341f5207b7SJohn Levon 
5351f5207b7SJohn Levon 	type = get_type(expr);
5361f5207b7SJohn Levon 	if (!type || type->type != SYM_PTR)
5371f5207b7SJohn Levon 		return 0;
5381f5207b7SJohn Levon 	type = get_real_base_type(type);
5391f5207b7SJohn Levon 	if (type == &char_ctype)
5401f5207b7SJohn Levon 		return 1;
5411f5207b7SJohn Levon 	return 0;
5421f5207b7SJohn Levon }
5431f5207b7SJohn Levon 
is_string(struct expression * expr)5441f5207b7SJohn Levon int is_string(struct expression *expr)
5451f5207b7SJohn Levon {
5461f5207b7SJohn Levon 	expr = strip_expr(expr);
5471f5207b7SJohn Levon 	if (!expr || expr->type != EXPR_STRING)
5481f5207b7SJohn Levon 		return 0;
5491f5207b7SJohn Levon 	if (expr->string)
5501f5207b7SJohn Levon 		return 1;
5511f5207b7SJohn Levon 	return 0;
5521f5207b7SJohn Levon }
5531f5207b7SJohn Levon 
is_struct_ptr(struct symbol * type)554*6523a3aaSJohn Levon bool is_struct_ptr(struct symbol *type)
555*6523a3aaSJohn Levon {
556*6523a3aaSJohn Levon 	if (!type || type->type != SYM_PTR)
557*6523a3aaSJohn Levon 		return false;
558*6523a3aaSJohn Levon 	type = get_real_base_type(type);
559*6523a3aaSJohn Levon 	if (!type || type->type != SYM_STRUCT)
560*6523a3aaSJohn Levon 		return false;
561*6523a3aaSJohn Levon 	return true;
562*6523a3aaSJohn Levon }
563*6523a3aaSJohn Levon 
is_static(struct expression * expr)5641f5207b7SJohn Levon int is_static(struct expression *expr)
5651f5207b7SJohn Levon {
5661f5207b7SJohn Levon 	char *name;
5671f5207b7SJohn Levon 	struct symbol *sym;
5681f5207b7SJohn Levon 	int ret = 0;
5691f5207b7SJohn Levon 
5701f5207b7SJohn Levon 	name = expr_to_str_sym(expr, &sym);
5711f5207b7SJohn Levon 	if (!name || !sym)
5721f5207b7SJohn Levon 		goto free;
5731f5207b7SJohn Levon 
5741f5207b7SJohn Levon 	if (sym->ctype.modifiers & MOD_STATIC)
5751f5207b7SJohn Levon 		ret = 1;
5761f5207b7SJohn Levon free:
5771f5207b7SJohn Levon 	free_string(name);
5781f5207b7SJohn Levon 	return ret;
5791f5207b7SJohn Levon }
5801f5207b7SJohn Levon 
is_local_variable(struct expression * expr)581c85f09ccSJohn Levon bool is_local_variable(struct expression *expr)
5821f5207b7SJohn Levon {
5831f5207b7SJohn Levon 	struct symbol *sym;
5841f5207b7SJohn Levon 
585c85f09ccSJohn Levon 	if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol)
586c85f09ccSJohn Levon 		return false;
587c85f09ccSJohn Levon 	sym = expr->symbol;
588c85f09ccSJohn Levon 	if (!(sym->ctype.modifiers & MOD_TOPLEVEL))
589c85f09ccSJohn Levon 		return true;
590c85f09ccSJohn Levon 	return false;
5911f5207b7SJohn Levon }
5921f5207b7SJohn Levon 
types_equiv(struct symbol * one,struct symbol * two)5931f5207b7SJohn Levon int types_equiv(struct symbol *one, struct symbol *two)
5941f5207b7SJohn Levon {
5951f5207b7SJohn Levon 	if (!one && !two)
5961f5207b7SJohn Levon 		return 1;
5971f5207b7SJohn Levon 	if (!one || !two)
5981f5207b7SJohn Levon 		return 0;
5991f5207b7SJohn Levon 	if (one->type != two->type)
6001f5207b7SJohn Levon 		return 0;
6011f5207b7SJohn Levon 	if (one->type == SYM_PTR)
6021f5207b7SJohn Levon 		return types_equiv(get_real_base_type(one), get_real_base_type(two));
6031f5207b7SJohn Levon 	if (type_positive_bits(one) != type_positive_bits(two))
6041f5207b7SJohn Levon 		return 0;
6051f5207b7SJohn Levon 	return 1;
6061f5207b7SJohn Levon }
6071f5207b7SJohn Levon 
type_fits(struct symbol * type,struct symbol * test)608*6523a3aaSJohn Levon bool type_fits(struct symbol *type, struct symbol *test)
609*6523a3aaSJohn Levon {
610*6523a3aaSJohn Levon 	if (!type || !test)
611*6523a3aaSJohn Levon 		return false;
612*6523a3aaSJohn Levon 
613*6523a3aaSJohn Levon 	if (type == test)
614*6523a3aaSJohn Levon 		return true;
615*6523a3aaSJohn Levon 
616*6523a3aaSJohn Levon 	if (type_bits(test) > type_bits(type))
617*6523a3aaSJohn Levon 		return false;
618*6523a3aaSJohn Levon 	if (type_signed(test) && !type_signed(type))
619*6523a3aaSJohn Levon 		return false;
620*6523a3aaSJohn Levon 	if (type_positive_bits(test) > type_positive_bits(type))
621*6523a3aaSJohn Levon 		return false;
622*6523a3aaSJohn Levon 	return true;
623*6523a3aaSJohn Levon }
624*6523a3aaSJohn Levon 
fn_static(void)6251f5207b7SJohn Levon int fn_static(void)
6261f5207b7SJohn Levon {
6271f5207b7SJohn Levon 	return !!(cur_func_sym->ctype.modifiers & MOD_STATIC);
6281f5207b7SJohn Levon }
6291f5207b7SJohn Levon 
global_static(void)6301f5207b7SJohn Levon const char *global_static(void)
6311f5207b7SJohn Levon {
6321f5207b7SJohn Levon 	if (cur_func_sym->ctype.modifiers & MOD_STATIC)
6331f5207b7SJohn Levon 		return "static";
6341f5207b7SJohn Levon 	else
6351f5207b7SJohn Levon 		return "global";
6361f5207b7SJohn Levon }
6371f5207b7SJohn Levon 
cur_func_return_type(void)6381f5207b7SJohn Levon struct symbol *cur_func_return_type(void)
6391f5207b7SJohn Levon {
6401f5207b7SJohn Levon 	struct symbol *sym;
6411f5207b7SJohn Levon 
6421f5207b7SJohn Levon 	sym = get_real_base_type(cur_func_sym);
6431f5207b7SJohn Levon 	if (!sym || sym->type != SYM_FN)
6441f5207b7SJohn Levon 		return NULL;
6451f5207b7SJohn Levon 	sym = get_real_base_type(sym);
6461f5207b7SJohn Levon 	return sym;
6471f5207b7SJohn Levon }
6481f5207b7SJohn Levon 
get_arg_type(struct expression * fn,int arg)6491f5207b7SJohn Levon struct symbol *get_arg_type(struct expression *fn, int arg)
6501f5207b7SJohn Levon {
6511f5207b7SJohn Levon 	struct symbol *fn_type;
6521f5207b7SJohn Levon 	struct symbol *tmp;
6531f5207b7SJohn Levon 	struct symbol *arg_type;
6541f5207b7SJohn Levon 	int i;
6551f5207b7SJohn Levon 
6561f5207b7SJohn Levon 	fn_type = get_type(fn);
6571f5207b7SJohn Levon 	if (!fn_type)
6581f5207b7SJohn Levon 		return NULL;
6591f5207b7SJohn Levon 	if (fn_type->type == SYM_PTR)
6601f5207b7SJohn Levon 		fn_type = get_real_base_type(fn_type);
6611f5207b7SJohn Levon 	if (fn_type->type != SYM_FN)
6621f5207b7SJohn Levon 		return NULL;
6631f5207b7SJohn Levon 
6641f5207b7SJohn Levon 	i = 0;
6651f5207b7SJohn Levon 	FOR_EACH_PTR(fn_type->arguments, tmp) {
6661f5207b7SJohn Levon 		arg_type = get_real_base_type(tmp);
6671f5207b7SJohn Levon 		if (i == arg) {
6681f5207b7SJohn Levon 			return arg_type;
6691f5207b7SJohn Levon 		}
6701f5207b7SJohn Levon 		i++;
6711f5207b7SJohn Levon 	} END_FOR_EACH_PTR(tmp);
6721f5207b7SJohn Levon 
6731f5207b7SJohn Levon 	return NULL;
6741f5207b7SJohn Levon }
6751f5207b7SJohn Levon 
get_member_from_string(struct symbol_list * symbol_list,const char * name)6761f5207b7SJohn Levon static struct symbol *get_member_from_string(struct symbol_list *symbol_list, const char *name)
6771f5207b7SJohn Levon {
6781f5207b7SJohn Levon 	struct symbol *tmp, *sub;
6791f5207b7SJohn Levon 	int chunk_len;
6801f5207b7SJohn Levon 
6811f5207b7SJohn Levon 	if (strncmp(name, ".", 1) == 0)
6821f5207b7SJohn Levon 		name += 1;
683efe51d0cSJohn Levon 	else if (strncmp(name, "->", 2) == 0)
6841f5207b7SJohn Levon 		name += 2;
6851f5207b7SJohn Levon 
6861f5207b7SJohn Levon 	FOR_EACH_PTR(symbol_list, tmp) {
6871f5207b7SJohn Levon 		if (!tmp->ident) {
6881f5207b7SJohn Levon 			sub = get_real_base_type(tmp);
6891f5207b7SJohn Levon 			sub = get_member_from_string(sub->symbol_list, name);
6901f5207b7SJohn Levon 			if (sub)
6911f5207b7SJohn Levon 				return sub;
6921f5207b7SJohn Levon 			continue;
6931f5207b7SJohn Levon 		}
6941f5207b7SJohn Levon 
6951f5207b7SJohn Levon 		if (strcmp(tmp->ident->name, name) == 0)
6961f5207b7SJohn Levon 			return tmp;
6971f5207b7SJohn Levon 
698efe51d0cSJohn Levon 		chunk_len = tmp->ident->len;
6991f5207b7SJohn Levon 		if (strncmp(tmp->ident->name, name, chunk_len) == 0 &&
7001f5207b7SJohn Levon 		    (name[chunk_len] == '.' || name[chunk_len] == '-')) {
7011f5207b7SJohn Levon 			sub = get_real_base_type(tmp);
702efe51d0cSJohn Levon 			if (sub->type == SYM_PTR)
703efe51d0cSJohn Levon 				sub = get_real_base_type(sub);
7041f5207b7SJohn Levon 			return get_member_from_string(sub->symbol_list, name + chunk_len);
7051f5207b7SJohn Levon 		}
7061f5207b7SJohn Levon 
7071f5207b7SJohn Levon 	} END_FOR_EACH_PTR(tmp);
7081f5207b7SJohn Levon 
7091f5207b7SJohn Levon 	return NULL;
7101f5207b7SJohn Levon }
7111f5207b7SJohn Levon 
get_member_type_from_key(struct expression * expr,const char * key)7121f5207b7SJohn Levon struct symbol *get_member_type_from_key(struct expression *expr, const char *key)
7131f5207b7SJohn Levon {
7141f5207b7SJohn Levon 	struct symbol *sym;
715*6523a3aaSJohn Levon 	int star = 0;
716*6523a3aaSJohn Levon 	int i;
7171f5207b7SJohn Levon 
7181f5207b7SJohn Levon 	if (strcmp(key, "$") == 0)
7191f5207b7SJohn Levon 		return get_type(expr);
7201f5207b7SJohn Levon 
7211f5207b7SJohn Levon 	if (strcmp(key, "*$") == 0) {
7221f5207b7SJohn Levon 		sym = get_type(expr);
7231f5207b7SJohn Levon 		if (!sym || sym->type != SYM_PTR)
7241f5207b7SJohn Levon 			return NULL;
7251f5207b7SJohn Levon 		return get_real_base_type(sym);
7261f5207b7SJohn Levon 	}
7271f5207b7SJohn Levon 
7281f5207b7SJohn Levon 	sym = get_type(expr);
7291f5207b7SJohn Levon 	if (!sym)
7301f5207b7SJohn Levon 		return NULL;
7311f5207b7SJohn Levon 	if (sym->type == SYM_PTR)
7321f5207b7SJohn Levon 		sym = get_real_base_type(sym);
7331f5207b7SJohn Levon 
734*6523a3aaSJohn Levon 	while (*key == '*') {
735*6523a3aaSJohn Levon 		key++;
736*6523a3aaSJohn Levon 		star++;
737*6523a3aaSJohn Levon 	}
738*6523a3aaSJohn Levon 
739*6523a3aaSJohn Levon 	if (*key != '$')
740*6523a3aaSJohn Levon 		return NULL;
741*6523a3aaSJohn Levon 	key++;
742*6523a3aaSJohn Levon 
7431f5207b7SJohn Levon 	sym = get_member_from_string(sym->symbol_list, key);
7441f5207b7SJohn Levon 	if (!sym)
7451f5207b7SJohn Levon 		return NULL;
746*6523a3aaSJohn Levon 	if (sym->type == SYM_RESTRICT || sym->type == SYM_NODE)
747*6523a3aaSJohn Levon 		sym = get_real_base_type(sym);
748*6523a3aaSJohn Levon 	for (i = 0; i < star; i++) {
749*6523a3aaSJohn Levon 		if (!sym || sym->type != SYM_PTR)
750*6523a3aaSJohn Levon 			return NULL;
751*6523a3aaSJohn Levon 		sym = get_real_base_type(sym);
752*6523a3aaSJohn Levon 	}
753*6523a3aaSJohn Levon 	return sym;
7541f5207b7SJohn Levon }
7551f5207b7SJohn Levon 
get_arg_type_from_key(struct expression * fn,int param,struct expression * arg,const char * key)7561f5207b7SJohn Levon struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key)
7571f5207b7SJohn Levon {
7581f5207b7SJohn Levon 	struct symbol *type;
7591f5207b7SJohn Levon 
7601f5207b7SJohn Levon 	if (!key)
7611f5207b7SJohn Levon 		return NULL;
7621f5207b7SJohn Levon 	if (strcmp(key, "$") == 0)
7631f5207b7SJohn Levon 		return get_arg_type(fn, param);
7641f5207b7SJohn Levon 	if (strcmp(key, "*$") == 0) {
7651f5207b7SJohn Levon 		type = get_arg_type(fn, param);
7661f5207b7SJohn Levon 		if (!type || type->type != SYM_PTR)
7671f5207b7SJohn Levon 			return NULL;
7681f5207b7SJohn Levon 		return get_real_base_type(type);
7691f5207b7SJohn Levon 	}
7701f5207b7SJohn Levon 	return get_member_type_from_key(arg, key);
7711f5207b7SJohn Levon }
7721f5207b7SJohn Levon 
is_struct(struct expression * expr)7731f5207b7SJohn Levon int is_struct(struct expression *expr)
7741f5207b7SJohn Levon {
7751f5207b7SJohn Levon 	struct symbol *type;
7761f5207b7SJohn Levon 
7771f5207b7SJohn Levon 	type = get_type(expr);
7781f5207b7SJohn Levon 	if (type && type->type == SYM_STRUCT)
7791f5207b7SJohn Levon 		return 1;
7801f5207b7SJohn Levon 	return 0;
7811f5207b7SJohn Levon }
7821f5207b7SJohn Levon 
7831f5207b7SJohn Levon static struct {
7841f5207b7SJohn Levon 	struct symbol *sym;
7851f5207b7SJohn Levon 	const char *name;
7861f5207b7SJohn Levon } base_types[] = {
7871f5207b7SJohn Levon 	{&bool_ctype, "bool"},
7881f5207b7SJohn Levon 	{&void_ctype, "void"},
7891f5207b7SJohn Levon 	{&type_ctype, "type"},
7901f5207b7SJohn Levon 	{&char_ctype, "char"},
7911f5207b7SJohn Levon 	{&schar_ctype, "schar"},
7921f5207b7SJohn Levon 	{&uchar_ctype, "uchar"},
7931f5207b7SJohn Levon 	{&short_ctype, "short"},
7941f5207b7SJohn Levon 	{&sshort_ctype, "sshort"},
7951f5207b7SJohn Levon 	{&ushort_ctype, "ushort"},
7961f5207b7SJohn Levon 	{&int_ctype, "int"},
7971f5207b7SJohn Levon 	{&sint_ctype, "sint"},
7981f5207b7SJohn Levon 	{&uint_ctype, "uint"},
7991f5207b7SJohn Levon 	{&long_ctype, "long"},
8001f5207b7SJohn Levon 	{&slong_ctype, "slong"},
8011f5207b7SJohn Levon 	{&ulong_ctype, "ulong"},
8021f5207b7SJohn Levon 	{&llong_ctype, "llong"},
8031f5207b7SJohn Levon 	{&sllong_ctype, "sllong"},
8041f5207b7SJohn Levon 	{&ullong_ctype, "ullong"},
8051f5207b7SJohn Levon 	{&lllong_ctype, "lllong"},
8061f5207b7SJohn Levon 	{&slllong_ctype, "slllong"},
8071f5207b7SJohn Levon 	{&ulllong_ctype, "ulllong"},
8081f5207b7SJohn Levon 	{&float_ctype, "float"},
8091f5207b7SJohn Levon 	{&double_ctype, "double"},
8101f5207b7SJohn Levon 	{&ldouble_ctype, "ldouble"},
8111f5207b7SJohn Levon 	{&string_ctype, "string"},
8121f5207b7SJohn Levon 	{&ptr_ctype, "ptr"},
8131f5207b7SJohn Levon 	{&lazy_ptr_ctype, "lazy_ptr"},
8141f5207b7SJohn Levon 	{&incomplete_ctype, "incomplete"},
8151f5207b7SJohn Levon 	{&label_ctype, "label"},
8161f5207b7SJohn Levon 	{&bad_ctype, "bad"},
8171f5207b7SJohn Levon 	{&null_ctype, "null"},
8181f5207b7SJohn Levon };
8191f5207b7SJohn Levon 
base_type_str(struct symbol * sym)8201f5207b7SJohn Levon static const char *base_type_str(struct symbol *sym)
8211f5207b7SJohn Levon {
8221f5207b7SJohn Levon 	int i;
8231f5207b7SJohn Levon 
8241f5207b7SJohn Levon 	for (i = 0; i < ARRAY_SIZE(base_types); i++) {
8251f5207b7SJohn Levon 		if (sym == base_types[i].sym)
8261f5207b7SJohn Levon 			return base_types[i].name;
8271f5207b7SJohn Levon 	}
8281f5207b7SJohn Levon 	return "<unknown>";
8291f5207b7SJohn Levon }
8301f5207b7SJohn Levon 
type_str_helper(char * buf,int size,struct symbol * type)8311f5207b7SJohn Levon static int type_str_helper(char *buf, int size, struct symbol *type)
8321f5207b7SJohn Levon {
8331f5207b7SJohn Levon 	int n;
8341f5207b7SJohn Levon 
8351f5207b7SJohn Levon 	if (!type)
83631ad075eSJohn Levon 		return snprintf(buf, size, "<null type>");
8371f5207b7SJohn Levon 
8381f5207b7SJohn Levon 	if (type->type == SYM_BASETYPE) {
839efe51d0cSJohn Levon 		return snprintf(buf, size, "%s", base_type_str(type));
8401f5207b7SJohn Levon 	} else if (type->type == SYM_PTR) {
8411f5207b7SJohn Levon 		type = get_real_base_type(type);
8421f5207b7SJohn Levon 		n = type_str_helper(buf, size, type);
8431f5207b7SJohn Levon 		if (n > size)
8441f5207b7SJohn Levon 			return n;
8451f5207b7SJohn Levon 		return n + snprintf(buf + n, size - n, "*");
8461f5207b7SJohn Levon 	} else if (type->type == SYM_ARRAY) {
8471f5207b7SJohn Levon 		type = get_real_base_type(type);
8481f5207b7SJohn Levon 		n = type_str_helper(buf, size, type);
8491f5207b7SJohn Levon 		if (n > size)
8501f5207b7SJohn Levon 			return n;
8511f5207b7SJohn Levon 		return n + snprintf(buf + n, size - n, "[]");
8521f5207b7SJohn Levon 	} else if (type->type == SYM_STRUCT) {
8531f5207b7SJohn Levon 		return snprintf(buf, size, "struct %s", type->ident ? type->ident->name : "");
8541f5207b7SJohn Levon 	} else if (type->type == SYM_UNION) {
8551f5207b7SJohn Levon 		if (type->ident)
8561f5207b7SJohn Levon 			return snprintf(buf, size, "union %s", type->ident->name);
8571f5207b7SJohn Levon 		else
8581f5207b7SJohn Levon 			return snprintf(buf, size, "anonymous union");
8591f5207b7SJohn Levon 	} else if (type->type == SYM_FN) {
8601f5207b7SJohn Levon 		struct symbol *arg, *return_type, *arg_type;
8611f5207b7SJohn Levon 		int i;
8621f5207b7SJohn Levon 
8631f5207b7SJohn Levon 		return_type = get_real_base_type(type);
8641f5207b7SJohn Levon 		n = type_str_helper(buf, size, return_type);
8651f5207b7SJohn Levon 		if (n > size)
8661f5207b7SJohn Levon 			return n;
8671f5207b7SJohn Levon 		n += snprintf(buf + n, size - n, "(*)(");
8681f5207b7SJohn Levon 		if (n > size)
8691f5207b7SJohn Levon 			return n;
8701f5207b7SJohn Levon 
8711f5207b7SJohn Levon 		i = 0;
8721f5207b7SJohn Levon 		FOR_EACH_PTR(type->arguments, arg) {
8731f5207b7SJohn Levon 			if (i++)
8741f5207b7SJohn Levon 				n += snprintf(buf + n, size - n, ", ");
8751f5207b7SJohn Levon 			if (n > size)
8761f5207b7SJohn Levon 				return n;
8771f5207b7SJohn Levon 			arg_type = get_real_base_type(arg);
8781f5207b7SJohn Levon 			n += type_str_helper(buf + n, size - n, arg_type);
8791f5207b7SJohn Levon 			if (n > size)
8801f5207b7SJohn Levon 				return n;
8811f5207b7SJohn Levon 		} END_FOR_EACH_PTR(arg);
8821f5207b7SJohn Levon 
8831f5207b7SJohn Levon 		return n + snprintf(buf + n, size - n, ")");
8841f5207b7SJohn Levon 	} else if (type->type == SYM_NODE) {
8851f5207b7SJohn Levon 		n = snprintf(buf, size, "node {");
8861f5207b7SJohn Levon 		if (n > size)
8871f5207b7SJohn Levon 			return n;
8881f5207b7SJohn Levon 		type = get_real_base_type(type);
8891f5207b7SJohn Levon 		n += type_str_helper(buf + n, size - n, type);
8901f5207b7SJohn Levon 		if (n > size)
8911f5207b7SJohn Levon 			return n;
8921f5207b7SJohn Levon 		return n + snprintf(buf + n, size - n, "}");
893efe51d0cSJohn Levon 	} else if (type->type == SYM_ENUM) {
894efe51d0cSJohn Levon 		return snprintf(buf, size, "enum %s", type->ident ? type->ident->name : "<unknown>");
8951f5207b7SJohn Levon 	} else {
8961f5207b7SJohn Levon 		return snprintf(buf, size, "<type %d>", type->type);
8971f5207b7SJohn Levon 	}
8981f5207b7SJohn Levon }
8991f5207b7SJohn Levon 
type_to_str(struct symbol * type)9001f5207b7SJohn Levon char *type_to_str(struct symbol *type)
9011f5207b7SJohn Levon {
9021f5207b7SJohn Levon 	static char buf[256];
9031f5207b7SJohn Levon 
9041f5207b7SJohn Levon 	buf[0] = '\0';
9051f5207b7SJohn Levon 	type_str_helper(buf, sizeof(buf), type);
9061f5207b7SJohn Levon 	return buf;
9071f5207b7SJohn Levon }
908