Home | History | Annotate | Line # | Download | only in indent
debug.c revision 1.6
      1  1.6  rillig /*	$NetBSD: debug.c,v 1.6 2023/05/15 07:57:22 rillig Exp $	*/
      2  1.1  rillig 
      3  1.1  rillig /*-
      4  1.1  rillig  * Copyright (c) 2023 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 #include <sys/cdefs.h>
     33  1.6  rillig __RCSID("$NetBSD: debug.c,v 1.6 2023/05/15 07:57:22 rillig Exp $");
     34  1.6  rillig 
     35  1.6  rillig #include <stdarg.h>
     36  1.1  rillig 
     37  1.1  rillig #include "indent.h"
     38  1.1  rillig 
     39  1.1  rillig #ifdef debug
     40  1.1  rillig const char *const lsym_name[] = {
     41  1.1  rillig     "eof",
     42  1.1  rillig     "preprocessing",
     43  1.1  rillig     "newline",
     44  1.1  rillig     "form_feed",
     45  1.1  rillig     "comment",
     46  1.1  rillig     "lparen_or_lbracket",
     47  1.1  rillig     "rparen_or_rbracket",
     48  1.1  rillig     "lbrace",
     49  1.1  rillig     "rbrace",
     50  1.1  rillig     "period",
     51  1.1  rillig     "unary_op",
     52  1.1  rillig     "binary_op",
     53  1.1  rillig     "postfix_op",
     54  1.1  rillig     "question",
     55  1.1  rillig     "colon",
     56  1.1  rillig     "comma",
     57  1.1  rillig     "semicolon",
     58  1.1  rillig     "typedef",
     59  1.1  rillig     "storage_class",
     60  1.1  rillig     "type_outside_parentheses",
     61  1.1  rillig     "type_in_parentheses",
     62  1.1  rillig     "tag",
     63  1.1  rillig     "case_label",
     64  1.1  rillig     "sizeof",
     65  1.1  rillig     "offsetof",
     66  1.1  rillig     "word",
     67  1.1  rillig     "funcname",
     68  1.1  rillig     "do",
     69  1.1  rillig     "else",
     70  1.1  rillig     "for",
     71  1.1  rillig     "if",
     72  1.1  rillig     "switch",
     73  1.1  rillig     "while",
     74  1.1  rillig     "return",
     75  1.1  rillig };
     76  1.1  rillig 
     77  1.1  rillig const char *const psym_name[] = {
     78  1.1  rillig     "0",
     79  1.1  rillig     "lbrace",
     80  1.1  rillig     "rbrace",
     81  1.1  rillig     "decl",
     82  1.1  rillig     "stmt",
     83  1.1  rillig     "stmt_list",
     84  1.1  rillig     "for_exprs",
     85  1.1  rillig     "if_expr",
     86  1.1  rillig     "if_expr_stmt",
     87  1.1  rillig     "if_expr_stmt_else",
     88  1.1  rillig     "else",
     89  1.1  rillig     "switch_expr",
     90  1.1  rillig     "do",
     91  1.1  rillig     "do_stmt",
     92  1.1  rillig     "while_expr",
     93  1.1  rillig };
     94  1.1  rillig 
     95  1.3  rillig static const char *declaration_name[] = {
     96  1.3  rillig     "no",
     97  1.3  rillig     "begin",
     98  1.3  rillig     "end",
     99  1.3  rillig };
    100  1.3  rillig 
    101  1.2  rillig static const char *in_enum_name[] = {
    102  1.2  rillig     "no",
    103  1.2  rillig     "enum",
    104  1.2  rillig     "type",
    105  1.2  rillig     "brace",
    106  1.2  rillig };
    107  1.2  rillig 
    108  1.1  rillig static bool debug_full_parser_state = true;
    109  1.1  rillig 
    110  1.6  rillig void
    111  1.6  rillig debug_printf(const char *fmt, ...)
    112  1.6  rillig {
    113  1.6  rillig     FILE *f = output == stdout ? stderr : stdout;
    114  1.6  rillig     va_list ap;
    115  1.6  rillig 
    116  1.6  rillig     va_start(ap, fmt);
    117  1.6  rillig     vfprintf(f, fmt, ap);
    118  1.6  rillig     va_end(ap);
    119  1.6  rillig }
    120  1.6  rillig 
    121  1.6  rillig void
    122  1.6  rillig debug_println(const char *fmt, ...)
    123  1.6  rillig {
    124  1.6  rillig     FILE *f = output == stdout ? stderr : stdout;
    125  1.6  rillig     va_list ap;
    126  1.6  rillig 
    127  1.6  rillig     va_start(ap, fmt);
    128  1.6  rillig     vfprintf(f, fmt, ap);
    129  1.6  rillig     va_end(ap);
    130  1.6  rillig     fprintf(f, "\n");
    131  1.6  rillig }
    132  1.6  rillig 
    133  1.6  rillig void
    134  1.6  rillig debug_vis_range(const char *prefix, const char *s, size_t len,
    135  1.6  rillig     const char *suffix)
    136  1.6  rillig {
    137  1.6  rillig     debug_printf("%s", prefix);
    138  1.6  rillig     for (size_t i = 0; i < len; i++) {
    139  1.6  rillig 	const char *p = s + i;
    140  1.6  rillig 	if (*p == '\\' || *p == '"')
    141  1.6  rillig 	    debug_printf("\\%c", *p);
    142  1.6  rillig 	else if (isprint((unsigned char)*p))
    143  1.6  rillig 	    debug_printf("%c", *p);
    144  1.6  rillig 	else if (*p == '\n')
    145  1.6  rillig 	    debug_printf("\\n");
    146  1.6  rillig 	else if (*p == '\t')
    147  1.6  rillig 	    debug_printf("\\t");
    148  1.6  rillig 	else
    149  1.6  rillig 	    debug_printf("\\x%02x", (unsigned char)*p);
    150  1.6  rillig     }
    151  1.6  rillig     debug_printf("%s", suffix);
    152  1.6  rillig }
    153  1.6  rillig 
    154  1.1  rillig static void
    155  1.1  rillig debug_print_buf(const char *name, const struct buffer *buf)
    156  1.1  rillig {
    157  1.5  rillig     if (buf->len > 0) {
    158  1.1  rillig 	debug_printf("%s ", name);
    159  1.5  rillig 	debug_vis_range("\"", buf->st, buf->len, "\"\n");
    160  1.1  rillig     }
    161  1.1  rillig }
    162  1.1  rillig 
    163  1.1  rillig void
    164  1.1  rillig debug_buffers(void)
    165  1.1  rillig {
    166  1.5  rillig     if (lab.len > 0) {
    167  1.1  rillig 	debug_printf(" label ");
    168  1.5  rillig 	debug_vis_range("\"", lab.st, lab.len, "\"");
    169  1.1  rillig     }
    170  1.5  rillig     if (code.len > 0) {
    171  1.1  rillig 	debug_printf(" code ");
    172  1.5  rillig 	debug_vis_range("\"", code.st, code.len, "\"");
    173  1.1  rillig     }
    174  1.5  rillig     if (com.len > 0) {
    175  1.1  rillig 	debug_printf(" comment ");
    176  1.5  rillig 	debug_vis_range("\"", com.st, com.len, "\"");
    177  1.1  rillig     }
    178  1.1  rillig }
    179  1.1  rillig 
    180  1.1  rillig #define debug_ps_bool(name) \
    181  1.1  rillig         if (ps.name != prev_ps.name) \
    182  1.1  rillig 	    debug_println("[%c] -> [%c] ps." #name, \
    183  1.1  rillig 		prev_ps.name ? 'x' : ' ', ps.name ? 'x' : ' '); \
    184  1.1  rillig 	else if (debug_full_parser_state) \
    185  1.1  rillig 	    debug_println("       [%c] ps." #name, ps.name ? 'x' : ' ')
    186  1.1  rillig #define debug_ps_int(name) \
    187  1.1  rillig 	if (ps.name != prev_ps.name) \
    188  1.1  rillig 	    debug_println("%3d -> %3d ps." #name, prev_ps.name, ps.name); \
    189  1.1  rillig 	else if (debug_full_parser_state) \
    190  1.1  rillig 	    debug_println("       %3d ps." #name, ps.name)
    191  1.1  rillig #define debug_ps_enum(name, names) \
    192  1.1  rillig 	if (ps.name != prev_ps.name) \
    193  1.1  rillig 	    debug_println("%3s -> %3s ps." #name, \
    194  1.1  rillig 		(names)[prev_ps.name], (names)[ps.name]); \
    195  1.1  rillig 	else if (debug_full_parser_state) \
    196  1.1  rillig 	    debug_println("%10s ps." #name, (names)[ps.name])
    197  1.1  rillig 
    198  1.1  rillig static bool
    199  1.1  rillig ps_paren_has_changed(const struct parser_state *prev_ps)
    200  1.1  rillig {
    201  1.1  rillig     const paren_level_props *prev = prev_ps->paren, *curr = ps.paren;
    202  1.1  rillig 
    203  1.1  rillig     if (prev_ps->nparen != ps.nparen)
    204  1.1  rillig 	return true;
    205  1.1  rillig 
    206  1.1  rillig     for (int i = 0; i < ps.nparen; i++) {
    207  1.1  rillig 	if (curr[i].indent != prev[i].indent ||
    208  1.1  rillig 	    curr[i].maybe_cast != prev[i].maybe_cast ||
    209  1.1  rillig 	    curr[i].no_cast != prev[i].no_cast)
    210  1.1  rillig 	    return true;
    211  1.1  rillig     }
    212  1.1  rillig     return false;
    213  1.1  rillig }
    214  1.1  rillig 
    215  1.1  rillig static void
    216  1.1  rillig debug_ps_paren(const struct parser_state *prev_ps)
    217  1.1  rillig {
    218  1.1  rillig     if (!debug_full_parser_state && !ps_paren_has_changed(prev_ps))
    219  1.1  rillig 	return;
    220  1.1  rillig 
    221  1.1  rillig     debug_printf("           ps.paren:");
    222  1.1  rillig     for (int i = 0; i < ps.nparen; i++) {
    223  1.1  rillig 	const paren_level_props *props = ps.paren + i;
    224  1.1  rillig 	const char *cast = props->no_cast ? "(no cast)"
    225  1.1  rillig 	    : props->maybe_cast ? "(cast)"
    226  1.1  rillig 	    : "";
    227  1.1  rillig 	debug_printf(" %s%d", cast, props->indent);
    228  1.1  rillig     }
    229  1.1  rillig     if (ps.nparen == 0)
    230  1.1  rillig 	debug_printf(" none");
    231  1.1  rillig     debug_println("");
    232  1.1  rillig }
    233  1.1  rillig 
    234  1.1  rillig void
    235  1.1  rillig debug_parser_state(lexer_symbol lsym)
    236  1.1  rillig {
    237  1.1  rillig     static struct parser_state prev_ps;
    238  1.1  rillig 
    239  1.1  rillig     debug_println("");
    240  1.1  rillig     debug_printf("line %d: %s", line_no, lsym_name[lsym]);
    241  1.5  rillig     debug_vis_range(" \"", token.st, token.len, "\"\n");
    242  1.1  rillig 
    243  1.1  rillig     debug_print_buf("label", &lab);
    244  1.1  rillig     debug_print_buf("code", &code);
    245  1.1  rillig     debug_print_buf("comment", &com);
    246  1.1  rillig 
    247  1.1  rillig     debug_println("           ps.prev_token = %s", lsym_name[ps.prev_token]);
    248  1.1  rillig     debug_ps_bool(curr_col_1);
    249  1.1  rillig     debug_ps_bool(next_col_1);
    250  1.1  rillig     debug_ps_bool(next_unary);
    251  1.1  rillig     debug_ps_bool(is_function_definition);
    252  1.1  rillig     debug_ps_bool(want_blank);
    253  1.1  rillig     debug_ps_bool(force_nl);
    254  1.1  rillig     debug_ps_int(line_start_nparen);
    255  1.1  rillig     debug_ps_int(nparen);
    256  1.1  rillig     debug_ps_paren(&prev_ps);
    257  1.1  rillig 
    258  1.1  rillig     debug_ps_int(comment_delta);
    259  1.1  rillig     debug_ps_int(n_comment_delta);
    260  1.1  rillig     debug_ps_int(com_ind);
    261  1.1  rillig 
    262  1.1  rillig     debug_ps_bool(block_init);
    263  1.1  rillig     debug_ps_int(block_init_level);
    264  1.1  rillig     debug_ps_bool(init_or_struct);
    265  1.1  rillig 
    266  1.1  rillig     debug_ps_int(ind_level);
    267  1.1  rillig     debug_ps_int(ind_level_follow);
    268  1.1  rillig 
    269  1.1  rillig     debug_ps_int(decl_level);
    270  1.1  rillig     debug_ps_bool(decl_on_line);
    271  1.1  rillig     debug_ps_bool(in_decl);
    272  1.3  rillig     debug_ps_enum(declaration, declaration_name);
    273  1.4  rillig     debug_ps_bool(blank_line_after_decl);
    274  1.1  rillig     debug_ps_bool(in_func_def_params);
    275  1.2  rillig     debug_ps_enum(in_enum, in_enum_name);
    276  1.1  rillig     debug_ps_bool(decl_indent_done);
    277  1.1  rillig     debug_ps_int(decl_ind);
    278  1.1  rillig     // No debug output for di_stack.
    279  1.1  rillig     debug_ps_bool(tabs_to_var);
    280  1.1  rillig 
    281  1.1  rillig     debug_ps_bool(in_stmt_or_decl);
    282  1.1  rillig     debug_ps_bool(in_stmt_cont);
    283  1.1  rillig     debug_ps_bool(is_case_label);
    284  1.1  rillig     debug_ps_bool(seen_case);
    285  1.1  rillig 
    286  1.1  rillig     // The debug output for the parser symbols is done in 'parse' instead.
    287  1.1  rillig 
    288  1.1  rillig     debug_ps_enum(spaced_expr_psym, psym_name);
    289  1.1  rillig     debug_ps_int(quest_level);
    290  1.1  rillig 
    291  1.1  rillig     prev_ps = ps;
    292  1.1  rillig }
    293  1.1  rillig 
    294  1.1  rillig void
    295  1.1  rillig debug_parse_stack(const char *situation)
    296  1.1  rillig {
    297  1.1  rillig     printf("parse stack %s:", situation);
    298  1.1  rillig     for (int i = 1; i <= ps.tos; ++i)
    299  1.1  rillig 	printf(" %s %d", psym_name[ps.s_sym[i]], ps.s_ind_level[i]);
    300  1.1  rillig     if (ps.tos == 0)
    301  1.1  rillig 	printf(" empty");
    302  1.1  rillig     printf("\n");
    303  1.1  rillig }
    304  1.1  rillig #endif
    305