Home | History | Annotate | Line # | Download | only in lint1
debug.c revision 1.9
      1  1.9  rillig /* $NetBSD: debug.c,v 1.9 2022/03/01 00:17:12 rillig Exp $ */
      2  1.1  rillig 
      3  1.1  rillig /*-
      4  1.1  rillig  * Copyright (c) 2021 The NetBSD Foundation, Inc.
      5  1.1  rillig  * All rights reserved.
      6  1.1  rillig  *
      7  1.1  rillig  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  rillig  * by Roland Illig <rillig (at) NetBSD.org>.
      9  1.1  rillig  *
     10  1.1  rillig  * Redistribution and use in source and binary forms, with or without
     11  1.1  rillig  * modification, are permitted provided that the following conditions
     12  1.1  rillig  * are met:
     13  1.1  rillig  * 1. Redistributions of source code must retain the above copyright
     14  1.1  rillig  *    notice, this list of conditions and the following disclaimer.
     15  1.1  rillig  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  rillig  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  rillig  *    documentation and/or other materials provided with the distribution.
     18  1.1  rillig  *
     19  1.1  rillig  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1  rillig  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1  rillig  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1  rillig  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1  rillig  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1  rillig  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1  rillig  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1  rillig  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1  rillig  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1  rillig  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1  rillig  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1  rillig  */
     31  1.1  rillig 
     32  1.1  rillig #if HAVE_NBTOOL_CONFIG_H
     33  1.1  rillig #include "nbtool_config.h"
     34  1.1  rillig #endif
     35  1.1  rillig 
     36  1.1  rillig #include <sys/cdefs.h>
     37  1.1  rillig #if defined(__RCSID) && !defined(lint)
     38  1.9  rillig __RCSID("$NetBSD: debug.c,v 1.9 2022/03/01 00:17:12 rillig Exp $");
     39  1.1  rillig #endif
     40  1.1  rillig 
     41  1.2  rillig #include <stdlib.h>
     42  1.2  rillig 
     43  1.1  rillig #include "lint1.h"
     44  1.9  rillig #include "cgram.h"
     45  1.1  rillig 
     46  1.1  rillig 
     47  1.1  rillig #ifdef DEBUG
     48  1.1  rillig 
     49  1.1  rillig static int debug_indentation = 0;
     50  1.1  rillig 
     51  1.1  rillig 
     52  1.1  rillig void __printflike(1, 2)
     53  1.1  rillig debug_printf(const char *fmt, ...)
     54  1.1  rillig {
     55  1.1  rillig 	va_list va;
     56  1.1  rillig 
     57  1.1  rillig 	va_start(va, fmt);
     58  1.1  rillig 	vfprintf(stdout, fmt, va);
     59  1.1  rillig 	va_end(va);
     60  1.1  rillig }
     61  1.1  rillig 
     62  1.1  rillig void
     63  1.7  rillig debug_print_indent(void)
     64  1.1  rillig {
     65  1.1  rillig 
     66  1.1  rillig 	debug_printf("%*s", 2 * debug_indentation, "");
     67  1.1  rillig }
     68  1.1  rillig 
     69  1.1  rillig void
     70  1.1  rillig debug_indent_inc(void)
     71  1.1  rillig {
     72  1.1  rillig 
     73  1.1  rillig 	debug_indentation++;
     74  1.1  rillig }
     75  1.1  rillig 
     76  1.1  rillig void
     77  1.1  rillig debug_indent_dec(void)
     78  1.1  rillig {
     79  1.1  rillig 
     80  1.1  rillig 	debug_indentation--;
     81  1.1  rillig }
     82  1.1  rillig 
     83  1.1  rillig void
     84  1.1  rillig (debug_enter)(const char *func)
     85  1.1  rillig {
     86  1.1  rillig 
     87  1.1  rillig 	printf("%*s+ %s\n", 2 * debug_indentation++, "", func);
     88  1.1  rillig }
     89  1.1  rillig 
     90  1.1  rillig void __printflike(1, 2)
     91  1.1  rillig debug_step(const char *fmt, ...)
     92  1.1  rillig {
     93  1.1  rillig 	va_list va;
     94  1.1  rillig 
     95  1.7  rillig 	debug_print_indent();
     96  1.1  rillig 	va_start(va, fmt);
     97  1.1  rillig 	vfprintf(stdout, fmt, va);
     98  1.1  rillig 	va_end(va);
     99  1.1  rillig 	printf("\n");
    100  1.1  rillig }
    101  1.1  rillig 
    102  1.1  rillig void
    103  1.1  rillig (debug_leave)(const char *func)
    104  1.1  rillig {
    105  1.1  rillig 
    106  1.1  rillig 	printf("%*s- %s\n", 2 * --debug_indentation, "", func);
    107  1.1  rillig }
    108  1.1  rillig 
    109  1.1  rillig void
    110  1.2  rillig debug_node(const tnode_t *tn)
    111  1.1  rillig {
    112  1.1  rillig 	op_t op;
    113  1.1  rillig 
    114  1.1  rillig 	if (tn == NULL) {
    115  1.2  rillig 		debug_step("null");
    116  1.1  rillig 		return;
    117  1.1  rillig 	}
    118  1.1  rillig 
    119  1.1  rillig 	op = tn->tn_op;
    120  1.7  rillig 	debug_print_indent();
    121  1.4  rillig 	debug_printf("'%s' with type '%s'%s%s%s",
    122  1.1  rillig 	    op == CVT && !tn->tn_cast ? "convert" : modtab[op].m_name,
    123  1.1  rillig 	    type_name(tn->tn_type), tn->tn_lvalue ? ", lvalue" : "",
    124  1.4  rillig 	    tn->tn_parenthesized ? ", parenthesized" : "",
    125  1.5  rillig 	    tn->tn_sys ? ", sys" : "");
    126  1.1  rillig 
    127  1.1  rillig 	if (op == NAME)
    128  1.2  rillig 		debug_printf(" %s %s\n", tn->tn_sym->s_name,
    129  1.2  rillig 		    storage_class_name(tn->tn_sym->s_scl));
    130  1.1  rillig 	else if (op == CON && is_floating(tn->tn_type->t_tspec))
    131  1.2  rillig 		debug_printf(", value %Lg", tn->tn_val->v_ldbl);
    132  1.1  rillig 	else if (op == CON && is_uinteger(tn->tn_type->t_tspec))
    133  1.9  rillig 		debug_printf(", value %llu\n",
    134  1.9  rillig 		    (unsigned long long)tn->tn_val->v_quad);
    135  1.1  rillig 	else if (op == CON && is_integer(tn->tn_type->t_tspec))
    136  1.9  rillig 		debug_printf(", value %lld\n",
    137  1.9  rillig 		    (long long)tn->tn_val->v_quad);
    138  1.6  rillig 	else if (op == CON && tn->tn_type->t_tspec == BOOL)
    139  1.6  rillig 		debug_printf(", value %s\n",
    140  1.6  rillig 		    tn->tn_val->v_quad != 0 ? "true" : "false");
    141  1.1  rillig 	else if (op == CON)
    142  1.2  rillig 		debug_printf(", unknown value\n");
    143  1.8  rillig 	else if (op == STRING && tn->tn_string->st_char)
    144  1.2  rillig 		debug_printf(", length %zu, \"%s\"\n",
    145  1.8  rillig 		    tn->tn_string->st_len,
    146  1.8  rillig 		    (const char *)tn->tn_string->st_mem);
    147  1.8  rillig 	else if (op == STRING) {
    148  1.8  rillig 		size_t n = MB_CUR_MAX * (tn->tn_string->st_len + 1);
    149  1.8  rillig 		char *s = xmalloc(n);
    150  1.8  rillig 		(void)wcstombs(s, tn->tn_string->st_mem, n);
    151  1.2  rillig 		debug_printf(", length %zu, L\"%s\"",
    152  1.2  rillig 		    tn->tn_string->st_len, s);
    153  1.2  rillig 		free(s);
    154  1.2  rillig 
    155  1.2  rillig 	} else {
    156  1.2  rillig 		debug_printf("\n");
    157  1.1  rillig 
    158  1.2  rillig 		debug_indent_inc();
    159  1.2  rillig 		debug_node(tn->tn_left);
    160  1.3  rillig 		if (is_binary(tn) || tn->tn_right != NULL)
    161  1.2  rillig 			debug_node(tn->tn_right);
    162  1.2  rillig 		debug_indent_dec();
    163  1.1  rillig 	}
    164  1.1  rillig }
    165  1.1  rillig 
    166  1.9  rillig static const char *
    167  1.9  rillig def_name(def_t def)
    168  1.9  rillig {
    169  1.9  rillig 	static const char *const name[] = {
    170  1.9  rillig 		"not-declared",
    171  1.9  rillig 		"declared",
    172  1.9  rillig 		"tentative-defined",
    173  1.9  rillig 		"defined",
    174  1.9  rillig 	};
    175  1.9  rillig 
    176  1.9  rillig 	return name[def];
    177  1.9  rillig }
    178  1.9  rillig 
    179  1.9  rillig const char *
    180  1.9  rillig scl_name(scl_t scl)
    181  1.9  rillig {
    182  1.9  rillig 	static const char *const name[] = {
    183  1.9  rillig 		"none",
    184  1.9  rillig 		"extern",
    185  1.9  rillig 		"static",
    186  1.9  rillig 		"auto",
    187  1.9  rillig 		"register",
    188  1.9  rillig 		"typedef",
    189  1.9  rillig 		"struct",
    190  1.9  rillig 		"union",
    191  1.9  rillig 		"enum",
    192  1.9  rillig 		"member-of-struct",
    193  1.9  rillig 		"member-of-union",
    194  1.9  rillig 		"compile-time-constant",
    195  1.9  rillig 		"abstract",
    196  1.9  rillig 		"old-style-function-argument",
    197  1.9  rillig 		"prototype-argument",
    198  1.9  rillig 		"inline",
    199  1.9  rillig 	};
    200  1.9  rillig 
    201  1.9  rillig 	return name[scl];
    202  1.9  rillig }
    203  1.9  rillig 
    204  1.9  rillig const char *
    205  1.9  rillig symt_name(symt_t kind)
    206  1.9  rillig {
    207  1.9  rillig 	static const char *const name[] = {
    208  1.9  rillig 		"var-func-type",
    209  1.9  rillig 		"member",
    210  1.9  rillig 		"tag",
    211  1.9  rillig 		"label",
    212  1.9  rillig 	};
    213  1.9  rillig 
    214  1.9  rillig 	return name[kind];
    215  1.9  rillig }
    216  1.9  rillig 
    217  1.9  rillig const char *
    218  1.9  rillig tqual_name(tqual_t qual)
    219  1.9  rillig {
    220  1.9  rillig 	static const char *const name[] = {
    221  1.9  rillig 		"const",
    222  1.9  rillig 		"volatile",
    223  1.9  rillig 		"restrict",
    224  1.9  rillig 		"_Thread_local",
    225  1.9  rillig 	};
    226  1.9  rillig 
    227  1.9  rillig 	return name[qual];
    228  1.9  rillig }
    229  1.9  rillig 
    230  1.9  rillig static void
    231  1.9  rillig debug_word(bool flag, const char *name)
    232  1.9  rillig {
    233  1.9  rillig 
    234  1.9  rillig 	if (flag)
    235  1.9  rillig 		debug_printf(" %s", name);
    236  1.9  rillig }
    237  1.9  rillig 
    238  1.9  rillig void
    239  1.9  rillig debug_sym(const sym_t *sym)
    240  1.9  rillig {
    241  1.9  rillig 
    242  1.9  rillig 	debug_print_indent();
    243  1.9  rillig 	debug_printf("%s", sym->s_name);
    244  1.9  rillig 	if (sym->s_type != NULL)
    245  1.9  rillig 		debug_printf(" type='%s'", type_name(sym->s_type));
    246  1.9  rillig 	if (sym->s_rename != NULL)
    247  1.9  rillig 		debug_printf(" rename=%s", sym->s_rename);
    248  1.9  rillig 	debug_printf(" %s", symt_name(sym->s_kind));
    249  1.9  rillig 	debug_word(sym->s_keyword != NULL, "keyword");
    250  1.9  rillig 	debug_word(sym->s_bitfield, "bit-field");
    251  1.9  rillig 	debug_word(sym->s_set, "set");
    252  1.9  rillig 	debug_word(sym->s_used, "used");
    253  1.9  rillig 	debug_word(sym->s_arg, "argument");
    254  1.9  rillig 	debug_word(sym->s_register, "register");
    255  1.9  rillig 	debug_word(sym->s_defarg, "old-style-undefined");
    256  1.9  rillig 	debug_word(sym->s_return_type_implicit_int, "return-int");
    257  1.9  rillig 	debug_word(sym->s_osdef, "old-style");
    258  1.9  rillig 	debug_word(sym->s_inline, "inline");
    259  1.9  rillig 	debug_word(sym->s_ext_sym != NULL, "has-external");
    260  1.9  rillig 	debug_word(sym->s_scl != NOSCL, scl_name(sym->s_scl));
    261  1.9  rillig 	debug_word(sym->s_keyword == NULL, def_name(sym->s_def));
    262  1.9  rillig 
    263  1.9  rillig 	if (sym->s_def_pos.p_file != NULL)
    264  1.9  rillig 		debug_printf(" defined-at=%s:%d",
    265  1.9  rillig 		    sym->s_def_pos.p_file, sym->s_def_pos.p_line);
    266  1.9  rillig 	if (sym->s_set_pos.p_file != NULL)
    267  1.9  rillig 		debug_printf(" set-at=%s:%d",
    268  1.9  rillig 		    sym->s_set_pos.p_file, sym->s_set_pos.p_line);
    269  1.9  rillig 	if (sym->s_use_pos.p_file != NULL)
    270  1.9  rillig 		debug_printf(" used-at=%s:%d",
    271  1.9  rillig 		    sym->s_use_pos.p_file, sym->s_use_pos.p_line);
    272  1.9  rillig 
    273  1.9  rillig 	if (sym->s_type != NULL &&
    274  1.9  rillig 	    (sym->s_type->t_is_enum || sym->s_type->t_tspec == BOOL))
    275  1.9  rillig 		debug_printf(" value=%d", (int)sym->s_value.v_quad);
    276  1.9  rillig 
    277  1.9  rillig 	if ((sym->s_scl == MOS || sym->s_scl == MOU) &&
    278  1.9  rillig 	    sym->s_sou_type != NULL) {
    279  1.9  rillig 		const char *tag = sym->s_sou_type->sou_tag->s_name;
    280  1.9  rillig 		const sym_t *def = sym->s_sou_type->sou_first_typedef;
    281  1.9  rillig 		if (tag == unnamed && def != NULL)
    282  1.9  rillig 			debug_printf(" sou='typedef %s'", def->s_name);
    283  1.9  rillig 		else
    284  1.9  rillig 			debug_printf(" sou=%s", tag);
    285  1.9  rillig 	}
    286  1.9  rillig 
    287  1.9  rillig 	if (sym->s_keyword != NULL) {
    288  1.9  rillig 		int t = (int)sym->s_value.v_quad;
    289  1.9  rillig 		if (t == T_TYPE || t == T_STRUCT_OR_UNION)
    290  1.9  rillig 			debug_printf(" %s", tspec_name(sym->s_tspec));
    291  1.9  rillig 		else if (t == T_QUAL)
    292  1.9  rillig 			debug_printf(" %s", tqual_name(sym->s_tqual));
    293  1.9  rillig 	}
    294  1.9  rillig 
    295  1.9  rillig 	debug_word(sym->s_osdef && sym->s_args != NULL, "old-style-args");
    296  1.9  rillig 
    297  1.9  rillig 	debug_printf("\n");
    298  1.9  rillig }
    299  1.9  rillig 
    300  1.1  rillig #endif
    301