1*1f5207b7SJohn Levon /*
2*1f5207b7SJohn Levon  * Copyright (C) 2009 Dan Carpenter.
3*1f5207b7SJohn Levon  *
4*1f5207b7SJohn Levon  * This program is free software; you can redistribute it and/or
5*1f5207b7SJohn Levon  * modify it under the terms of the GNU General Public License
6*1f5207b7SJohn Levon  * as published by the Free Software Foundation; either version 2
7*1f5207b7SJohn Levon  * of the License, or (at your option) any later version.
8*1f5207b7SJohn Levon  *
9*1f5207b7SJohn Levon  * This program is distributed in the hope that it will be useful,
10*1f5207b7SJohn Levon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*1f5207b7SJohn Levon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*1f5207b7SJohn Levon  * GNU General Public License for more details.
13*1f5207b7SJohn Levon  *
14*1f5207b7SJohn Levon  * You should have received a copy of the GNU General Public License
15*1f5207b7SJohn Levon  * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16*1f5207b7SJohn Levon  */
17*1f5207b7SJohn Levon 
18*1f5207b7SJohn Levon /*
19*1f5207b7SJohn Levon  * The idea here is that you have an expression and you
20*1f5207b7SJohn Levon  * want to know what the type is for that.
21*1f5207b7SJohn Levon  */
22*1f5207b7SJohn Levon 
23*1f5207b7SJohn Levon #include "smatch.h"
24*1f5207b7SJohn Levon #include "smatch_slist.h"
25*1f5207b7SJohn Levon 
26*1f5207b7SJohn Levon struct symbol *get_real_base_type(struct symbol *sym)
27*1f5207b7SJohn Levon {
28*1f5207b7SJohn Levon 	struct symbol *ret;
29*1f5207b7SJohn Levon 
30*1f5207b7SJohn Levon 	if (!sym)
31*1f5207b7SJohn Levon 		return NULL;
32*1f5207b7SJohn Levon 	ret = get_base_type(sym);
33*1f5207b7SJohn Levon 	if (!ret)
34*1f5207b7SJohn Levon 		return NULL;
35*1f5207b7SJohn Levon 	if (ret->type == SYM_RESTRICT || ret->type == SYM_NODE)
36*1f5207b7SJohn Levon 		return get_real_base_type(ret);
37*1f5207b7SJohn Levon 	return ret;
38*1f5207b7SJohn Levon }
39*1f5207b7SJohn Levon 
40*1f5207b7SJohn Levon int type_bytes(struct symbol *type)
41*1f5207b7SJohn Levon {
42*1f5207b7SJohn Levon 	int bits;
43*1f5207b7SJohn Levon 
44*1f5207b7SJohn Levon 	if (type && type->type == SYM_ARRAY)
45*1f5207b7SJohn Levon 		return array_bytes(type);
46*1f5207b7SJohn Levon 
47*1f5207b7SJohn Levon 	bits = type_bits(type);
48*1f5207b7SJohn Levon 	if (bits < 0)
49*1f5207b7SJohn Levon 		return 0;
50*1f5207b7SJohn Levon 	return bits_to_bytes(bits);
51*1f5207b7SJohn Levon }
52*1f5207b7SJohn Levon 
53*1f5207b7SJohn Levon int array_bytes(struct symbol *type)
54*1f5207b7SJohn Levon {
55*1f5207b7SJohn Levon 	if (!type || type->type != SYM_ARRAY)
56*1f5207b7SJohn Levon 		return 0;
57*1f5207b7SJohn Levon 	return bits_to_bytes(type->bit_size);
58*1f5207b7SJohn Levon }
59*1f5207b7SJohn Levon 
60*1f5207b7SJohn Levon static struct symbol *get_binop_type(struct expression *expr)
61*1f5207b7SJohn Levon {
62*1f5207b7SJohn Levon 	struct symbol *left, *right;
63*1f5207b7SJohn Levon 
64*1f5207b7SJohn Levon 	left = get_type(expr->left);
65*1f5207b7SJohn Levon 	if (!left)
66*1f5207b7SJohn Levon 		return NULL;
67*1f5207b7SJohn Levon 
68*1f5207b7SJohn Levon 	if (expr->op == SPECIAL_LEFTSHIFT ||
69*1f5207b7SJohn Levon 	    expr->op == SPECIAL_RIGHTSHIFT) {
70*1f5207b7SJohn Levon 		if (type_positive_bits(left) < 31)
71*1f5207b7SJohn Levon 			return &int_ctype;
72*1f5207b7SJohn Levon 		return left;
73*1f5207b7SJohn Levon 	}
74*1f5207b7SJohn Levon 	right = get_type(expr->right);
75*1f5207b7SJohn Levon 	if (!right)
76*1f5207b7SJohn Levon 		return NULL;
77*1f5207b7SJohn Levon 
78*1f5207b7SJohn Levon 	if (left->type == SYM_PTR || left->type == SYM_ARRAY)
79*1f5207b7SJohn Levon 		return left;
80*1f5207b7SJohn Levon 	if (right->type == SYM_PTR || right->type == SYM_ARRAY)
81*1f5207b7SJohn Levon 		return right;
82*1f5207b7SJohn Levon 
83*1f5207b7SJohn Levon 	if (type_positive_bits(left) < 31 && type_positive_bits(right) < 31)
84*1f5207b7SJohn Levon 		return &int_ctype;
85*1f5207b7SJohn Levon 
86*1f5207b7SJohn Levon 	if (type_positive_bits(left) > type_positive_bits(right))
87*1f5207b7SJohn Levon 		return left;
88*1f5207b7SJohn Levon 	return right;
89*1f5207b7SJohn Levon }
90*1f5207b7SJohn Levon 
91*1f5207b7SJohn Levon static struct symbol *get_type_symbol(struct expression *expr)
92*1f5207b7SJohn Levon {
93*1f5207b7SJohn Levon 	if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol)
94*1f5207b7SJohn Levon 		return NULL;
95*1f5207b7SJohn Levon 
96*1f5207b7SJohn Levon 	return get_real_base_type(expr->symbol);
97*1f5207b7SJohn Levon }
98*1f5207b7SJohn Levon 
99*1f5207b7SJohn Levon static struct symbol *get_member_symbol(struct symbol_list *symbol_list, struct ident *member)
100*1f5207b7SJohn Levon {
101*1f5207b7SJohn Levon 	struct symbol *tmp, *sub;
102*1f5207b7SJohn Levon 
103*1f5207b7SJohn Levon 	FOR_EACH_PTR(symbol_list, tmp) {
104*1f5207b7SJohn Levon 		if (!tmp->ident) {
105*1f5207b7SJohn Levon 			sub = get_real_base_type(tmp);
106*1f5207b7SJohn Levon 			sub = get_member_symbol(sub->symbol_list, member);
107*1f5207b7SJohn Levon 			if (sub)
108*1f5207b7SJohn Levon 				return sub;
109*1f5207b7SJohn Levon 			continue;
110*1f5207b7SJohn Levon 		}
111*1f5207b7SJohn Levon 		if (tmp->ident == member)
112*1f5207b7SJohn Levon 			return tmp;
113*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(tmp);
114*1f5207b7SJohn Levon 
115*1f5207b7SJohn Levon 	return NULL;
116*1f5207b7SJohn Levon }
117*1f5207b7SJohn Levon 
118*1f5207b7SJohn Levon static struct symbol *get_symbol_from_deref(struct expression *expr)
119*1f5207b7SJohn Levon {
120*1f5207b7SJohn Levon 	struct ident *member;
121*1f5207b7SJohn Levon 	struct symbol *sym;
122*1f5207b7SJohn Levon 
123*1f5207b7SJohn Levon 	if (!expr || expr->type != EXPR_DEREF)
124*1f5207b7SJohn Levon 		return NULL;
125*1f5207b7SJohn Levon 
126*1f5207b7SJohn Levon 	member = expr->member;
127*1f5207b7SJohn Levon 	sym = get_type(expr->deref);
128*1f5207b7SJohn Levon 	if (!sym) {
129*1f5207b7SJohn Levon 		// sm_msg("could not find struct type");
130*1f5207b7SJohn Levon 		return NULL;
131*1f5207b7SJohn Levon 	}
132*1f5207b7SJohn Levon 	if (sym->type == SYM_PTR)
133*1f5207b7SJohn Levon 		sym = get_real_base_type(sym);
134*1f5207b7SJohn Levon 	sym = get_member_symbol(sym->symbol_list, member);
135*1f5207b7SJohn Levon 	if (!sym)
136*1f5207b7SJohn Levon 		return NULL;
137*1f5207b7SJohn Levon 	return get_real_base_type(sym);
138*1f5207b7SJohn Levon }
139*1f5207b7SJohn Levon 
140*1f5207b7SJohn Levon static struct symbol *get_return_type(struct expression *expr)
141*1f5207b7SJohn Levon {
142*1f5207b7SJohn Levon 	struct symbol *tmp;
143*1f5207b7SJohn Levon 
144*1f5207b7SJohn Levon 	tmp = get_type(expr->fn);
145*1f5207b7SJohn Levon 	if (!tmp)
146*1f5207b7SJohn Levon 		return NULL;
147*1f5207b7SJohn Levon 	/* this is to handle __builtin_constant_p() */
148*1f5207b7SJohn Levon 	if (tmp->type != SYM_FN)
149*1f5207b7SJohn Levon 		tmp = get_base_type(tmp);
150*1f5207b7SJohn Levon 	return get_real_base_type(tmp);
151*1f5207b7SJohn Levon }
152*1f5207b7SJohn Levon 
153*1f5207b7SJohn Levon static struct symbol *get_expr_stmt_type(struct statement *stmt)
154*1f5207b7SJohn Levon {
155*1f5207b7SJohn Levon 	if (stmt->type != STMT_COMPOUND)
156*1f5207b7SJohn Levon 		return NULL;
157*1f5207b7SJohn Levon 	stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
158*1f5207b7SJohn Levon 	if (stmt->type == STMT_LABEL)
159*1f5207b7SJohn Levon 		stmt = stmt->label_statement;
160*1f5207b7SJohn Levon 	if (stmt->type != STMT_EXPRESSION)
161*1f5207b7SJohn Levon 		return NULL;
162*1f5207b7SJohn Levon 	return get_type(stmt->expression);
163*1f5207b7SJohn Levon }
164*1f5207b7SJohn Levon 
165*1f5207b7SJohn Levon static struct symbol *get_select_type(struct expression *expr)
166*1f5207b7SJohn Levon {
167*1f5207b7SJohn Levon 	struct symbol *one, *two;
168*1f5207b7SJohn Levon 
169*1f5207b7SJohn Levon 	one = get_type(expr->cond_true);
170*1f5207b7SJohn Levon 	two = get_type(expr->cond_false);
171*1f5207b7SJohn Levon 	if (!one || !two)
172*1f5207b7SJohn Levon 		return NULL;
173*1f5207b7SJohn Levon 	/*
174*1f5207b7SJohn Levon 	 * This is a hack.  If the types are not equiv then we
175*1f5207b7SJohn Levon 	 * really don't know the type.  But I think guessing is
176*1f5207b7SJohn Levon 	 *  probably Ok here.
177*1f5207b7SJohn Levon 	 */
178*1f5207b7SJohn Levon 	if (type_positive_bits(one) > type_positive_bits(two))
179*1f5207b7SJohn Levon 		return one;
180*1f5207b7SJohn Levon 	return two;
181*1f5207b7SJohn Levon }
182*1f5207b7SJohn Levon 
183*1f5207b7SJohn Levon struct symbol *get_pointer_type(struct expression *expr)
184*1f5207b7SJohn Levon {
185*1f5207b7SJohn Levon 	struct symbol *sym;
186*1f5207b7SJohn Levon 
187*1f5207b7SJohn Levon 	sym = get_type(expr);
188*1f5207b7SJohn Levon 	if (!sym)
189*1f5207b7SJohn Levon 		return NULL;
190*1f5207b7SJohn Levon 	if (sym->type == SYM_NODE) {
191*1f5207b7SJohn Levon 		sym = get_real_base_type(sym);
192*1f5207b7SJohn Levon 		if (!sym)
193*1f5207b7SJohn Levon 			return NULL;
194*1f5207b7SJohn Levon 	}
195*1f5207b7SJohn Levon 	if (sym->type != SYM_PTR && sym->type != SYM_ARRAY)
196*1f5207b7SJohn Levon 		return NULL;
197*1f5207b7SJohn Levon 	return get_real_base_type(sym);
198*1f5207b7SJohn Levon }
199*1f5207b7SJohn Levon 
200*1f5207b7SJohn Levon static struct symbol *fake_pointer_sym(struct expression *expr)
201*1f5207b7SJohn Levon {
202*1f5207b7SJohn Levon 	struct symbol *sym;
203*1f5207b7SJohn Levon 	struct symbol *base;
204*1f5207b7SJohn Levon 
205*1f5207b7SJohn Levon 	sym = alloc_symbol(expr->pos, SYM_PTR);
206*1f5207b7SJohn Levon 	expr = expr->unop;
207*1f5207b7SJohn Levon 	base = get_type(expr);
208*1f5207b7SJohn Levon 	if (!base)
209*1f5207b7SJohn Levon 		return NULL;
210*1f5207b7SJohn Levon 	sym->ctype.base_type = base;
211*1f5207b7SJohn Levon 	return sym;
212*1f5207b7SJohn Levon }
213*1f5207b7SJohn Levon 
214*1f5207b7SJohn Levon static struct symbol *get_type_helper(struct expression *expr)
215*1f5207b7SJohn Levon {
216*1f5207b7SJohn Levon 	struct symbol *ret;
217*1f5207b7SJohn Levon 
218*1f5207b7SJohn Levon 	expr = strip_parens(expr);
219*1f5207b7SJohn Levon 	if (!expr)
220*1f5207b7SJohn Levon 		return NULL;
221*1f5207b7SJohn Levon 
222*1f5207b7SJohn Levon 	if (expr->ctype)
223*1f5207b7SJohn Levon 		return expr->ctype;
224*1f5207b7SJohn Levon 
225*1f5207b7SJohn Levon 	switch (expr->type) {
226*1f5207b7SJohn Levon 	case EXPR_STRING:
227*1f5207b7SJohn Levon 		ret = &string_ctype;
228*1f5207b7SJohn Levon 		break;
229*1f5207b7SJohn Levon 	case EXPR_SYMBOL:
230*1f5207b7SJohn Levon 		ret = get_type_symbol(expr);
231*1f5207b7SJohn Levon 		break;
232*1f5207b7SJohn Levon 	case EXPR_DEREF:
233*1f5207b7SJohn Levon 		ret = get_symbol_from_deref(expr);
234*1f5207b7SJohn Levon 		break;
235*1f5207b7SJohn Levon 	case EXPR_PREOP:
236*1f5207b7SJohn Levon 	case EXPR_POSTOP:
237*1f5207b7SJohn Levon 		if (expr->op == '&')
238*1f5207b7SJohn Levon 			ret = fake_pointer_sym(expr);
239*1f5207b7SJohn Levon 		else if (expr->op == '*')
240*1f5207b7SJohn Levon 			ret = get_pointer_type(expr->unop);
241*1f5207b7SJohn Levon 		else
242*1f5207b7SJohn Levon 			ret = get_type(expr->unop);
243*1f5207b7SJohn Levon 		break;
244*1f5207b7SJohn Levon 	case EXPR_ASSIGNMENT:
245*1f5207b7SJohn Levon 		ret = get_type(expr->left);
246*1f5207b7SJohn Levon 		break;
247*1f5207b7SJohn Levon 	case EXPR_CAST:
248*1f5207b7SJohn Levon 	case EXPR_FORCE_CAST:
249*1f5207b7SJohn Levon 	case EXPR_IMPLIED_CAST:
250*1f5207b7SJohn Levon 		ret = get_real_base_type(expr->cast_type);
251*1f5207b7SJohn Levon 		break;
252*1f5207b7SJohn Levon 	case EXPR_COMPARE:
253*1f5207b7SJohn Levon 	case EXPR_BINOP:
254*1f5207b7SJohn Levon 		ret = get_binop_type(expr);
255*1f5207b7SJohn Levon 		break;
256*1f5207b7SJohn Levon 	case EXPR_CALL:
257*1f5207b7SJohn Levon 		ret = get_return_type(expr);
258*1f5207b7SJohn Levon 		break;
259*1f5207b7SJohn Levon 	case EXPR_STATEMENT:
260*1f5207b7SJohn Levon 		ret = get_expr_stmt_type(expr->statement);
261*1f5207b7SJohn Levon 		break;
262*1f5207b7SJohn Levon 	case EXPR_CONDITIONAL:
263*1f5207b7SJohn Levon 	case EXPR_SELECT:
264*1f5207b7SJohn Levon 		ret = get_select_type(expr);
265*1f5207b7SJohn Levon 		break;
266*1f5207b7SJohn Levon 	case EXPR_SIZEOF:
267*1f5207b7SJohn Levon 		ret = &ulong_ctype;
268*1f5207b7SJohn Levon 		break;
269*1f5207b7SJohn Levon 	case EXPR_LOGICAL:
270*1f5207b7SJohn Levon 		ret = &int_ctype;
271*1f5207b7SJohn Levon 		break;
272*1f5207b7SJohn Levon 	default:
273*1f5207b7SJohn Levon 		return NULL;
274*1f5207b7SJohn Levon 	}
275*1f5207b7SJohn Levon 
276*1f5207b7SJohn Levon 	if (ret && ret->type == SYM_TYPEOF)
277*1f5207b7SJohn Levon 		ret = get_type(ret->initializer);
278*1f5207b7SJohn Levon 
279*1f5207b7SJohn Levon 	expr->ctype = ret;
280*1f5207b7SJohn Levon 	return ret;
281*1f5207b7SJohn Levon }
282*1f5207b7SJohn Levon 
283*1f5207b7SJohn Levon static struct symbol *get_final_type_helper(struct expression *expr)
284*1f5207b7SJohn Levon {
285*1f5207b7SJohn Levon 	/*
286*1f5207b7SJohn Levon 	 * I'm not totally positive I understand types...
287*1f5207b7SJohn Levon 	 *
288*1f5207b7SJohn Levon 	 * So, when you're doing pointer math, and you do a subtraction, then
289*1f5207b7SJohn Levon 	 * the sval_binop() and whatever need to know the type of the pointer
290*1f5207b7SJohn Levon 	 * so they can figure out the alignment.  But the result is going to be
291*1f5207b7SJohn Levon 	 * and ssize_t.  So get_operation_type() gives you the pointer type
292*1f5207b7SJohn Levon 	 * and get_type() gives you ssize_t.
293*1f5207b7SJohn Levon 	 *
294*1f5207b7SJohn Levon 	 * Most of the time the operation type and the final type are the same
295*1f5207b7SJohn Levon 	 * but this just handles the few places where they are different.
296*1f5207b7SJohn Levon 	 *
297*1f5207b7SJohn Levon 	 */
298*1f5207b7SJohn Levon 
299*1f5207b7SJohn Levon 	expr = strip_parens(expr);
300*1f5207b7SJohn Levon 	if (!expr)
301*1f5207b7SJohn Levon 		return NULL;
302*1f5207b7SJohn Levon 
303*1f5207b7SJohn Levon 	switch (expr->type) {
304*1f5207b7SJohn Levon 	case EXPR_COMPARE:
305*1f5207b7SJohn Levon 		return &int_ctype;
306*1f5207b7SJohn Levon 	case EXPR_BINOP: {
307*1f5207b7SJohn Levon 		struct symbol *left, *right;
308*1f5207b7SJohn Levon 
309*1f5207b7SJohn Levon 		if (expr->op != '-')
310*1f5207b7SJohn Levon 			return NULL;
311*1f5207b7SJohn Levon 
312*1f5207b7SJohn Levon 		left = get_type(expr->left);
313*1f5207b7SJohn Levon 		right = get_type(expr->right);
314*1f5207b7SJohn Levon 		if (type_is_ptr(left) || type_is_ptr(right))
315*1f5207b7SJohn Levon 			return ssize_t_ctype;
316*1f5207b7SJohn Levon 		}
317*1f5207b7SJohn Levon 	}
318*1f5207b7SJohn Levon 
319*1f5207b7SJohn Levon 	return NULL;
320*1f5207b7SJohn Levon }
321*1f5207b7SJohn Levon 
322*1f5207b7SJohn Levon struct symbol *get_type(struct expression *expr)
323*1f5207b7SJohn Levon {
324*1f5207b7SJohn Levon 	return get_type_helper(expr);
325*1f5207b7SJohn Levon }
326*1f5207b7SJohn Levon 
327*1f5207b7SJohn Levon struct symbol *get_final_type(struct expression *expr)
328*1f5207b7SJohn Levon {
329*1f5207b7SJohn Levon 	struct symbol *ret;
330*1f5207b7SJohn Levon 
331*1f5207b7SJohn Levon 	ret = get_final_type_helper(expr);
332*1f5207b7SJohn Levon 	if (ret)
333*1f5207b7SJohn Levon 		return ret;
334*1f5207b7SJohn Levon 	return get_type_helper(expr);
335*1f5207b7SJohn Levon }
336*1f5207b7SJohn Levon 
337*1f5207b7SJohn Levon struct symbol *get_promoted_type(struct symbol *left, struct symbol *right)
338*1f5207b7SJohn Levon {
339*1f5207b7SJohn Levon 	struct symbol *ret = &int_ctype;
340*1f5207b7SJohn Levon 
341*1f5207b7SJohn Levon 	if (type_positive_bits(left) > type_positive_bits(ret))
342*1f5207b7SJohn Levon 		ret = left;
343*1f5207b7SJohn Levon 	if (type_positive_bits(right) > type_positive_bits(ret))
344*1f5207b7SJohn Levon 		ret = right;
345*1f5207b7SJohn Levon 
346*1f5207b7SJohn Levon 	if (type_is_ptr(left))
347*1f5207b7SJohn Levon 		ret = left;
348*1f5207b7SJohn Levon 	if (type_is_ptr(right))
349*1f5207b7SJohn Levon 		ret = right;
350*1f5207b7SJohn Levon 
351*1f5207b7SJohn Levon 	return ret;
352*1f5207b7SJohn Levon }
353*1f5207b7SJohn Levon 
354*1f5207b7SJohn Levon int type_signed(struct symbol *base_type)
355*1f5207b7SJohn Levon {
356*1f5207b7SJohn Levon 	if (!base_type)
357*1f5207b7SJohn Levon 		return 0;
358*1f5207b7SJohn Levon 	if (base_type->ctype.modifiers & MOD_SIGNED)
359*1f5207b7SJohn Levon 		return 1;
360*1f5207b7SJohn Levon 	return 0;
361*1f5207b7SJohn Levon }
362*1f5207b7SJohn Levon 
363*1f5207b7SJohn Levon int expr_unsigned(struct expression *expr)
364*1f5207b7SJohn Levon {
365*1f5207b7SJohn Levon 	struct symbol *sym;
366*1f5207b7SJohn Levon 
367*1f5207b7SJohn Levon 	sym = get_type(expr);
368*1f5207b7SJohn Levon 	if (!sym)
369*1f5207b7SJohn Levon 		return 0;
370*1f5207b7SJohn Levon 	if (type_unsigned(sym))
371*1f5207b7SJohn Levon 		return 1;
372*1f5207b7SJohn Levon 	return 0;
373*1f5207b7SJohn Levon }
374*1f5207b7SJohn Levon 
375*1f5207b7SJohn Levon int expr_signed(struct expression *expr)
376*1f5207b7SJohn Levon {
377*1f5207b7SJohn Levon 	struct symbol *sym;
378*1f5207b7SJohn Levon 
379*1f5207b7SJohn Levon 	sym = get_type(expr);
380*1f5207b7SJohn Levon 	if (!sym)
381*1f5207b7SJohn Levon 		return 0;
382*1f5207b7SJohn Levon 	if (type_signed(sym))
383*1f5207b7SJohn Levon 		return 1;
384*1f5207b7SJohn Levon 	return 0;
385*1f5207b7SJohn Levon }
386*1f5207b7SJohn Levon 
387*1f5207b7SJohn Levon int returns_unsigned(struct symbol *sym)
388*1f5207b7SJohn Levon {
389*1f5207b7SJohn Levon 	if (!sym)
390*1f5207b7SJohn Levon 		return 0;
391*1f5207b7SJohn Levon 	sym = get_base_type(sym);
392*1f5207b7SJohn Levon 	if (!sym || sym->type != SYM_FN)
393*1f5207b7SJohn Levon 		return 0;
394*1f5207b7SJohn Levon 	sym = get_base_type(sym);
395*1f5207b7SJohn Levon 	return type_unsigned(sym);
396*1f5207b7SJohn Levon }
397*1f5207b7SJohn Levon 
398*1f5207b7SJohn Levon int is_pointer(struct expression *expr)
399*1f5207b7SJohn Levon {
400*1f5207b7SJohn Levon 	struct symbol *sym;
401*1f5207b7SJohn Levon 
402*1f5207b7SJohn Levon 	sym = get_type(expr);
403*1f5207b7SJohn Levon 	if (!sym)
404*1f5207b7SJohn Levon 		return 0;
405*1f5207b7SJohn Levon 	if (sym == &string_ctype)
406*1f5207b7SJohn Levon 		return 0;
407*1f5207b7SJohn Levon 	if (sym->type == SYM_PTR)
408*1f5207b7SJohn Levon 		return 1;
409*1f5207b7SJohn Levon 	return 0;
410*1f5207b7SJohn Levon }
411*1f5207b7SJohn Levon 
412*1f5207b7SJohn Levon int returns_pointer(struct symbol *sym)
413*1f5207b7SJohn Levon {
414*1f5207b7SJohn Levon 	if (!sym)
415*1f5207b7SJohn Levon 		return 0;
416*1f5207b7SJohn Levon 	sym = get_base_type(sym);
417*1f5207b7SJohn Levon 	if (!sym || sym->type != SYM_FN)
418*1f5207b7SJohn Levon 		return 0;
419*1f5207b7SJohn Levon 	sym = get_base_type(sym);
420*1f5207b7SJohn Levon 	if (sym->type == SYM_PTR)
421*1f5207b7SJohn Levon 		return 1;
422*1f5207b7SJohn Levon 	return 0;
423*1f5207b7SJohn Levon }
424*1f5207b7SJohn Levon 
425*1f5207b7SJohn Levon sval_t sval_type_max(struct symbol *base_type)
426*1f5207b7SJohn Levon {
427*1f5207b7SJohn Levon 	sval_t ret;
428*1f5207b7SJohn Levon 
429*1f5207b7SJohn Levon 	if (!base_type || !type_bits(base_type))
430*1f5207b7SJohn Levon 		base_type = &llong_ctype;
431*1f5207b7SJohn Levon 	ret.type = base_type;
432*1f5207b7SJohn Levon 
433*1f5207b7SJohn Levon 	ret.value = (~0ULL) >> (64 - type_positive_bits(base_type));
434*1f5207b7SJohn Levon 	return ret;
435*1f5207b7SJohn Levon }
436*1f5207b7SJohn Levon 
437*1f5207b7SJohn Levon sval_t sval_type_min(struct symbol *base_type)
438*1f5207b7SJohn Levon {
439*1f5207b7SJohn Levon 	sval_t ret;
440*1f5207b7SJohn Levon 
441*1f5207b7SJohn Levon 	if (!base_type || !type_bits(base_type))
442*1f5207b7SJohn Levon 		base_type = &llong_ctype;
443*1f5207b7SJohn Levon 	ret.type = base_type;
444*1f5207b7SJohn Levon 
445*1f5207b7SJohn Levon 	if (type_unsigned(base_type)) {
446*1f5207b7SJohn Levon 		ret.value = 0;
447*1f5207b7SJohn Levon 		return ret;
448*1f5207b7SJohn Levon 	}
449*1f5207b7SJohn Levon 
450*1f5207b7SJohn Levon 	ret.value = (~0ULL) << type_positive_bits(base_type);
451*1f5207b7SJohn Levon 
452*1f5207b7SJohn Levon 	return ret;
453*1f5207b7SJohn Levon }
454*1f5207b7SJohn Levon 
455*1f5207b7SJohn Levon int nr_bits(struct expression *expr)
456*1f5207b7SJohn Levon {
457*1f5207b7SJohn Levon 	struct symbol *type;
458*1f5207b7SJohn Levon 
459*1f5207b7SJohn Levon 	type = get_type(expr);
460*1f5207b7SJohn Levon 	if (!type)
461*1f5207b7SJohn Levon 		return 0;
462*1f5207b7SJohn Levon 	return type_bits(type);
463*1f5207b7SJohn Levon }
464*1f5207b7SJohn Levon 
465*1f5207b7SJohn Levon int is_void_pointer(struct expression *expr)
466*1f5207b7SJohn Levon {
467*1f5207b7SJohn Levon 	struct symbol *type;
468*1f5207b7SJohn Levon 
469*1f5207b7SJohn Levon 	type = get_type(expr);
470*1f5207b7SJohn Levon 	if (!type || type->type != SYM_PTR)
471*1f5207b7SJohn Levon 		return 0;
472*1f5207b7SJohn Levon 	type = get_real_base_type(type);
473*1f5207b7SJohn Levon 	if (type == &void_ctype)
474*1f5207b7SJohn Levon 		return 1;
475*1f5207b7SJohn Levon 	return 0;
476*1f5207b7SJohn Levon }
477*1f5207b7SJohn Levon 
478*1f5207b7SJohn Levon int is_char_pointer(struct expression *expr)
479*1f5207b7SJohn Levon {
480*1f5207b7SJohn Levon 	struct symbol *type;
481*1f5207b7SJohn Levon 
482*1f5207b7SJohn Levon 	type = get_type(expr);
483*1f5207b7SJohn Levon 	if (!type || type->type != SYM_PTR)
484*1f5207b7SJohn Levon 		return 0;
485*1f5207b7SJohn Levon 	type = get_real_base_type(type);
486*1f5207b7SJohn Levon 	if (type == &char_ctype)
487*1f5207b7SJohn Levon 		return 1;
488*1f5207b7SJohn Levon 	return 0;
489*1f5207b7SJohn Levon }
490*1f5207b7SJohn Levon 
491*1f5207b7SJohn Levon int is_string(struct expression *expr)
492*1f5207b7SJohn Levon {
493*1f5207b7SJohn Levon 	expr = strip_expr(expr);
494*1f5207b7SJohn Levon 	if (!expr || expr->type != EXPR_STRING)
495*1f5207b7SJohn Levon 		return 0;
496*1f5207b7SJohn Levon 	if (expr->string)
497*1f5207b7SJohn Levon 		return 1;
498*1f5207b7SJohn Levon 	return 0;
499*1f5207b7SJohn Levon }
500*1f5207b7SJohn Levon 
501*1f5207b7SJohn Levon int is_static(struct expression *expr)
502*1f5207b7SJohn Levon {
503*1f5207b7SJohn Levon 	char *name;
504*1f5207b7SJohn Levon 	struct symbol *sym;
505*1f5207b7SJohn Levon 	int ret = 0;
506*1f5207b7SJohn Levon 
507*1f5207b7SJohn Levon 	name = expr_to_str_sym(expr, &sym);
508*1f5207b7SJohn Levon 	if (!name || !sym)
509*1f5207b7SJohn Levon 		goto free;
510*1f5207b7SJohn Levon 
511*1f5207b7SJohn Levon 	if (sym->ctype.modifiers & MOD_STATIC)
512*1f5207b7SJohn Levon 		ret = 1;
513*1f5207b7SJohn Levon free:
514*1f5207b7SJohn Levon 	free_string(name);
515*1f5207b7SJohn Levon 	return ret;
516*1f5207b7SJohn Levon }
517*1f5207b7SJohn Levon 
518*1f5207b7SJohn Levon int is_local_variable(struct expression *expr)
519*1f5207b7SJohn Levon {
520*1f5207b7SJohn Levon 	struct symbol *sym;
521*1f5207b7SJohn Levon 	char *name;
522*1f5207b7SJohn Levon 
523*1f5207b7SJohn Levon 	name = expr_to_var_sym(expr, &sym);
524*1f5207b7SJohn Levon 	free_string(name);
525*1f5207b7SJohn Levon 	if (!sym || !sym->scope || !sym->scope->token || !cur_func_sym)
526*1f5207b7SJohn Levon 		return 0;
527*1f5207b7SJohn Levon 	if (cmp_pos(sym->scope->token->pos, cur_func_sym->pos) < 0)
528*1f5207b7SJohn Levon 		return 0;
529*1f5207b7SJohn Levon 	if (is_static(expr))
530*1f5207b7SJohn Levon 		return 0;
531*1f5207b7SJohn Levon 	return 1;
532*1f5207b7SJohn Levon }
533*1f5207b7SJohn Levon 
534*1f5207b7SJohn Levon int types_equiv(struct symbol *one, struct symbol *two)
535*1f5207b7SJohn Levon {
536*1f5207b7SJohn Levon 	if (!one && !two)
537*1f5207b7SJohn Levon 		return 1;
538*1f5207b7SJohn Levon 	if (!one || !two)
539*1f5207b7SJohn Levon 		return 0;
540*1f5207b7SJohn Levon 	if (one->type != two->type)
541*1f5207b7SJohn Levon 		return 0;
542*1f5207b7SJohn Levon 	if (one->type == SYM_PTR)
543*1f5207b7SJohn Levon 		return types_equiv(get_real_base_type(one), get_real_base_type(two));
544*1f5207b7SJohn Levon 	if (type_positive_bits(one) != type_positive_bits(two))
545*1f5207b7SJohn Levon 		return 0;
546*1f5207b7SJohn Levon 	return 1;
547*1f5207b7SJohn Levon }
548*1f5207b7SJohn Levon 
549*1f5207b7SJohn Levon int fn_static(void)
550*1f5207b7SJohn Levon {
551*1f5207b7SJohn Levon 	return !!(cur_func_sym->ctype.modifiers & MOD_STATIC);
552*1f5207b7SJohn Levon }
553*1f5207b7SJohn Levon 
554*1f5207b7SJohn Levon const char *global_static(void)
555*1f5207b7SJohn Levon {
556*1f5207b7SJohn Levon 	if (cur_func_sym->ctype.modifiers & MOD_STATIC)
557*1f5207b7SJohn Levon 		return "static";
558*1f5207b7SJohn Levon 	else
559*1f5207b7SJohn Levon 		return "global";
560*1f5207b7SJohn Levon }
561*1f5207b7SJohn Levon 
562*1f5207b7SJohn Levon struct symbol *cur_func_return_type(void)
563*1f5207b7SJohn Levon {
564*1f5207b7SJohn Levon 	struct symbol *sym;
565*1f5207b7SJohn Levon 
566*1f5207b7SJohn Levon 	sym = get_real_base_type(cur_func_sym);
567*1f5207b7SJohn Levon 	if (!sym || sym->type != SYM_FN)
568*1f5207b7SJohn Levon 		return NULL;
569*1f5207b7SJohn Levon 	sym = get_real_base_type(sym);
570*1f5207b7SJohn Levon 	return sym;
571*1f5207b7SJohn Levon }
572*1f5207b7SJohn Levon 
573*1f5207b7SJohn Levon struct symbol *get_arg_type(struct expression *fn, int arg)
574*1f5207b7SJohn Levon {
575*1f5207b7SJohn Levon 	struct symbol *fn_type;
576*1f5207b7SJohn Levon 	struct symbol *tmp;
577*1f5207b7SJohn Levon 	struct symbol *arg_type;
578*1f5207b7SJohn Levon 	int i;
579*1f5207b7SJohn Levon 
580*1f5207b7SJohn Levon 	fn_type = get_type(fn);
581*1f5207b7SJohn Levon 	if (!fn_type)
582*1f5207b7SJohn Levon 		return NULL;
583*1f5207b7SJohn Levon 	if (fn_type->type == SYM_PTR)
584*1f5207b7SJohn Levon 		fn_type = get_real_base_type(fn_type);
585*1f5207b7SJohn Levon 	if (fn_type->type != SYM_FN)
586*1f5207b7SJohn Levon 		return NULL;
587*1f5207b7SJohn Levon 
588*1f5207b7SJohn Levon 	i = 0;
589*1f5207b7SJohn Levon 	FOR_EACH_PTR(fn_type->arguments, tmp) {
590*1f5207b7SJohn Levon 		arg_type = get_real_base_type(tmp);
591*1f5207b7SJohn Levon 		if (i == arg) {
592*1f5207b7SJohn Levon 			return arg_type;
593*1f5207b7SJohn Levon 		}
594*1f5207b7SJohn Levon 		i++;
595*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(tmp);
596*1f5207b7SJohn Levon 
597*1f5207b7SJohn Levon 	return NULL;
598*1f5207b7SJohn Levon }
599*1f5207b7SJohn Levon 
600*1f5207b7SJohn Levon static struct symbol *get_member_from_string(struct symbol_list *symbol_list, const char *name)
601*1f5207b7SJohn Levon {
602*1f5207b7SJohn Levon 	struct symbol *tmp, *sub;
603*1f5207b7SJohn Levon 	int chunk_len;
604*1f5207b7SJohn Levon 
605*1f5207b7SJohn Levon 	if (strncmp(name, ".", 1) == 0)
606*1f5207b7SJohn Levon 		name += 1;
607*1f5207b7SJohn Levon 	if (strncmp(name, "->", 2) == 0)
608*1f5207b7SJohn Levon 		name += 2;
609*1f5207b7SJohn Levon 
610*1f5207b7SJohn Levon 	FOR_EACH_PTR(symbol_list, tmp) {
611*1f5207b7SJohn Levon 		if (!tmp->ident) {
612*1f5207b7SJohn Levon 			sub = get_real_base_type(tmp);
613*1f5207b7SJohn Levon 			sub = get_member_from_string(sub->symbol_list, name);
614*1f5207b7SJohn Levon 			if (sub)
615*1f5207b7SJohn Levon 				return sub;
616*1f5207b7SJohn Levon 			continue;
617*1f5207b7SJohn Levon 		}
618*1f5207b7SJohn Levon 
619*1f5207b7SJohn Levon 		if (strcmp(tmp->ident->name, name) == 0)
620*1f5207b7SJohn Levon 			return tmp;
621*1f5207b7SJohn Levon 
622*1f5207b7SJohn Levon 		chunk_len = strlen(tmp->ident->name);
623*1f5207b7SJohn Levon 		if (strncmp(tmp->ident->name, name, chunk_len) == 0 &&
624*1f5207b7SJohn Levon 		    (name[chunk_len] == '.' || name[chunk_len] == '-')) {
625*1f5207b7SJohn Levon 			sub = get_real_base_type(tmp);
626*1f5207b7SJohn Levon 			return get_member_from_string(sub->symbol_list, name + chunk_len);
627*1f5207b7SJohn Levon 		}
628*1f5207b7SJohn Levon 
629*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(tmp);
630*1f5207b7SJohn Levon 
631*1f5207b7SJohn Levon 	return NULL;
632*1f5207b7SJohn Levon }
633*1f5207b7SJohn Levon 
634*1f5207b7SJohn Levon struct symbol *get_member_type_from_key(struct expression *expr, const char *key)
635*1f5207b7SJohn Levon {
636*1f5207b7SJohn Levon 	struct symbol *sym;
637*1f5207b7SJohn Levon 
638*1f5207b7SJohn Levon 	if (strcmp(key, "$") == 0)
639*1f5207b7SJohn Levon 		return get_type(expr);
640*1f5207b7SJohn Levon 
641*1f5207b7SJohn Levon 	if (strcmp(key, "*$") == 0) {
642*1f5207b7SJohn Levon 		sym = get_type(expr);
643*1f5207b7SJohn Levon 		if (!sym || sym->type != SYM_PTR)
644*1f5207b7SJohn Levon 			return NULL;
645*1f5207b7SJohn Levon 		return get_real_base_type(sym);
646*1f5207b7SJohn Levon 	}
647*1f5207b7SJohn Levon 
648*1f5207b7SJohn Levon 	sym = get_type(expr);
649*1f5207b7SJohn Levon 	if (!sym)
650*1f5207b7SJohn Levon 		return NULL;
651*1f5207b7SJohn Levon 	if (sym->type == SYM_PTR)
652*1f5207b7SJohn Levon 		sym = get_real_base_type(sym);
653*1f5207b7SJohn Levon 
654*1f5207b7SJohn Levon 	key = key + 1;
655*1f5207b7SJohn Levon 	sym = get_member_from_string(sym->symbol_list, key);
656*1f5207b7SJohn Levon 	if (!sym)
657*1f5207b7SJohn Levon 		return NULL;
658*1f5207b7SJohn Levon 	return get_real_base_type(sym);
659*1f5207b7SJohn Levon }
660*1f5207b7SJohn Levon 
661*1f5207b7SJohn Levon struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key)
662*1f5207b7SJohn Levon {
663*1f5207b7SJohn Levon 	struct symbol *type;
664*1f5207b7SJohn Levon 
665*1f5207b7SJohn Levon 	if (!key)
666*1f5207b7SJohn Levon 		return NULL;
667*1f5207b7SJohn Levon 	if (strcmp(key, "$") == 0)
668*1f5207b7SJohn Levon 		return get_arg_type(fn, param);
669*1f5207b7SJohn Levon 	if (strcmp(key, "*$") == 0) {
670*1f5207b7SJohn Levon 		type = get_arg_type(fn, param);
671*1f5207b7SJohn Levon 		if (!type || type->type != SYM_PTR)
672*1f5207b7SJohn Levon 			return NULL;
673*1f5207b7SJohn Levon 		return get_real_base_type(type);
674*1f5207b7SJohn Levon 	}
675*1f5207b7SJohn Levon 	return get_member_type_from_key(arg, key);
676*1f5207b7SJohn Levon }
677*1f5207b7SJohn Levon 
678*1f5207b7SJohn Levon int is_struct(struct expression *expr)
679*1f5207b7SJohn Levon {
680*1f5207b7SJohn Levon 	struct symbol *type;
681*1f5207b7SJohn Levon 
682*1f5207b7SJohn Levon 	type = get_type(expr);
683*1f5207b7SJohn Levon 	if (type && type->type == SYM_STRUCT)
684*1f5207b7SJohn Levon 		return 1;
685*1f5207b7SJohn Levon 	return 0;
686*1f5207b7SJohn Levon }
687*1f5207b7SJohn Levon 
688*1f5207b7SJohn Levon static struct {
689*1f5207b7SJohn Levon 	struct symbol *sym;
690*1f5207b7SJohn Levon 	const char *name;
691*1f5207b7SJohn Levon } base_types[] = {
692*1f5207b7SJohn Levon 	{&bool_ctype, "bool"},
693*1f5207b7SJohn Levon 	{&void_ctype, "void"},
694*1f5207b7SJohn Levon 	{&type_ctype, "type"},
695*1f5207b7SJohn Levon 	{&char_ctype, "char"},
696*1f5207b7SJohn Levon 	{&schar_ctype, "schar"},
697*1f5207b7SJohn Levon 	{&uchar_ctype, "uchar"},
698*1f5207b7SJohn Levon 	{&short_ctype, "short"},
699*1f5207b7SJohn Levon 	{&sshort_ctype, "sshort"},
700*1f5207b7SJohn Levon 	{&ushort_ctype, "ushort"},
701*1f5207b7SJohn Levon 	{&int_ctype, "int"},
702*1f5207b7SJohn Levon 	{&sint_ctype, "sint"},
703*1f5207b7SJohn Levon 	{&uint_ctype, "uint"},
704*1f5207b7SJohn Levon 	{&long_ctype, "long"},
705*1f5207b7SJohn Levon 	{&slong_ctype, "slong"},
706*1f5207b7SJohn Levon 	{&ulong_ctype, "ulong"},
707*1f5207b7SJohn Levon 	{&llong_ctype, "llong"},
708*1f5207b7SJohn Levon 	{&sllong_ctype, "sllong"},
709*1f5207b7SJohn Levon 	{&ullong_ctype, "ullong"},
710*1f5207b7SJohn Levon 	{&lllong_ctype, "lllong"},
711*1f5207b7SJohn Levon 	{&slllong_ctype, "slllong"},
712*1f5207b7SJohn Levon 	{&ulllong_ctype, "ulllong"},
713*1f5207b7SJohn Levon 	{&float_ctype, "float"},
714*1f5207b7SJohn Levon 	{&double_ctype, "double"},
715*1f5207b7SJohn Levon 	{&ldouble_ctype, "ldouble"},
716*1f5207b7SJohn Levon 	{&string_ctype, "string"},
717*1f5207b7SJohn Levon 	{&ptr_ctype, "ptr"},
718*1f5207b7SJohn Levon 	{&lazy_ptr_ctype, "lazy_ptr"},
719*1f5207b7SJohn Levon 	{&incomplete_ctype, "incomplete"},
720*1f5207b7SJohn Levon 	{&label_ctype, "label"},
721*1f5207b7SJohn Levon 	{&bad_ctype, "bad"},
722*1f5207b7SJohn Levon 	{&null_ctype, "null"},
723*1f5207b7SJohn Levon };
724*1f5207b7SJohn Levon 
725*1f5207b7SJohn Levon static const char *base_type_str(struct symbol *sym)
726*1f5207b7SJohn Levon {
727*1f5207b7SJohn Levon 	int i;
728*1f5207b7SJohn Levon 
729*1f5207b7SJohn Levon 	for (i = 0; i < ARRAY_SIZE(base_types); i++) {
730*1f5207b7SJohn Levon 		if (sym == base_types[i].sym)
731*1f5207b7SJohn Levon 			return base_types[i].name;
732*1f5207b7SJohn Levon 	}
733*1f5207b7SJohn Levon 	return "<unknown>";
734*1f5207b7SJohn Levon }
735*1f5207b7SJohn Levon 
736*1f5207b7SJohn Levon static int type_str_helper(char *buf, int size, struct symbol *type)
737*1f5207b7SJohn Levon {
738*1f5207b7SJohn Levon 	int n;
739*1f5207b7SJohn Levon 
740*1f5207b7SJohn Levon 	if (!type)
741*1f5207b7SJohn Levon 		return snprintf(buf, size, "<unknown>");
742*1f5207b7SJohn Levon 
743*1f5207b7SJohn Levon 	if (type->type == SYM_BASETYPE) {
744*1f5207b7SJohn Levon 		return snprintf(buf, size, base_type_str(type));
745*1f5207b7SJohn Levon 	} else if (type->type == SYM_PTR) {
746*1f5207b7SJohn Levon 		type = get_real_base_type(type);
747*1f5207b7SJohn Levon 		n = type_str_helper(buf, size, type);
748*1f5207b7SJohn Levon 		if (n > size)
749*1f5207b7SJohn Levon 			return n;
750*1f5207b7SJohn Levon 		return n + snprintf(buf + n, size - n, "*");
751*1f5207b7SJohn Levon 	} else if (type->type == SYM_ARRAY) {
752*1f5207b7SJohn Levon 		type = get_real_base_type(type);
753*1f5207b7SJohn Levon 		n = type_str_helper(buf, size, type);
754*1f5207b7SJohn Levon 		if (n > size)
755*1f5207b7SJohn Levon 			return n;
756*1f5207b7SJohn Levon 		return n + snprintf(buf + n, size - n, "[]");
757*1f5207b7SJohn Levon 	} else if (type->type == SYM_STRUCT) {
758*1f5207b7SJohn Levon 		return snprintf(buf, size, "struct %s", type->ident ? type->ident->name : "");
759*1f5207b7SJohn Levon 	} else if (type->type == SYM_UNION) {
760*1f5207b7SJohn Levon 		if (type->ident)
761*1f5207b7SJohn Levon 			return snprintf(buf, size, "union %s", type->ident->name);
762*1f5207b7SJohn Levon 		else
763*1f5207b7SJohn Levon 			return snprintf(buf, size, "anonymous union");
764*1f5207b7SJohn Levon 	} else if (type->type == SYM_FN) {
765*1f5207b7SJohn Levon 		struct symbol *arg, *return_type, *arg_type;
766*1f5207b7SJohn Levon 		int i;
767*1f5207b7SJohn Levon 
768*1f5207b7SJohn Levon 		return_type = get_real_base_type(type);
769*1f5207b7SJohn Levon 		n = type_str_helper(buf, size, return_type);
770*1f5207b7SJohn Levon 		if (n > size)
771*1f5207b7SJohn Levon 			return n;
772*1f5207b7SJohn Levon 		n += snprintf(buf + n, size - n, "(*)(");
773*1f5207b7SJohn Levon 		if (n > size)
774*1f5207b7SJohn Levon 			return n;
775*1f5207b7SJohn Levon 
776*1f5207b7SJohn Levon 		i = 0;
777*1f5207b7SJohn Levon 		FOR_EACH_PTR(type->arguments, arg) {
778*1f5207b7SJohn Levon 			if (i++)
779*1f5207b7SJohn Levon 				n += snprintf(buf + n, size - n, ", ");
780*1f5207b7SJohn Levon 			if (n > size)
781*1f5207b7SJohn Levon 				return n;
782*1f5207b7SJohn Levon 			arg_type = get_real_base_type(arg);
783*1f5207b7SJohn Levon 			n += type_str_helper(buf + n, size - n, arg_type);
784*1f5207b7SJohn Levon 			if (n > size)
785*1f5207b7SJohn Levon 				return n;
786*1f5207b7SJohn Levon 		} END_FOR_EACH_PTR(arg);
787*1f5207b7SJohn Levon 
788*1f5207b7SJohn Levon 		return n + snprintf(buf + n, size - n, ")");
789*1f5207b7SJohn Levon 	} else if (type->type == SYM_NODE) {
790*1f5207b7SJohn Levon 		n = snprintf(buf, size, "node {");
791*1f5207b7SJohn Levon 		if (n > size)
792*1f5207b7SJohn Levon 			return n;
793*1f5207b7SJohn Levon 		type = get_real_base_type(type);
794*1f5207b7SJohn Levon 		n += type_str_helper(buf + n, size - n, type);
795*1f5207b7SJohn Levon 		if (n > size)
796*1f5207b7SJohn Levon 			return n;
797*1f5207b7SJohn Levon 		return n + snprintf(buf + n, size - n, "}");
798*1f5207b7SJohn Levon 	} else {
799*1f5207b7SJohn Levon 		return snprintf(buf, size, "<type %d>", type->type);
800*1f5207b7SJohn Levon 	}
801*1f5207b7SJohn Levon }
802*1f5207b7SJohn Levon 
803*1f5207b7SJohn Levon char *type_to_str(struct symbol *type)
804*1f5207b7SJohn Levon {
805*1f5207b7SJohn Levon 	static char buf[256];
806*1f5207b7SJohn Levon 
807*1f5207b7SJohn Levon 	buf[0] = '\0';
808*1f5207b7SJohn Levon 	type_str_helper(buf, sizeof(buf), type);
809*1f5207b7SJohn Levon 	return buf;
810*1f5207b7SJohn Levon }
811