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