Sat Mar 13 09:21:57 2021 UTC ()
indent: add debug logging for actually writing to the output file

Together with the results of the tokenizer and the 4 buffers for token,
label, code and comment, the debug log now provides a good high-level
view on how the indentation happens and where to look for the many
remaining bugs.


(rillig)
diff -r1.47 -r1.48 src/usr.bin/indent/indent.c
diff -r1.8 -r1.9 src/usr.bin/indent/indent.h
diff -r1.35 -r1.36 src/usr.bin/indent/io.c
diff -r1.38 -r1.39 src/usr.bin/indent/lexi.c

cvs diff -r1.47 -r1.48 src/usr.bin/indent/indent.c (switch to unified diff)

--- src/usr.bin/indent/indent.c 2021/03/13 00:26:56 1.47
+++ src/usr.bin/indent/indent.c 2021/03/13 09:21:57 1.48
@@ -1,1391 +1,1434 @@ @@ -1,1391 +1,1434 @@
1/* $NetBSD: indent.c,v 1.47 2021/03/13 00:26:56 rillig Exp $ */ 1/* $NetBSD: indent.c,v 1.48 2021/03/13 09:21:57 rillig Exp $ */
2 2
3/*- 3/*-
4 * SPDX-License-Identifier: BSD-4-Clause 4 * SPDX-License-Identifier: BSD-4-Clause
5 * 5 *
6 * Copyright (c) 1985 Sun Microsystems, Inc. 6 * Copyright (c) 1985 Sun Microsystems, Inc.
7 * Copyright (c) 1976 Board of Trustees of the University of Illinois. 7 * Copyright (c) 1976 Board of Trustees of the University of Illinois.
8 * Copyright (c) 1980, 1993 8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved. 9 * The Regents of the University of California. All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software 19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement: 20 * must display the following acknowledgement:
21 * This product includes software developed by the University of 21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors. 22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors 23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software 24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission. 25 * without specific prior written permission.
26 * 26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE. 37 * SUCH DAMAGE.
38 */ 38 */
39 39
40#if 0 40#if 0
41#ifndef lint 41#ifndef lint
42static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; 42static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93";
43#endif /* not lint */ 43#endif /* not lint */
44#endif 44#endif
45 45
46#include <sys/cdefs.h> 46#include <sys/cdefs.h>
47#ifndef lint 47#ifndef lint
48#if defined(__NetBSD__) 48#if defined(__NetBSD__)
49__RCSID("$NetBSD: indent.c,v 1.47 2021/03/13 00:26:56 rillig Exp $"); 49__RCSID("$NetBSD: indent.c,v 1.48 2021/03/13 09:21:57 rillig Exp $");
50#elif defined(__FreeBSD__) 50#elif defined(__FreeBSD__)
51__FBSDID("$FreeBSD: head/usr.bin/indent/indent.c 340138 2018-11-04 19:24:49Z oshogbo $"); 51__FBSDID("$FreeBSD: head/usr.bin/indent/indent.c 340138 2018-11-04 19:24:49Z oshogbo $");
52#endif 52#endif
53#endif 53#endif
54 54
55#include <sys/param.h> 55#include <sys/param.h>
56#if HAVE_CAPSICUM 56#if HAVE_CAPSICUM
57#include <sys/capsicum.h> 57#include <sys/capsicum.h>
58#include <capsicum_helpers.h> 58#include <capsicum_helpers.h>
59#endif 59#endif
60#include <err.h> 60#include <err.h>
61#include <errno.h> 61#include <errno.h>
62#include <fcntl.h> 62#include <fcntl.h>
63#include <unistd.h> 63#include <unistd.h>
64#include <stdio.h> 64#include <stdio.h>
65#include <stdlib.h> 65#include <stdlib.h>
66#include <string.h> 66#include <string.h>
67#include <ctype.h> 67#include <ctype.h>
68 68
69#include "indent.h" 69#include "indent.h"
70 70
71struct options opt; 71struct options opt;
72struct parser_state ps; 72struct parser_state ps;
73 73
74char *labbuf; 74char *labbuf;
75char *s_lab; 75char *s_lab;
76char *e_lab; 76char *e_lab;
77char *l_lab; 77char *l_lab;
78 78
79char *codebuf; 79char *codebuf;
80char *s_code; 80char *s_code;
81char *e_code; 81char *e_code;
82char *l_code; 82char *l_code;
83 83
84char *combuf; 84char *combuf;
85char *s_com; 85char *s_com;
86char *e_com; 86char *e_com;
87char *l_com; 87char *l_com;
88 88
89char *tokenbuf; 89char *tokenbuf;
90char *s_token; 90char *s_token;
91char *e_token; 91char *e_token;
92char *l_token; 92char *l_token;
93 93
94char *in_buffer; 94char *in_buffer;
95char *in_buffer_limit; 95char *in_buffer_limit;
96char *buf_ptr; 96char *buf_ptr;
97char *buf_end; 97char *buf_end;
98 98
99char sc_buf[sc_size]; 99char sc_buf[sc_size];
100char *save_com; 100char *save_com;
101char *sc_end; 101char *sc_end;
102 102
103char *bp_save; 103char *bp_save;
104char *be_save; 104char *be_save;
105 105
106int found_err; 106int found_err;
107int n_real_blanklines; 107int n_real_blanklines;
108int prefix_blankline_requested; 108int prefix_blankline_requested;
109int postfix_blankline_requested; 109int postfix_blankline_requested;
110int break_comma; 110int break_comma;
111float case_ind; 111float case_ind;
112int code_lines; 112int code_lines;
113int had_eof; 113int had_eof;
114int line_no; 114int line_no;
115int inhibit_formatting; 115int inhibit_formatting;
116int suppress_blanklines; 116int suppress_blanklines;
117 117
118int ifdef_level; 118int ifdef_level;
119struct parser_state state_stack[5]; 119struct parser_state state_stack[5];
120struct parser_state match_state[5]; 120struct parser_state match_state[5];
121 121
122FILE *input; 122FILE *input;
123FILE *output; 123FILE *output;
124 124
125static void bakcopy(void); 125static void bakcopy(void);
126static void indent_declaration(int, int); 126static void indent_declaration(int, int);
127 127
128const char *in_name = "Standard Input"; /* will always point to name of input 128const char *in_name = "Standard Input"; /* will always point to name of input
129 * file */ 129 * file */
130const char *out_name = "Standard Output"; /* will always point to name 130const char *out_name = "Standard Output"; /* will always point to name
131 * of output file */ 131 * of output file */
132const char *simple_backup_suffix = ".BAK"; /* Suffix to use for backup 132const char *simple_backup_suffix = ".BAK"; /* Suffix to use for backup
133 * files */ 133 * files */
134char bakfile[MAXPATHLEN] = ""; 134char bakfile[MAXPATHLEN] = "";
135 135
136static void 136static void
137check_size_code(size_t desired_size) 137check_size_code(size_t desired_size)
138{ 138{
139 if (e_code + (desired_size) < l_code) 139 if (e_code + (desired_size) < l_code)
140 return; 140 return;
141 141
142 size_t nsize = l_code - s_code + 400 + desired_size; 142 size_t nsize = l_code - s_code + 400 + desired_size;
143 size_t code_len = e_code - s_code; 143 size_t code_len = e_code - s_code;
144 codebuf = realloc(codebuf, nsize); 144 codebuf = realloc(codebuf, nsize);
145 if (codebuf == NULL) 145 if (codebuf == NULL)
146 err(1, NULL); 146 err(1, NULL);
147 e_code = codebuf + code_len + 1; 147 e_code = codebuf + code_len + 1;
148 l_code = codebuf + nsize - 5; 148 l_code = codebuf + nsize - 5;
149 s_code = codebuf + 1; 149 s_code = codebuf + 1;
150} 150}
151 151
152static void 152static void
153check_size_label(size_t desired_size) 153check_size_label(size_t desired_size)
154{ 154{
155 if (e_lab + (desired_size) < l_lab) 155 if (e_lab + (desired_size) < l_lab)
156 return; 156 return;
157 157
158 size_t nsize = l_lab - s_lab + 400 + desired_size; 158 size_t nsize = l_lab - s_lab + 400 + desired_size;
159 size_t label_len = e_lab - s_lab; 159 size_t label_len = e_lab - s_lab;
160 labbuf = realloc(labbuf, nsize); 160 labbuf = realloc(labbuf, nsize);
161 if (labbuf == NULL) 161 if (labbuf == NULL)
162 err(1, NULL); 162 err(1, NULL);
163 e_lab = labbuf + label_len + 1; 163 e_lab = labbuf + label_len + 1;
164 l_lab = labbuf + nsize - 5; 164 l_lab = labbuf + nsize - 5;
165 s_lab = labbuf + 1; 165 s_lab = labbuf + 1;
166} 166}
167 167
168#if HAVE_CAPSICUM 168#if HAVE_CAPSICUM
169static void 169static void
170init_capsicum(void) 170init_capsicum(void)
171{ 171{
172 cap_rights_t rights; 172 cap_rights_t rights;
173 173
174 /* Restrict input/output descriptors and enter Capsicum sandbox. */ 174 /* Restrict input/output descriptors and enter Capsicum sandbox. */
175 cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE); 175 cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
176 if (caph_rights_limit(fileno(output), &rights) < 0) 176 if (caph_rights_limit(fileno(output), &rights) < 0)
177 err(EXIT_FAILURE, "unable to limit rights for %s", out_name); 177 err(EXIT_FAILURE, "unable to limit rights for %s", out_name);
178 cap_rights_init(&rights, CAP_FSTAT, CAP_READ); 178 cap_rights_init(&rights, CAP_FSTAT, CAP_READ);
179 if (caph_rights_limit(fileno(input), &rights) < 0) 179 if (caph_rights_limit(fileno(input), &rights) < 0)
180 err(EXIT_FAILURE, "unable to limit rights for %s", in_name); 180 err(EXIT_FAILURE, "unable to limit rights for %s", in_name);
181 if (caph_enter() < 0) 181 if (caph_enter() < 0)
182 err(EXIT_FAILURE, "unable to enter capability mode"); 182 err(EXIT_FAILURE, "unable to enter capability mode");
183} 183}
184#endif 184#endif
185 185
186static void 186static void
187search_brace(token_type *inout_type_code, int *inout_force_nl, 187search_brace(token_type *inout_type_code, int *inout_force_nl,
188 int *inout_comment_buffered, int *inout_last_else) 188 int *inout_comment_buffered, int *inout_last_else)
189{ 189{
190 while (ps.search_brace) { 190 while (ps.search_brace) {
191 switch (*inout_type_code) { 191 switch (*inout_type_code) {
192 case newline: 192 case newline:
193 if (sc_end == NULL) { 193 if (sc_end == NULL) {
194 save_com = sc_buf; 194 save_com = sc_buf;
195 save_com[0] = save_com[1] = ' '; 195 save_com[0] = save_com[1] = ' ';
196 sc_end = &save_com[2]; 196 sc_end = &save_com[2];
197 } 197 }
198 *sc_end++ = '\n'; 198 *sc_end++ = '\n';
199 /* 199 /*
200 * We may have inherited a force_nl == true from the previous 200 * We may have inherited a force_nl == true from the previous
201 * token (like a semicolon). But once we know that a newline 201 * token (like a semicolon). But once we know that a newline
202 * has been scanned in this loop, force_nl should be false. 202 * has been scanned in this loop, force_nl should be false.
203 * 203 *
204 * However, the force_nl == true must be preserved if newline 204 * However, the force_nl == true must be preserved if newline
205 * is never scanned in this loop, so this assignment cannot be 205 * is never scanned in this loop, so this assignment cannot be
206 * done earlier. 206 * done earlier.
207 */ 207 */
208 *inout_force_nl = false; 208 *inout_force_nl = false;
209 case form_feed: 209 case form_feed:
210 break; 210 break;
211 case comment: 211 case comment:
212 if (sc_end == NULL) { 212 if (sc_end == NULL) {
213 /* 213 /*
214 * Copy everything from the start of the line, because 214 * Copy everything from the start of the line, because
215 * pr_comment() will use that to calculate original 215 * pr_comment() will use that to calculate original
216 * indentation of a boxed comment. 216 * indentation of a boxed comment.
217 */ 217 */
218 memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4); 218 memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4);
219 save_com = sc_buf + (buf_ptr - in_buffer - 4); 219 save_com = sc_buf + (buf_ptr - in_buffer - 4);
220 save_com[0] = save_com[1] = ' '; 220 save_com[0] = save_com[1] = ' ';
221 sc_end = &save_com[2]; 221 sc_end = &save_com[2];
222 } 222 }
223 *inout_comment_buffered = true; 223 *inout_comment_buffered = true;
224 *sc_end++ = '/'; /* copy in start of comment */ 224 *sc_end++ = '/'; /* copy in start of comment */
225 *sc_end++ = '*'; 225 *sc_end++ = '*';
226 for (;;) { /* loop until the end of the comment */ 226 for (;;) { /* loop until the end of the comment */
227 *sc_end = *buf_ptr++; 227 *sc_end = *buf_ptr++;
228 if (buf_ptr >= buf_end) 228 if (buf_ptr >= buf_end)
229 fill_buffer(); 229 fill_buffer();
230 if (*sc_end++ == '*' && *buf_ptr == '/') 230 if (*sc_end++ == '*' && *buf_ptr == '/')
231 break; /* we are at end of comment */ 231 break; /* we are at end of comment */
232 if (sc_end >= &save_com[sc_size]) { /* check for temp buffer 232 if (sc_end >= &save_com[sc_size]) { /* check for temp buffer
233 * overflow */ 233 * overflow */
234 diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever"); 234 diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever");
235 fflush(output); 235 fflush(output);
236 exit(1); 236 exit(1);
237 } 237 }
238 } 238 }
239 *sc_end++ = '/'; /* add ending slash */ 239 *sc_end++ = '/'; /* add ending slash */
240 if (++buf_ptr >= buf_end) /* get past / in buffer */ 240 if (++buf_ptr >= buf_end) /* get past / in buffer */
241 fill_buffer(); 241 fill_buffer();
242 break; 242 break;
243 case lbrace: 243 case lbrace:
244 /* 244 /*
245 * Put KNF-style lbraces before the buffered up tokens and 245 * Put KNF-style lbraces before the buffered up tokens and
246 * jump out of this loop in order to avoid copying the token 246 * jump out of this loop in order to avoid copying the token
247 * again under the default case of the switch below. 247 * again under the default case of the switch below.
248 */ 248 */
249 if (sc_end != NULL && opt.btype_2) { 249 if (sc_end != NULL && opt.btype_2) {
250 save_com[0] = '{'; 250 save_com[0] = '{';
251 /* 251 /*
252 * Originally the lbrace may have been alone on its own 252 * Originally the lbrace may have been alone on its own
253 * line, but it will be moved into "the else's line", so 253 * line, but it will be moved into "the else's line", so
254 * if there was a newline resulting from the "{" before, 254 * if there was a newline resulting from the "{" before,
255 * it must be scanned now and ignored. 255 * it must be scanned now and ignored.
256 */ 256 */
257 while (isspace((unsigned char)*buf_ptr)) { 257 while (isspace((unsigned char)*buf_ptr)) {
258 if (++buf_ptr >= buf_end) 258 if (++buf_ptr >= buf_end)
259 fill_buffer(); 259 fill_buffer();
260 if (*buf_ptr == '\n') 260 if (*buf_ptr == '\n')
261 break; 261 break;
262 } 262 }
263 goto sw_buffer; 263 goto sw_buffer;
264 } 264 }
265 /* FALLTHROUGH */ 265 /* FALLTHROUGH */
266 default: /* it is the start of a normal statement */ 266 default: /* it is the start of a normal statement */
267 { 267 {
268 int remove_newlines; 268 int remove_newlines;
269 269
270 remove_newlines = 270 remove_newlines =
271 /* "} else" */ 271 /* "} else" */
272 (*inout_type_code == keyword_do_else && *token == 'e' && 272 (*inout_type_code == keyword_do_else && *token == 'e' &&
273 e_code != s_code && e_code[-1] == '}') 273 e_code != s_code && e_code[-1] == '}')
274 /* "else if" */ 274 /* "else if" */
275 || (*inout_type_code == keyword_for_if_while && 275 || (*inout_type_code == keyword_for_if_while &&
276 *token == 'i' && *inout_last_else && opt.else_if); 276 *token == 'i' && *inout_last_else && opt.else_if);
277 if (remove_newlines) 277 if (remove_newlines)
278 *inout_force_nl = false; 278 *inout_force_nl = false;
279 if (sc_end == NULL) { /* ignore buffering if 279 if (sc_end == NULL) { /* ignore buffering if
280 * comment wasn't saved up */ 280 * comment wasn't saved up */
281 ps.search_brace = false; 281 ps.search_brace = false;
282 return; 282 return;
283 } 283 }
284 while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) { 284 while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) {
285 sc_end--; 285 sc_end--;
286 } 286 }
287 if (opt.swallow_optional_blanklines || 287 if (opt.swallow_optional_blanklines ||
288 (!*inout_comment_buffered && remove_newlines)) { 288 (!*inout_comment_buffered && remove_newlines)) {
289 *inout_force_nl = !remove_newlines; 289 *inout_force_nl = !remove_newlines;
290 while (sc_end > save_com && sc_end[-1] == '\n') { 290 while (sc_end > save_com && sc_end[-1] == '\n') {
291 sc_end--; 291 sc_end--;
292 } 292 }
293 } 293 }
294 if (*inout_force_nl) { /* if we should insert a nl here, put 294 if (*inout_force_nl) { /* if we should insert a nl here, put
295 * it into the buffer */ 295 * it into the buffer */
296 *inout_force_nl = false; 296 *inout_force_nl = false;
297 --line_no; /* this will be re-increased when the 297 --line_no; /* this will be re-increased when the
298 * newline is read from the buffer */ 298 * newline is read from the buffer */
299 *sc_end++ = '\n'; 299 *sc_end++ = '\n';
300 *sc_end++ = ' '; 300 *sc_end++ = ' ';
301 if (opt.verbose) /* print error msg if the line was 301 if (opt.verbose) /* print error msg if the line was
302 * not already broken */ 302 * not already broken */
303 diag(0, "Line broken"); 303 diag(0, "Line broken");
304 } 304 }
305 for (const char *t_ptr = token; *t_ptr; ++t_ptr) 305 for (const char *t_ptr = token; *t_ptr; ++t_ptr)
306 *sc_end++ = *t_ptr; 306 *sc_end++ = *t_ptr;
307 307
308 sw_buffer: 308 sw_buffer:
309 ps.search_brace = false; /* stop looking for start of stmt */ 309 ps.search_brace = false; /* stop looking for start of stmt */
310 bp_save = buf_ptr; /* save current input buffer */ 310 bp_save = buf_ptr; /* save current input buffer */
311 be_save = buf_end; 311 be_save = buf_end;
312 buf_ptr = save_com; /* fix so that subsequent calls to 312 buf_ptr = save_com; /* fix so that subsequent calls to
313 * lexi will take tokens out of save_com */ 313 * lexi will take tokens out of save_com */
314 *sc_end++ = ' '; /* add trailing blank, just in case */ 314 *sc_end++ = ' '; /* add trailing blank, just in case */
315 buf_end = sc_end; 315 buf_end = sc_end;
316 sc_end = NULL; 316 sc_end = NULL;
317 break; 317 break;
318 } 318 }
319 } /* end of switch */ 319 } /* end of switch */
320 /* 320 /*
321 * We must make this check, just in case there was an unexpected 321 * We must make this check, just in case there was an unexpected
322 * EOF. 322 * EOF.
323 */ 323 */
324 if (*inout_type_code != end_of_file) { 324 if (*inout_type_code != end_of_file) {
325 /* 325 /*
326 * The only intended purpose of calling lexi() below is to 326 * The only intended purpose of calling lexi() below is to
327 * categorize the next token in order to decide whether to 327 * categorize the next token in order to decide whether to
328 * continue buffering forthcoming tokens. Once the buffering 328 * continue buffering forthcoming tokens. Once the buffering
329 * is over, lexi() will be called again elsewhere on all of 329 * is over, lexi() will be called again elsewhere on all of
330 * the tokens - this time for normal processing. 330 * the tokens - this time for normal processing.
331 * 331 *
332 * Calling it for this purpose is a bug, because lexi() also 332 * Calling it for this purpose is a bug, because lexi() also
333 * changes the parser state and discards leading whitespace, 333 * changes the parser state and discards leading whitespace,
334 * which is needed mostly for comment-related considerations. 334 * which is needed mostly for comment-related considerations.
335 * 335 *
336 * Work around the former problem by giving lexi() a copy of 336 * Work around the former problem by giving lexi() a copy of
337 * the current parser state and discard it if the call turned 337 * the current parser state and discard it if the call turned
338 * out to be just a look ahead. 338 * out to be just a look ahead.
339 * 339 *
340 * Work around the latter problem by copying all whitespace 340 * Work around the latter problem by copying all whitespace
341 * characters into the buffer so that the later lexi() call 341 * characters into the buffer so that the later lexi() call
342 * will read them. 342 * will read them.
343 */ 343 */
344 if (sc_end != NULL) { 344 if (sc_end != NULL) {
345 while (*buf_ptr == ' ' || *buf_ptr == '\t') { 345 while (*buf_ptr == ' ' || *buf_ptr == '\t') {
346 *sc_end++ = *buf_ptr++; 346 *sc_end++ = *buf_ptr++;
347 if (sc_end >= &save_com[sc_size]) { 347 if (sc_end >= &save_com[sc_size]) {
348 errx(1, "input too long"); 348 errx(1, "input too long");
349 } 349 }
350 } 350 }
351 if (buf_ptr >= buf_end) { 351 if (buf_ptr >= buf_end) {
352 fill_buffer(); 352 fill_buffer();
353 } 353 }
354 } 354 }
355 355
356 struct parser_state transient_state; 356 struct parser_state transient_state;
357 transient_state = ps; 357 transient_state = ps;
358 *inout_type_code = lexi(&transient_state); /* read another token */ 358 *inout_type_code = lexi(&transient_state); /* read another token */
359 if (*inout_type_code != newline && *inout_type_code != form_feed && 359 if (*inout_type_code != newline && *inout_type_code != form_feed &&
360 *inout_type_code != comment && !transient_state.search_brace) { 360 *inout_type_code != comment && !transient_state.search_brace) {
361 ps = transient_state; 361 ps = transient_state;
362 } 362 }
363 } 363 }
364 } 364 }
365 365
366 *inout_last_else = 0; 366 *inout_last_else = 0;
367} 367}
368 368
369int 369int
370main(int argc, char **argv) 370main(int argc, char **argv)
371{ 371{
372 int dec_ind; /* current indentation for declarations */ 372 int dec_ind; /* current indentation for declarations */
373 int di_stack[20]; /* a stack of structure indentation levels */ 373 int di_stack[20]; /* a stack of structure indentation levels */
374 int force_nl; /* when true, code must be broken */ 374 int force_nl; /* when true, code must be broken */
375 token_type hd_type = end_of_file; /* used to store type of stmt 375 token_type hd_type = end_of_file; /* used to store type of stmt
376 * for if (...), for (...), etc */ 376 * for if (...), for (...), etc */
377 int i; /* local loop counter */ 377 int i; /* local loop counter */
378 int scase; /* set to true when we see a case, so we will 378 int scase; /* set to true when we see a case, so we will
379 * know what to do with the following colon */ 379 * know what to do with the following colon */
380 int sp_sw; /* when true, we are in the expression of 380 int sp_sw; /* when true, we are in the expression of
381 * if(...), while(...), etc. */ 381 * if(...), while(...), etc. */
382 int squest; /* when this is positive, we have seen a ? 382 int squest; /* when this is positive, we have seen a ?
383 * without the matching : in a <c>?<s>:<s> 383 * without the matching : in a <c>?<s>:<s>
384 * construct */ 384 * construct */
385 int tabs_to_var; /* true if using tabs to indent to var name */ 385 int tabs_to_var; /* true if using tabs to indent to var name */
386 token_type type_code; /* returned by lexi */ 386 token_type type_code; /* returned by lexi */
387 387
388 int last_else = 0; /* true iff last keyword was an else */ 388 int last_else = 0; /* true iff last keyword was an else */
389 const char *profile_name = NULL; 389 const char *profile_name = NULL;
390 const char *envval = NULL; 390 const char *envval = NULL;
391 391
392 /*-----------------------------------------------*\ 392 /*-----------------------------------------------*\
393 | INITIALIZATION | 393 | INITIALIZATION |
394 \*-----------------------------------------------*/ 394 \*-----------------------------------------------*/
395 395
396 found_err = 0; 396 found_err = 0;
397 397
398 ps.p_stack[0] = stmt; /* this is the parser's stack */ 398 ps.p_stack[0] = stmt; /* this is the parser's stack */
399 ps.last_nl = true; /* this is true if the last thing scanned was 399 ps.last_nl = true; /* this is true if the last thing scanned was
400 * a newline */ 400 * a newline */
401 ps.last_token = semicolon; 401 ps.last_token = semicolon;
402 combuf = malloc(bufsize); 402 combuf = malloc(bufsize);
403 if (combuf == NULL) 403 if (combuf == NULL)
404 err(1, NULL); 404 err(1, NULL);
405 labbuf = malloc(bufsize); 405 labbuf = malloc(bufsize);
406 if (labbuf == NULL) 406 if (labbuf == NULL)
407 err(1, NULL); 407 err(1, NULL);
408 codebuf = malloc(bufsize); 408 codebuf = malloc(bufsize);
409 if (codebuf == NULL) 409 if (codebuf == NULL)
410 err(1, NULL); 410 err(1, NULL);
411 tokenbuf = malloc(bufsize); 411 tokenbuf = malloc(bufsize);
412 if (tokenbuf == NULL) 412 if (tokenbuf == NULL)
413 err(1, NULL); 413 err(1, NULL);
414 alloc_typenames(); 414 alloc_typenames();
415 init_constant_tt(); 415 init_constant_tt();
416 l_com = combuf + bufsize - 5; 416 l_com = combuf + bufsize - 5;
417 l_lab = labbuf + bufsize - 5; 417 l_lab = labbuf + bufsize - 5;
418 l_code = codebuf + bufsize - 5; 418 l_code = codebuf + bufsize - 5;
419 l_token = tokenbuf + bufsize - 5; 419 l_token = tokenbuf + bufsize - 5;
420 combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and 420 combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and
421 * comment buffers */ 421 * comment buffers */
422 combuf[1] = codebuf[1] = labbuf[1] = tokenbuf[1] = '\0'; 422 combuf[1] = codebuf[1] = labbuf[1] = tokenbuf[1] = '\0';
423 opt.else_if = 1; /* Default else-if special processing to on */ 423 opt.else_if = 1; /* Default else-if special processing to on */
424 s_lab = e_lab = labbuf + 1; 424 s_lab = e_lab = labbuf + 1;
425 s_code = e_code = codebuf + 1; 425 s_code = e_code = codebuf + 1;
426 s_com = e_com = combuf + 1; 426 s_com = e_com = combuf + 1;
427 s_token = e_token = tokenbuf + 1; 427 s_token = e_token = tokenbuf + 1;
428 428
429 in_buffer = malloc(10); 429 in_buffer = malloc(10);
430 if (in_buffer == NULL) 430 if (in_buffer == NULL)
431 err(1, NULL); 431 err(1, NULL);
432 in_buffer_limit = in_buffer + 8; 432 in_buffer_limit = in_buffer + 8;
433 buf_ptr = buf_end = in_buffer; 433 buf_ptr = buf_end = in_buffer;
434 line_no = 1; 434 line_no = 1;
435 had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; 435 had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
436 sp_sw = force_nl = false; 436 sp_sw = force_nl = false;
437 ps.in_or_st = false; 437 ps.in_or_st = false;
438 ps.bl_line = true; 438 ps.bl_line = true;
439 dec_ind = 0; 439 dec_ind = 0;
440 di_stack[ps.dec_nest = 0] = 0; 440 di_stack[ps.dec_nest = 0] = 0;
441 ps.want_blank = ps.in_stmt = ps.ind_stmt = false; 441 ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
442 442
443 scase = ps.pcase = false; 443 scase = ps.pcase = false;
444 squest = 0; 444 squest = 0;
445 sc_end = NULL; 445 sc_end = NULL;
446 bp_save = NULL; 446 bp_save = NULL;
447 be_save = NULL; 447 be_save = NULL;
448 448
449 output = NULL; 449 output = NULL;
450 tabs_to_var = 0; 450 tabs_to_var = 0;
451 451
452 envval = getenv("SIMPLE_BACKUP_SUFFIX"); 452 envval = getenv("SIMPLE_BACKUP_SUFFIX");
453 if (envval) 453 if (envval)
454 simple_backup_suffix = envval; 454 simple_backup_suffix = envval;
455 455
456 /*--------------------------------------------------*\ 456 /*--------------------------------------------------*\
457 | COMMAND LINE SCAN | 457 | COMMAND LINE SCAN |
458 \*--------------------------------------------------*/ 458 \*--------------------------------------------------*/
459 459
460#ifdef undef 460#ifdef undef
461 max_col = 78; /* -l78 */ 461 max_col = 78; /* -l78 */
462 lineup_to_parens = 1; /* -lp */ 462 lineup_to_parens = 1; /* -lp */
463 lineup_to_parens_always = 0; /* -nlpl */ 463 lineup_to_parens_always = 0; /* -nlpl */
464 ps.ljust_decl = 0; /* -ndj */ 464 ps.ljust_decl = 0; /* -ndj */
465 ps.com_ind = 33; /* -c33 */ 465 ps.com_ind = 33; /* -c33 */
466 star_comment_cont = 1; /* -sc */ 466 star_comment_cont = 1; /* -sc */
467 ps.ind_size = 8; /* -i8 */ 467 ps.ind_size = 8; /* -i8 */
468 verbose = 0; 468 verbose = 0;
469 ps.decl_indent = 16; /* -di16 */ 469 ps.decl_indent = 16; /* -di16 */
470 ps.local_decl_indent = -1; /* if this is not set to some nonnegative value 470 ps.local_decl_indent = -1; /* if this is not set to some nonnegative value
471 * by an arg, we will set this equal to 471 * by an arg, we will set this equal to
472 * ps.decl_ind */ 472 * ps.decl_ind */
473 ps.indent_parameters = 1; /* -ip */ 473 ps.indent_parameters = 1; /* -ip */
474 ps.decl_com_ind = 0; /* if this is not set to some positive value 474 ps.decl_com_ind = 0; /* if this is not set to some positive value
475 * by an arg, we will set this equal to 475 * by an arg, we will set this equal to
476 * ps.com_ind */ 476 * ps.com_ind */
477 btype_2 = 1; /* -br */ 477 btype_2 = 1; /* -br */
478 cuddle_else = 1; /* -ce */ 478 cuddle_else = 1; /* -ce */
479 ps.unindent_displace = 0; /* -d0 */ 479 ps.unindent_displace = 0; /* -d0 */
480 ps.case_indent = 0; /* -cli0 */ 480 ps.case_indent = 0; /* -cli0 */
481 format_block_comments = 1; /* -fcb */ 481 format_block_comments = 1; /* -fcb */
482 format_col1_comments = 1; /* -fc1 */ 482 format_col1_comments = 1; /* -fc1 */
483 procnames_start_line = 1; /* -psl */ 483 procnames_start_line = 1; /* -psl */
484 proc_calls_space = 0; /* -npcs */ 484 proc_calls_space = 0; /* -npcs */
485 comment_delimiter_on_blankline = 1; /* -cdb */ 485 comment_delimiter_on_blankline = 1; /* -cdb */
486 ps.leave_comma = 1; /* -nbc */ 486 ps.leave_comma = 1; /* -nbc */
487#endif 487#endif
488 488
489 for (i = 1; i < argc; ++i) 489 for (i = 1; i < argc; ++i)
490 if (strcmp(argv[i], "-npro") == 0) 490 if (strcmp(argv[i], "-npro") == 0)
491 break; 491 break;
492 else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0') 492 else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0')
493 profile_name = argv[i]; /* non-empty -P (set profile) */ 493 profile_name = argv[i]; /* non-empty -P (set profile) */
494 set_defaults(); 494 set_defaults();
495 if (i >= argc) 495 if (i >= argc)
496 set_profile(profile_name); 496 set_profile(profile_name);
497 497
498 for (i = 1; i < argc; ++i) { 498 for (i = 1; i < argc; ++i) {
499 499
500 /* 500 /*
501 * look thru args (if any) for changes to defaults 501 * look thru args (if any) for changes to defaults
502 */ 502 */
503 if (argv[i][0] != '-') {/* no flag on parameter */ 503 if (argv[i][0] != '-') {/* no flag on parameter */
504 if (input == NULL) { /* we must have the input file */ 504 if (input == NULL) { /* we must have the input file */
505 in_name = argv[i]; /* remember name of input file */ 505 in_name = argv[i]; /* remember name of input file */
506 input = fopen(in_name, "r"); 506 input = fopen(in_name, "r");
507 if (input == NULL) /* check for open error */ 507 if (input == NULL) /* check for open error */
508 err(1, "%s", in_name); 508 err(1, "%s", in_name);
509 continue; 509 continue;
510 } else if (output == NULL) { /* we have the output file */ 510 } else if (output == NULL) { /* we have the output file */
511 out_name = argv[i]; /* remember name of output file */ 511 out_name = argv[i]; /* remember name of output file */
512 if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite 512 if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite
513 * the file */ 513 * the file */
514 errx(1, "input and output files must be different"); 514 errx(1, "input and output files must be different");
515 } 515 }
516 output = fopen(out_name, "w"); 516 output = fopen(out_name, "w");
517 if (output == NULL) /* check for create error */ 517 if (output == NULL) /* check for create error */
518 err(1, "%s", out_name); 518 err(1, "%s", out_name);
519 continue; 519 continue;
520 } 520 }
521 errx(1, "unknown parameter: %s", argv[i]); 521 errx(1, "unknown parameter: %s", argv[i]);
522 } else 522 } else
523 set_option(argv[i]); 523 set_option(argv[i]);
524 } /* end of for */ 524 } /* end of for */
525 if (input == NULL) 525 if (input == NULL)
526 input = stdin; 526 input = stdin;
527 if (output == NULL) { 527 if (output == NULL) {
528 if (input == stdin) 528 if (input == stdin)
529 output = stdout; 529 output = stdout;
530 else { 530 else {
531 out_name = in_name; 531 out_name = in_name;
532 bakcopy(); 532 bakcopy();
533 } 533 }
534 } 534 }
535 535
536#if HAVE_CAPSICUM 536#if HAVE_CAPSICUM
537 init_capsicum(); 537 init_capsicum();
538#endif 538#endif
539 539
540 if (opt.com_ind <= 1) 540 if (opt.com_ind <= 1)
541 opt.com_ind = 2; /* don't put normal comments before column 2 */ 541 opt.com_ind = 2; /* don't put normal comments before column 2 */
542 if (opt.block_comment_max_col <= 0) 542 if (opt.block_comment_max_col <= 0)
543 opt.block_comment_max_col = opt.max_col; 543 opt.block_comment_max_col = opt.max_col;
544 if (opt.local_decl_indent < 0) /* if not specified by user, set this */ 544 if (opt.local_decl_indent < 0) /* if not specified by user, set this */
545 opt.local_decl_indent = opt.decl_indent; 545 opt.local_decl_indent = opt.decl_indent;
546 if (opt.decl_com_ind <= 0) /* if not specified by user, set this */ 546 if (opt.decl_com_ind <= 0) /* if not specified by user, set this */
547 opt.decl_com_ind = opt.ljust_decl ? (opt.com_ind <= 10 ? 2 : opt.com_ind - 8) : opt.com_ind; 547 opt.decl_com_ind = opt.ljust_decl ? (opt.com_ind <= 10 ? 2 : opt.com_ind - 8) : opt.com_ind;
548 if (opt.continuation_indent == 0) 548 if (opt.continuation_indent == 0)
549 opt.continuation_indent = opt.ind_size; 549 opt.continuation_indent = opt.ind_size;
550 fill_buffer(); /* get first batch of stuff into input buffer */ 550 fill_buffer(); /* get first batch of stuff into input buffer */
551 551
552 parse(semicolon); 552 parse(semicolon);
553 { 553 {
554 char *p = buf_ptr; 554 char *p = buf_ptr;
555 int col = 1; 555 int col = 1;
556 556
557 while (1) { 557 while (1) {
558 if (*p == ' ') 558 if (*p == ' ')
559 col++; 559 col++;
560 else if (*p == '\t') 560 else if (*p == '\t')
561 col = opt.tabsize * (1 + (col - 1) / opt.tabsize) + 1; 561 col = opt.tabsize * (1 + (col - 1) / opt.tabsize) + 1;
562 else 562 else
563 break; 563 break;
564 p++; 564 p++;
565 } 565 }
566 if (col > opt.ind_size) 566 if (col > opt.ind_size)
567 ps.ind_level = ps.i_l_follow = col / opt.ind_size; 567 ps.ind_level = ps.i_l_follow = col / opt.ind_size;
568 } 568 }
569 569
570 /* 570 /*
571 * START OF MAIN LOOP 571 * START OF MAIN LOOP
572 */ 572 */
573 573
574 while (1) { /* this is the main loop. it will go until we 574 while (1) { /* this is the main loop. it will go until we
575 * reach eof */ 575 * reach eof */
576 int comment_buffered = false; 576 int comment_buffered = false;
577 577
578 type_code = lexi(&ps); /* lexi reads one token. The actual 578 type_code = lexi(&ps); /* lexi reads one token. The actual
579 * characters read are stored in "token". lexi 579 * characters read are stored in "token". lexi
580 * returns a code indicating the type of token */ 580 * returns a code indicating the type of token */
581 581
582 /* 582 /*
583 * The following code moves newlines and comments following an if (), 583 * The following code moves newlines and comments following an if (),
584 * while (), else, etc. up to the start of the following stmt to 584 * while (), else, etc. up to the start of the following stmt to
585 * a buffer. This allows proper handling of both kinds of brace 585 * a buffer. This allows proper handling of both kinds of brace
586 * placement (-br, -bl) and cuddling "else" (-ce). 586 * placement (-br, -bl) and cuddling "else" (-ce).
587 */ 587 */
588 search_brace(&type_code, &force_nl, &comment_buffered, &last_else); 588 search_brace(&type_code, &force_nl, &comment_buffered, &last_else);
589 589
590 if (type_code == end_of_file) { /* we got eof */ 590 if (type_code == end_of_file) { /* we got eof */
591 if (s_lab != e_lab || s_code != e_code 591 if (s_lab != e_lab || s_code != e_code
592 || s_com != e_com) /* must dump end of line */ 592 || s_com != e_com) /* must dump end of line */
593 dump_line(); 593 dump_line();
594 if (ps.tos > 1) /* check for balanced braces */ 594 if (ps.tos > 1) /* check for balanced braces */
595 diag(1, "Stuff missing from end of file"); 595 diag(1, "Stuff missing from end of file");
596 596
597 if (opt.verbose) { 597 if (opt.verbose) {
598 printf("There were %d output lines and %d comments\n", 598 printf("There were %d output lines and %d comments\n",
599 ps.out_lines, ps.out_coms); 599 ps.out_lines, ps.out_coms);
600 printf("(Lines with comments)/(Lines with code): %6.3f\n", 600 printf("(Lines with comments)/(Lines with code): %6.3f\n",
601 (1.0 * ps.com_lines) / code_lines); 601 (1.0 * ps.com_lines) / code_lines);
602 } 602 }
603 fflush(output); 603 fflush(output);
604 exit(found_err); 604 exit(found_err);
605 } 605 }
606 if ( 606 if (
607 (type_code != comment) && 607 (type_code != comment) &&
608 (type_code != newline) && 608 (type_code != newline) &&
609 (type_code != preprocessing) && 609 (type_code != preprocessing) &&
610 (type_code != form_feed)) { 610 (type_code != form_feed)) {
611 if (force_nl && 611 if (force_nl &&
612 (type_code != semicolon) && 612 (type_code != semicolon) &&
613 (type_code != lbrace || !opt.btype_2)) { 613 (type_code != lbrace || !opt.btype_2)) {
614 /* we should force a broken line here */ 614 /* we should force a broken line here */
615 if (opt.verbose) 615 if (opt.verbose)
616 diag(0, "Line broken"); 616 diag(0, "Line broken");
617 dump_line(); 617 dump_line();
618 ps.want_blank = false; /* dont insert blank at line start */ 618 ps.want_blank = false; /* dont insert blank at line start */
619 force_nl = false; 619 force_nl = false;
620 } 620 }
621 ps.in_stmt = true; /* turn on flag which causes an extra level of 621 ps.in_stmt = true; /* turn on flag which causes an extra level of
622 * indentation. this is turned off by a ; or 622 * indentation. this is turned off by a ; or
623 * '}' */ 623 * '}' */
624 if (s_com != e_com) { /* the turkey has embedded a comment 624 if (s_com != e_com) { /* the turkey has embedded a comment
625 * in a line. fix it */ 625 * in a line. fix it */
626 int len = e_com - s_com; 626 int len = e_com - s_com;
627 627
628 check_size_code(len + 3); 628 check_size_code(len + 3);
629 *e_code++ = ' '; 629 *e_code++ = ' ';
630 memcpy(e_code, s_com, len); 630 memcpy(e_code, s_com, len);
631 e_code += len; 631 e_code += len;
632 *e_code++ = ' '; 632 *e_code++ = ' ';
633 *e_code = '\0'; /* null terminate code sect */ 633 *e_code = '\0'; /* null terminate code sect */
634 ps.want_blank = false; 634 ps.want_blank = false;
635 e_com = s_com; 635 e_com = s_com;
636 } 636 }
637 } else if (type_code != comment) /* preserve force_nl thru a comment */ 637 } else if (type_code != comment) /* preserve force_nl thru a comment */
638 force_nl = false; /* cancel forced newline after newline, form 638 force_nl = false; /* cancel forced newline after newline, form
639 * feed, etc */ 639 * feed, etc */
640 640
641 641
642 642
643 /*-----------------------------------------------------*\ 643 /*-----------------------------------------------------*\
644 | do switch on type of token scanned | 644 | do switch on type of token scanned |
645 \*-----------------------------------------------------*/ 645 \*-----------------------------------------------------*/
646 check_size_code(3); /* maximum number of increments of e_code 646 check_size_code(3); /* maximum number of increments of e_code
647 * before the next check_size_code or 647 * before the next check_size_code or
648 * dump_line() is 2. After that there's the 648 * dump_line() is 2. After that there's the
649 * final increment for the null character. */ 649 * final increment for the null character. */
650 switch (type_code) { /* now, decide what to do with the token */ 650 switch (type_code) { /* now, decide what to do with the token */
651 651
652 case form_feed: /* found a form feed in line */ 652 case form_feed: /* found a form feed in line */
653 ps.use_ff = true; /* a form feed is treated much like a newline */ 653 ps.use_ff = true; /* a form feed is treated much like a newline */
654 dump_line(); 654 dump_line();
655 ps.want_blank = false; 655 ps.want_blank = false;
656 break; 656 break;
657 657
658 case newline: 658 case newline:
659 if (ps.last_token != comma || ps.p_l_follow > 0 659 if (ps.last_token != comma || ps.p_l_follow > 0
660 || !opt.leave_comma || ps.block_init || !break_comma || s_com != e_com) { 660 || !opt.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
661 dump_line(); 661 dump_line();
662 ps.want_blank = false; 662 ps.want_blank = false;
663 } 663 }
664 ++line_no; /* keep track of input line number */ 664 ++line_no; /* keep track of input line number */
665 break; 665 break;
666 666
667 case lparen: /* got a '(' or '[' */ 667 case lparen: /* got a '(' or '[' */
668 /* count parens to make Healy happy */ 668 /* count parens to make Healy happy */
669 if (++ps.p_l_follow == nitems(ps.paren_indents)) { 669 if (++ps.p_l_follow == nitems(ps.paren_indents)) {
670 diag(0, "Reached internal limit of %zu unclosed parens", 670 diag(0, "Reached internal limit of %zu unclosed parens",
671 nitems(ps.paren_indents)); 671 nitems(ps.paren_indents));
672 ps.p_l_follow--; 672 ps.p_l_follow--;
673 } 673 }
674 if (*token == '[') 674 if (*token == '[')
675 /* not a function pointer declaration or a function call */; 675 /* not a function pointer declaration or a function call */;
676 else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent && 676 else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent &&
677 ps.procname[0] == '\0' && ps.paren_level == 0) { 677 ps.procname[0] == '\0' && ps.paren_level == 0) {
678 /* function pointer declarations */ 678 /* function pointer declarations */
679 indent_declaration(dec_ind, tabs_to_var); 679 indent_declaration(dec_ind, tabs_to_var);
680 ps.dumped_decl_indent = true; 680 ps.dumped_decl_indent = true;
681 } else if (ps.want_blank && 681 } else if (ps.want_blank &&
682 ((ps.last_token != ident && ps.last_token != funcname) || 682 ((ps.last_token != ident && ps.last_token != funcname) ||
683 opt.proc_calls_space || 683 opt.proc_calls_space ||
684 (ps.keyword == rw_sizeof ? opt.Bill_Shannon : 684 (ps.keyword == rw_sizeof ? opt.Bill_Shannon :
685 ps.keyword != rw_0 && ps.keyword != rw_offsetof))) 685 ps.keyword != rw_0 && ps.keyword != rw_offsetof)))
686 *e_code++ = ' '; 686 *e_code++ = ' ';
687 ps.want_blank = false; 687 ps.want_blank = false;
688 *e_code++ = token[0]; 688 *e_code++ = token[0];
689 ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1; 689 ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1;
690 if (sp_sw && ps.p_l_follow == 1 && opt.extra_expression_indent 690 if (sp_sw && ps.p_l_follow == 1 && opt.extra_expression_indent
691 && ps.paren_indents[0] < 2 * opt.ind_size) 691 && ps.paren_indents[0] < 2 * opt.ind_size)
692 ps.paren_indents[0] = 2 * opt.ind_size; 692 ps.paren_indents[0] = 2 * opt.ind_size;
693 if (ps.in_or_st && *token == '(' && ps.tos <= 2) { 693 if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
694 /* 694 /*
695 * this is a kluge to make sure that declarations will be 695 * this is a kluge to make sure that declarations will be
696 * aligned right if proc decl has an explicit type on it, i.e. 696 * aligned right if proc decl has an explicit type on it, i.e.
697 * "int a(x) {..." 697 * "int a(x) {..."
698 */ 698 */
699 parse(semicolon); /* I said this was a kluge... */ 699 parse(semicolon); /* I said this was a kluge... */
700 ps.in_or_st = false; /* turn off flag for structure decl or 700 ps.in_or_st = false; /* turn off flag for structure decl or
701 * initialization */ 701 * initialization */
702 } 702 }
703 /* parenthesized type following sizeof or offsetof is not a cast */ 703 /* parenthesized type following sizeof or offsetof is not a cast */
704 if (ps.keyword == rw_offsetof || ps.keyword == rw_sizeof) 704 if (ps.keyword == rw_offsetof || ps.keyword == rw_sizeof)
705 ps.not_cast_mask |= 1 << ps.p_l_follow; 705 ps.not_cast_mask |= 1 << ps.p_l_follow;
706 break; 706 break;
707 707
708 case rparen: /* got a ')' or ']' */ 708 case rparen: /* got a ')' or ']' */
709 if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) { 709 if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) {
710 ps.last_u_d = true; 710 ps.last_u_d = true;
711 ps.cast_mask &= (1 << ps.p_l_follow) - 1; 711 ps.cast_mask &= (1 << ps.p_l_follow) - 1;
712 ps.want_blank = opt.space_after_cast; 712 ps.want_blank = opt.space_after_cast;
713 } else 713 } else
714 ps.want_blank = true; 714 ps.want_blank = true;
715 ps.not_cast_mask &= (1 << ps.p_l_follow) - 1; 715 ps.not_cast_mask &= (1 << ps.p_l_follow) - 1;
716 if (--ps.p_l_follow < 0) { 716 if (--ps.p_l_follow < 0) {
717 ps.p_l_follow = 0; 717 ps.p_l_follow = 0;
718 diag(0, "Extra %c", *token); 718 diag(0, "Extra %c", *token);
719 } 719 }
720 if (e_code == s_code) /* if the paren starts the line */ 720 if (e_code == s_code) /* if the paren starts the line */
721 ps.paren_level = ps.p_l_follow; /* then indent it */ 721 ps.paren_level = ps.p_l_follow; /* then indent it */
722 722
723 *e_code++ = token[0]; 723 *e_code++ = token[0];
724 724
725 if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if 725 if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if
726 * (...), or some such */ 726 * (...), or some such */
727 sp_sw = false; 727 sp_sw = false;
728 force_nl = true; /* must force newline after if */ 728 force_nl = true; /* must force newline after if */
729 ps.last_u_d = true; /* inform lexi that a following 729 ps.last_u_d = true; /* inform lexi that a following
730 * operator is unary */ 730 * operator is unary */
731 ps.in_stmt = false; /* dont use stmt continuation 731 ps.in_stmt = false; /* dont use stmt continuation
732 * indentation */ 732 * indentation */
733 733
734 parse(hd_type); /* let parser worry about if, or whatever */ 734 parse(hd_type); /* let parser worry about if, or whatever */
735 } 735 }
736 ps.search_brace = opt.btype_2; /* this should ensure that 736 ps.search_brace = opt.btype_2; /* this should ensure that
737 * constructs such as main(){...} 737 * constructs such as main(){...}
738 * and int[]{...} have their braces 738 * and int[]{...} have their braces
739 * put in the right place */ 739 * put in the right place */
740 break; 740 break;
741 741
742 case unary_op: /* this could be any unary operation */ 742 case unary_op: /* this could be any unary operation */
743 if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init && 743 if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init &&
744 ps.procname[0] == '\0' && ps.paren_level == 0) { 744 ps.procname[0] == '\0' && ps.paren_level == 0) {
745 /* pointer declarations */ 745 /* pointer declarations */
746 746
747 /* 747 /*
748 * if this is a unary op in a declaration, we should indent 748 * if this is a unary op in a declaration, we should indent
749 * this token 749 * this token
750 */ 750 */
751 for (i = 0; token[i]; ++i) 751 for (i = 0; token[i]; ++i)
752 /* find length of token */; 752 /* find length of token */;
753 indent_declaration(dec_ind - i, tabs_to_var); 753 indent_declaration(dec_ind - i, tabs_to_var);
754 ps.dumped_decl_indent = true; 754 ps.dumped_decl_indent = true;
755 } else if (ps.want_blank) 755 } else if (ps.want_blank)
756 *e_code++ = ' '; 756 *e_code++ = ' ';
757 757
758 { 758 {
759 int len = e_token - s_token; 759 int len = e_token - s_token;
760 760
761 check_size_code(len); 761 check_size_code(len);
762 memcpy(e_code, token, len); 762 memcpy(e_code, token, len);
763 e_code += len; 763 e_code += len;
764 } 764 }
765 ps.want_blank = false; 765 ps.want_blank = false;
766 break; 766 break;
767 767
768 case binary_op: /* any binary operation */ 768 case binary_op: /* any binary operation */
769 { 769 {
770 int len = e_token - s_token; 770 int len = e_token - s_token;
771 771
772 check_size_code(len + 1); 772 check_size_code(len + 1);
773 if (ps.want_blank) 773 if (ps.want_blank)
774 *e_code++ = ' '; 774 *e_code++ = ' ';
775 memcpy(e_code, token, len); 775 memcpy(e_code, token, len);
776 e_code += len; 776 e_code += len;
777 } 777 }
778 ps.want_blank = true; 778 ps.want_blank = true;
779 break; 779 break;
780 780
781 case postfix_op: /* got a trailing ++ or -- */ 781 case postfix_op: /* got a trailing ++ or -- */
782 *e_code++ = token[0]; 782 *e_code++ = token[0];
783 *e_code++ = token[1]; 783 *e_code++ = token[1];
784 ps.want_blank = true; 784 ps.want_blank = true;
785 break; 785 break;
786 786
787 case question: /* got a ? */ 787 case question: /* got a ? */
788 squest++; /* this will be used when a later colon 788 squest++; /* this will be used when a later colon
789 * appears so we can distinguish the 789 * appears so we can distinguish the
790 * <c>?<n>:<n> construct */ 790 * <c>?<n>:<n> construct */
791 if (ps.want_blank) 791 if (ps.want_blank)
792 *e_code++ = ' '; 792 *e_code++ = ' ';
793 *e_code++ = '?'; 793 *e_code++ = '?';
794 ps.want_blank = true; 794 ps.want_blank = true;
795 break; 795 break;
796 796
797 case case_label: /* got word 'case' or 'default' */ 797 case case_label: /* got word 'case' or 'default' */
798 scase = true; /* so we can process the later colon properly */ 798 scase = true; /* so we can process the later colon properly */
799 goto copy_id; 799 goto copy_id;
800 800
801 case colon: /* got a ':' */ 801 case colon: /* got a ':' */
802 if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */ 802 if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */
803 --squest; 803 --squest;
804 if (ps.want_blank) 804 if (ps.want_blank)
805 *e_code++ = ' '; 805 *e_code++ = ' ';
806 *e_code++ = ':'; 806 *e_code++ = ':';
807 ps.want_blank = true; 807 ps.want_blank = true;
808 break; 808 break;
809 } 809 }
810 if (ps.in_or_st) { 810 if (ps.in_or_st) {
811 *e_code++ = ':'; 811 *e_code++ = ':';
812 ps.want_blank = false; 812 ps.want_blank = false;
813 break; 813 break;
814 } 814 }
815 ps.in_stmt = false; /* seeing a label does not imply we are in a 815 ps.in_stmt = false; /* seeing a label does not imply we are in a
816 * stmt */ 816 * stmt */
817 /* 817 /*
818 * turn everything so far into a label 818 * turn everything so far into a label
819 */ 819 */
820 { 820 {
821 int len = e_code - s_code; 821 int len = e_code - s_code;
822 822
823 check_size_label(len + 3); 823 check_size_label(len + 3);
824 memcpy(e_lab, s_code, len); 824 memcpy(e_lab, s_code, len);
825 e_lab += len; 825 e_lab += len;
826 *e_lab++ = ':'; 826 *e_lab++ = ':';
827 *e_lab = '\0'; 827 *e_lab = '\0';
828 e_code = s_code; 828 e_code = s_code;
829 } 829 }
830 force_nl = ps.pcase = scase; /* ps.pcase will be used by 830 force_nl = ps.pcase = scase; /* ps.pcase will be used by
831 * dump_line to decide how to 831 * dump_line to decide how to
832 * indent the label. force_nl 832 * indent the label. force_nl
833 * will force a case n: to be 833 * will force a case n: to be
834 * on a line by itself */ 834 * on a line by itself */
835 scase = false; 835 scase = false;
836 ps.want_blank = false; 836 ps.want_blank = false;
837 break; 837 break;
838 838
839 case semicolon: /* got a ';' */ 839 case semicolon: /* got a ';' */
840 if (ps.dec_nest == 0) 840 if (ps.dec_nest == 0)
841 ps.in_or_st = false; /* we are not in an initialization or 841 ps.in_or_st = false; /* we are not in an initialization or
842 * structure declaration */ 842 * structure declaration */
843 scase = false; /* these will only need resetting in an error */ 843 scase = false; /* these will only need resetting in an error */
844 squest = 0; 844 squest = 0;
845 if (ps.last_token == rparen) 845 if (ps.last_token == rparen)
846 ps.in_parameter_declaration = 0; 846 ps.in_parameter_declaration = 0;
847 ps.cast_mask = 0; 847 ps.cast_mask = 0;
848 ps.not_cast_mask = 0; 848 ps.not_cast_mask = 0;
849 ps.block_init = 0; 849 ps.block_init = 0;
850 ps.block_init_level = 0; 850 ps.block_init_level = 0;
851 ps.just_saw_decl--; 851 ps.just_saw_decl--;
852 852
853 if (ps.in_decl && s_code == e_code && !ps.block_init && 853 if (ps.in_decl && s_code == e_code && !ps.block_init &&
854 !ps.dumped_decl_indent && ps.paren_level == 0) { 854 !ps.dumped_decl_indent && ps.paren_level == 0) {
855 /* indent stray semicolons in declarations */ 855 /* indent stray semicolons in declarations */
856 indent_declaration(dec_ind - 1, tabs_to_var); 856 indent_declaration(dec_ind - 1, tabs_to_var);
857 ps.dumped_decl_indent = true; 857 ps.dumped_decl_indent = true;
858 } 858 }
859 859
860 ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level 860 ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level
861 * structure declaration, we 861 * structure declaration, we
862 * arent any more */ 862 * arent any more */
863 863
864 if ((!sp_sw || hd_type != for_exprs) && ps.p_l_follow > 0) { 864 if ((!sp_sw || hd_type != for_exprs) && ps.p_l_follow > 0) {
865 865
866 /* 866 /*
867 * This should be true iff there were unbalanced parens in the 867 * This should be true iff there were unbalanced parens in the
868 * stmt. It is a bit complicated, because the semicolon might 868 * stmt. It is a bit complicated, because the semicolon might
869 * be in a for stmt 869 * be in a for stmt
870 */ 870 */
871 diag(1, "Unbalanced parens"); 871 diag(1, "Unbalanced parens");
872 ps.p_l_follow = 0; 872 ps.p_l_follow = 0;
873 if (sp_sw) { /* this is a check for an if, while, etc. with 873 if (sp_sw) { /* this is a check for an if, while, etc. with
874 * unbalanced parens */ 874 * unbalanced parens */
875 sp_sw = false; 875 sp_sw = false;
876 parse(hd_type); /* dont lose the if, or whatever */ 876 parse(hd_type); /* dont lose the if, or whatever */
877 } 877 }
878 } 878 }
879 *e_code++ = ';'; 879 *e_code++ = ';';
880 ps.want_blank = true; 880 ps.want_blank = true;
881 ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the 881 ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the
882 * middle of a stmt */ 882 * middle of a stmt */
883 883
884 if (!sp_sw) { /* if not if for (;;) */ 884 if (!sp_sw) { /* if not if for (;;) */
885 parse(semicolon); /* let parser know about end of stmt */ 885 parse(semicolon); /* let parser know about end of stmt */
886 force_nl = true;/* force newline after an end of stmt */ 886 force_nl = true;/* force newline after an end of stmt */
887 } 887 }
888 break; 888 break;
889 889
890 case lbrace: /* got a '{' */ 890 case lbrace: /* got a '{' */
891 ps.in_stmt = false; /* dont indent the {} */ 891 ps.in_stmt = false; /* dont indent the {} */
892 if (!ps.block_init) 892 if (!ps.block_init)
893 force_nl = true;/* force other stuff on same line as '{' onto 893 force_nl = true;/* force other stuff on same line as '{' onto
894 * new line */ 894 * new line */
895 else if (ps.block_init_level <= 0) 895 else if (ps.block_init_level <= 0)
896 ps.block_init_level = 1; 896 ps.block_init_level = 1;
897 else 897 else
898 ps.block_init_level++; 898 ps.block_init_level++;
899 899
900 if (s_code != e_code && !ps.block_init) { 900 if (s_code != e_code && !ps.block_init) {
901 if (!opt.btype_2) { 901 if (!opt.btype_2) {
902 dump_line(); 902 dump_line();
903 ps.want_blank = false; 903 ps.want_blank = false;
904 } else if (ps.in_parameter_declaration && !ps.in_or_st) { 904 } else if (ps.in_parameter_declaration && !ps.in_or_st) {
905 ps.i_l_follow = 0; 905 ps.i_l_follow = 0;
906 if (opt.function_brace_split) { /* dump the line prior 906 if (opt.function_brace_split) { /* dump the line prior
907 * to the brace ... */ 907 * to the brace ... */
908 dump_line(); 908 dump_line();
909 ps.want_blank = false; 909 ps.want_blank = false;
910 } else /* add a space between the decl and brace */ 910 } else /* add a space between the decl and brace */
911 ps.want_blank = true; 911 ps.want_blank = true;
912 } 912 }
913 } 913 }
914 if (ps.in_parameter_declaration) 914 if (ps.in_parameter_declaration)
915 prefix_blankline_requested = 0; 915 prefix_blankline_requested = 0;
916 916
917 if (ps.p_l_follow > 0) { /* check for preceding unbalanced 917 if (ps.p_l_follow > 0) { /* check for preceding unbalanced
918 * parens */ 918 * parens */
919 diag(1, "Unbalanced parens"); 919 diag(1, "Unbalanced parens");
920 ps.p_l_follow = 0; 920 ps.p_l_follow = 0;
921 if (sp_sw) { /* check for unclosed if, for, etc. */ 921 if (sp_sw) { /* check for unclosed if, for, etc. */
922 sp_sw = false; 922 sp_sw = false;
923 parse(hd_type); 923 parse(hd_type);
924 ps.ind_level = ps.i_l_follow; 924 ps.ind_level = ps.i_l_follow;
925 } 925 }
926 } 926 }
927 if (s_code == e_code) 927 if (s_code == e_code)
928 ps.ind_stmt = false; /* dont put extra indentation on line 928 ps.ind_stmt = false; /* dont put extra indentation on line
929 * with '{' */ 929 * with '{' */
930 if (ps.in_decl && ps.in_or_st) { /* this is either a structure 930 if (ps.in_decl && ps.in_or_st) { /* this is either a structure
931 * declaration or an init */ 931 * declaration or an init */
932 di_stack[ps.dec_nest] = dec_ind; 932 di_stack[ps.dec_nest] = dec_ind;
933 if (++ps.dec_nest == nitems(di_stack)) { 933 if (++ps.dec_nest == nitems(di_stack)) {
934 diag(0, "Reached internal limit of %zu struct levels", 934 diag(0, "Reached internal limit of %zu struct levels",
935 nitems(di_stack)); 935 nitems(di_stack));
936 ps.dec_nest--; 936 ps.dec_nest--;
937 } 937 }
938 /* ? dec_ind = 0; */ 938 /* ? dec_ind = 0; */
939 } else { 939 } else {
940 ps.decl_on_line = false; /* we can't be in the middle of 940 ps.decl_on_line = false; /* we can't be in the middle of
941 * a declaration, so don't do 941 * a declaration, so don't do
942 * special indentation of 942 * special indentation of
943 * comments */ 943 * comments */
944 if (opt.blanklines_after_declarations_at_proctop 944 if (opt.blanklines_after_declarations_at_proctop
945 && ps.in_parameter_declaration) 945 && ps.in_parameter_declaration)
946 postfix_blankline_requested = 1; 946 postfix_blankline_requested = 1;
947 ps.in_parameter_declaration = 0; 947 ps.in_parameter_declaration = 0;
948 ps.in_decl = false; 948 ps.in_decl = false;
949 } 949 }
950 dec_ind = 0; 950 dec_ind = 0;
951 parse(lbrace); /* let parser know about this */ 951 parse(lbrace); /* let parser know about this */
952 if (ps.want_blank) /* put a blank before '{' if '{' is not at 952 if (ps.want_blank) /* put a blank before '{' if '{' is not at
953 * start of line */ 953 * start of line */
954 *e_code++ = ' '; 954 *e_code++ = ' ';
955 ps.want_blank = false; 955 ps.want_blank = false;
956 *e_code++ = '{'; 956 *e_code++ = '{';
957 ps.just_saw_decl = 0; 957 ps.just_saw_decl = 0;
958 break; 958 break;
959 959
960 case rbrace: /* got a '}' */ 960 case rbrace: /* got a '}' */
961 if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be 961 if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be
962 * omitted in 962 * omitted in
963 * declarations */ 963 * declarations */
964 parse(semicolon); 964 parse(semicolon);
965 if (ps.p_l_follow) {/* check for unclosed if, for, else. */ 965 if (ps.p_l_follow) {/* check for unclosed if, for, else. */
966 diag(1, "Unbalanced parens"); 966 diag(1, "Unbalanced parens");
967 ps.p_l_follow = 0; 967 ps.p_l_follow = 0;
968 sp_sw = false; 968 sp_sw = false;
969 } 969 }
970 ps.just_saw_decl = 0; 970 ps.just_saw_decl = 0;
971 ps.block_init_level--; 971 ps.block_init_level--;
972 if (s_code != e_code && !ps.block_init) { /* '}' must be first on 972 if (s_code != e_code && !ps.block_init) { /* '}' must be first on
973 * line */ 973 * line */
974 if (opt.verbose) 974 if (opt.verbose)
975 diag(0, "Line broken"); 975 diag(0, "Line broken");
976 dump_line(); 976 dump_line();
977 } 977 }
978 *e_code++ = '}'; 978 *e_code++ = '}';
979 ps.want_blank = true; 979 ps.want_blank = true;
980 ps.in_stmt = ps.ind_stmt = false; 980 ps.in_stmt = ps.ind_stmt = false;
981 if (ps.dec_nest > 0) { /* we are in multi-level structure 981 if (ps.dec_nest > 0) { /* we are in multi-level structure
982 * declaration */ 982 * declaration */
983 dec_ind = di_stack[--ps.dec_nest]; 983 dec_ind = di_stack[--ps.dec_nest];
984 if (ps.dec_nest == 0 && !ps.in_parameter_declaration) 984 if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
985 ps.just_saw_decl = 2; 985 ps.just_saw_decl = 2;
986 ps.in_decl = true; 986 ps.in_decl = true;
987 } 987 }
988 prefix_blankline_requested = 0; 988 prefix_blankline_requested = 0;
989 parse(rbrace); /* let parser know about this */ 989 parse(rbrace); /* let parser know about this */
990 ps.search_brace = opt.cuddle_else 990 ps.search_brace = opt.cuddle_else
991 && ps.p_stack[ps.tos] == if_expr_stmt 991 && ps.p_stack[ps.tos] == if_expr_stmt
992 && ps.il[ps.tos] >= ps.ind_level; 992 && ps.il[ps.tos] >= ps.ind_level;
993 if (ps.tos <= 1 && opt.blanklines_after_procs && ps.dec_nest <= 0) 993 if (ps.tos <= 1 && opt.blanklines_after_procs && ps.dec_nest <= 0)
994 postfix_blankline_requested = 1; 994 postfix_blankline_requested = 1;
995 break; 995 break;
996 996
997 case switch_expr: /* got keyword "switch" */ 997 case switch_expr: /* got keyword "switch" */
998 sp_sw = true; 998 sp_sw = true;
999 hd_type = switch_expr; /* keep this for when we have seen the 999 hd_type = switch_expr; /* keep this for when we have seen the
1000 * expression */ 1000 * expression */
1001 goto copy_id; /* go move the token into buffer */ 1001 goto copy_id; /* go move the token into buffer */
1002 1002
1003 case keyword_for_if_while: 1003 case keyword_for_if_while:
1004 sp_sw = true; /* the interesting stuff is done after the 1004 sp_sw = true; /* the interesting stuff is done after the
1005 * expression is scanned */ 1005 * expression is scanned */
1006 hd_type = (*token == 'i' ? if_expr : 1006 hd_type = (*token == 'i' ? if_expr :
1007 (*token == 'w' ? while_expr : for_exprs)); 1007 (*token == 'w' ? while_expr : for_exprs));
1008 1008
1009 /* 1009 /*
1010 * remember the type of header for later use by parser 1010 * remember the type of header for later use by parser
1011 */ 1011 */
1012 goto copy_id; /* copy the token into line */ 1012 goto copy_id; /* copy the token into line */
1013 1013
1014 case keyword_do_else: 1014 case keyword_do_else:
1015 ps.in_stmt = false; 1015 ps.in_stmt = false;
1016 if (*token == 'e') { 1016 if (*token == 'e') {
1017 if (e_code != s_code && (!opt.cuddle_else || e_code[-1] != '}')) { 1017 if (e_code != s_code && (!opt.cuddle_else || e_code[-1] != '}')) {
1018 if (opt.verbose) 1018 if (opt.verbose)
1019 diag(0, "Line broken"); 1019 diag(0, "Line broken");
1020 dump_line();/* make sure this starts a line */ 1020 dump_line();/* make sure this starts a line */
1021 ps.want_blank = false; 1021 ps.want_blank = false;
1022 } 1022 }
1023 force_nl = true;/* also, following stuff must go onto new line */ 1023 force_nl = true;/* also, following stuff must go onto new line */
1024 last_else = 1; 1024 last_else = 1;
1025 parse(keyword_else); 1025 parse(keyword_else);
1026 } else { 1026 } else {
1027 if (e_code != s_code) { /* make sure this starts a line */ 1027 if (e_code != s_code) { /* make sure this starts a line */
1028 if (opt.verbose) 1028 if (opt.verbose)
1029 diag(0, "Line broken"); 1029 diag(0, "Line broken");
1030 dump_line(); 1030 dump_line();
1031 ps.want_blank = false; 1031 ps.want_blank = false;
1032 } 1032 }
1033 force_nl = true;/* also, following stuff must go onto new line */ 1033 force_nl = true;/* also, following stuff must go onto new line */
1034 last_else = 0; 1034 last_else = 0;
1035 parse(keyword_do); 1035 parse(keyword_do);
1036 } 1036 }
1037 goto copy_id; /* move the token into line */ 1037 goto copy_id; /* move the token into line */
1038 1038
1039 case type_def: 1039 case type_def:
1040 case storage_class: 1040 case storage_class:
1041 prefix_blankline_requested = 0; 1041 prefix_blankline_requested = 0;
1042 goto copy_id; 1042 goto copy_id;
1043 1043
1044 case keyword_struct_union_enum: 1044 case keyword_struct_union_enum:
1045 if (ps.p_l_follow > 0) 1045 if (ps.p_l_follow > 0)
1046 goto copy_id; 1046 goto copy_id;
1047 /* FALLTHROUGH */ 1047 /* FALLTHROUGH */
1048 case decl: /* we have a declaration type (int, etc.) */ 1048 case decl: /* we have a declaration type (int, etc.) */
1049 parse(decl); /* let parser worry about indentation */ 1049 parse(decl); /* let parser worry about indentation */
1050 if (ps.last_token == rparen && ps.tos <= 1) { 1050 if (ps.last_token == rparen && ps.tos <= 1) {
1051 if (s_code != e_code) { 1051 if (s_code != e_code) {
1052 dump_line(); 1052 dump_line();
1053 ps.want_blank = 0; 1053 ps.want_blank = 0;
1054 } 1054 }
1055 } 1055 }
1056 if (ps.in_parameter_declaration && opt.indent_parameters && ps.dec_nest == 0) { 1056 if (ps.in_parameter_declaration && opt.indent_parameters && ps.dec_nest == 0) {
1057 ps.ind_level = ps.i_l_follow = 1; 1057 ps.ind_level = ps.i_l_follow = 1;
1058 ps.ind_stmt = 0; 1058 ps.ind_stmt = 0;
1059 } 1059 }
1060 ps.in_or_st = true; /* this might be a structure or initialization 1060 ps.in_or_st = true; /* this might be a structure or initialization
1061 * declaration */ 1061 * declaration */
1062 ps.in_decl = ps.decl_on_line = ps.last_token != type_def; 1062 ps.in_decl = ps.decl_on_line = ps.last_token != type_def;
1063 if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) 1063 if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
1064 ps.just_saw_decl = 2; 1064 ps.just_saw_decl = 2;
1065 prefix_blankline_requested = 0; 1065 prefix_blankline_requested = 0;
1066 for (i = 0; token[i++];); /* get length of token */ 1066 for (i = 0; token[i++];); /* get length of token */
1067 1067
1068 if (ps.ind_level == 0 || ps.dec_nest > 0) { 1068 if (ps.ind_level == 0 || ps.dec_nest > 0) {
1069 /* global variable or struct member in local variable */ 1069 /* global variable or struct member in local variable */
1070 dec_ind = opt.decl_indent > 0 ? opt.decl_indent : i; 1070 dec_ind = opt.decl_indent > 0 ? opt.decl_indent : i;
1071 tabs_to_var = (opt.use_tabs ? opt.decl_indent > 0 : 0); 1071 tabs_to_var = (opt.use_tabs ? opt.decl_indent > 0 : 0);
1072 } else { 1072 } else {
1073 /* local variable */ 1073 /* local variable */
1074 dec_ind = opt.local_decl_indent > 0 ? opt.local_decl_indent : i; 1074 dec_ind = opt.local_decl_indent > 0 ? opt.local_decl_indent : i;
1075 tabs_to_var = (opt.use_tabs ? opt.local_decl_indent > 0 : 0); 1075 tabs_to_var = (opt.use_tabs ? opt.local_decl_indent > 0 : 0);
1076 } 1076 }
1077 goto copy_id; 1077 goto copy_id;
1078 1078
1079 case funcname: 1079 case funcname:
1080 case ident: /* got an identifier or constant */ 1080 case ident: /* got an identifier or constant */
1081 if (ps.in_decl) { 1081 if (ps.in_decl) {
1082 if (type_code == funcname) { 1082 if (type_code == funcname) {
1083 ps.in_decl = false; 1083 ps.in_decl = false;
1084 if (opt.procnames_start_line && s_code != e_code) { 1084 if (opt.procnames_start_line && s_code != e_code) {
1085 *e_code = '\0'; 1085 *e_code = '\0';
1086 dump_line(); 1086 dump_line();
1087 } else if (ps.want_blank) { 1087 } else if (ps.want_blank) {
1088 *e_code++ = ' '; 1088 *e_code++ = ' ';
1089 } 1089 }
1090 ps.want_blank = false; 1090 ps.want_blank = false;
1091 } else if (!ps.block_init && !ps.dumped_decl_indent && 1091 } else if (!ps.block_init && !ps.dumped_decl_indent &&
1092 ps.paren_level == 0) { /* if we are in a declaration, we 1092 ps.paren_level == 0) { /* if we are in a declaration, we
1093 * must indent identifier */ 1093 * must indent identifier */
1094 indent_declaration(dec_ind, tabs_to_var); 1094 indent_declaration(dec_ind, tabs_to_var);
1095 ps.dumped_decl_indent = true; 1095 ps.dumped_decl_indent = true;
1096 ps.want_blank = false; 1096 ps.want_blank = false;
1097 } 1097 }
1098 } else if (sp_sw && ps.p_l_follow == 0) { 1098 } else if (sp_sw && ps.p_l_follow == 0) {
1099 sp_sw = false; 1099 sp_sw = false;
1100 force_nl = true; 1100 force_nl = true;
1101 ps.last_u_d = true; 1101 ps.last_u_d = true;
1102 ps.in_stmt = false; 1102 ps.in_stmt = false;
1103 parse(hd_type); 1103 parse(hd_type);
1104 } 1104 }
1105 copy_id: 1105 copy_id:
1106 { 1106 {
1107 int len = e_token - s_token; 1107 int len = e_token - s_token;
1108 1108
1109 check_size_code(len + 1); 1109 check_size_code(len + 1);
1110 if (ps.want_blank) 1110 if (ps.want_blank)
1111 *e_code++ = ' '; 1111 *e_code++ = ' ';
1112 memcpy(e_code, s_token, len); 1112 memcpy(e_code, s_token, len);
1113 e_code += len; 1113 e_code += len;
1114 } 1114 }
1115 if (type_code != funcname) 1115 if (type_code != funcname)
1116 ps.want_blank = true; 1116 ps.want_blank = true;
1117 break; 1117 break;
1118 1118
1119 case string_prefix: 1119 case string_prefix:
1120 { 1120 {
1121 int len = e_token - s_token; 1121 int len = e_token - s_token;
1122 1122
1123 check_size_code(len + 1); 1123 check_size_code(len + 1);
1124 if (ps.want_blank) 1124 if (ps.want_blank)
1125 *e_code++ = ' '; 1125 *e_code++ = ' ';
1126 memcpy(e_code, token, len); 1126 memcpy(e_code, token, len);
1127 e_code += len; 1127 e_code += len;
1128 } 1128 }
1129 ps.want_blank = false; 1129 ps.want_blank = false;
1130 break; 1130 break;
1131 1131
1132 case period: /* treat a period kind of like a binary 1132 case period: /* treat a period kind of like a binary
1133 * operation */ 1133 * operation */
1134 *e_code++ = '.'; /* move the period into line */ 1134 *e_code++ = '.'; /* move the period into line */
1135 ps.want_blank = false; /* dont put a blank after a period */ 1135 ps.want_blank = false; /* dont put a blank after a period */
1136 break; 1136 break;
1137 1137
1138 case comma: 1138 case comma:
1139 ps.want_blank = (s_code != e_code); /* only put blank after comma 1139 ps.want_blank = (s_code != e_code); /* only put blank after comma
1140 * if comma does not start the 1140 * if comma does not start the
1141 * line */ 1141 * line */
1142 if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init && 1142 if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init &&
1143 !ps.dumped_decl_indent && ps.paren_level == 0) { 1143 !ps.dumped_decl_indent && ps.paren_level == 0) {
1144 /* indent leading commas and not the actual identifiers */ 1144 /* indent leading commas and not the actual identifiers */
1145 indent_declaration(dec_ind - 1, tabs_to_var); 1145 indent_declaration(dec_ind - 1, tabs_to_var);
1146 ps.dumped_decl_indent = true; 1146 ps.dumped_decl_indent = true;
1147 } 1147 }
1148 *e_code++ = ','; 1148 *e_code++ = ',';
1149 if (ps.p_l_follow == 0) { 1149 if (ps.p_l_follow == 0) {
1150 if (ps.block_init_level <= 0) 1150 if (ps.block_init_level <= 0)
1151 ps.block_init = 0; 1151 ps.block_init = 0;
1152 if (break_comma && (!opt.leave_comma || 1152 if (break_comma && (!opt.leave_comma ||
1153 count_spaces_until(compute_code_column(), s_code, e_code) > 1153 count_spaces_until(compute_code_column(), s_code, e_code) >
1154 opt.max_col - opt.tabsize)) 1154 opt.max_col - opt.tabsize))
1155 force_nl = true; 1155 force_nl = true;
1156 } 1156 }
1157 break; 1157 break;
1158 1158
1159 case preprocessing: /* '#' */ 1159 case preprocessing: /* '#' */
1160 if ((s_com != e_com) || 1160 if ((s_com != e_com) ||
1161 (s_lab != e_lab) || 1161 (s_lab != e_lab) ||
1162 (s_code != e_code)) 1162 (s_code != e_code))
1163 dump_line(); 1163 dump_line();
1164 check_size_label(1); 1164 check_size_label(1);
1165 *e_lab++ = '#'; /* move whole line to 'label' buffer */ 1165 *e_lab++ = '#'; /* move whole line to 'label' buffer */
1166 { 1166 {
1167 int in_comment = 0; 1167 int in_comment = 0;
1168 int com_start = 0; 1168 int com_start = 0;
1169 char quote = 0; 1169 char quote = 0;
1170 int com_end = 0; 1170 int com_end = 0;
1171 1171
1172 while (*buf_ptr == ' ' || *buf_ptr == '\t') { 1172 while (*buf_ptr == ' ' || *buf_ptr == '\t') {
1173 buf_ptr++; 1173 buf_ptr++;
1174 if (buf_ptr >= buf_end) 1174 if (buf_ptr >= buf_end)
1175 fill_buffer(); 1175 fill_buffer();
1176 } 1176 }
1177 while (*buf_ptr != '\n' || (in_comment && !had_eof)) { 1177 while (*buf_ptr != '\n' || (in_comment && !had_eof)) {
1178 check_size_label(2); 1178 check_size_label(2);
1179 *e_lab = *buf_ptr++; 1179 *e_lab = *buf_ptr++;
1180 if (buf_ptr >= buf_end) 1180 if (buf_ptr >= buf_end)
1181 fill_buffer(); 1181 fill_buffer();
1182 switch (*e_lab++) { 1182 switch (*e_lab++) {
1183 case '\\': 1183 case '\\':
1184 if (!in_comment) { 1184 if (!in_comment) {
1185 *e_lab++ = *buf_ptr++; 1185 *e_lab++ = *buf_ptr++;
1186 if (buf_ptr >= buf_end) 1186 if (buf_ptr >= buf_end)
1187 fill_buffer(); 1187 fill_buffer();
1188 } 1188 }
1189 break; 1189 break;
1190 case '/': 1190 case '/':
1191 if (*buf_ptr == '*' && !in_comment && !quote) { 1191 if (*buf_ptr == '*' && !in_comment && !quote) {
1192 in_comment = 1; 1192 in_comment = 1;
1193 *e_lab++ = *buf_ptr++; 1193 *e_lab++ = *buf_ptr++;
1194 com_start = e_lab - s_lab - 2; 1194 com_start = e_lab - s_lab - 2;
1195 } 1195 }
1196 break; 1196 break;
1197 case '"': 1197 case '"':
1198 if (quote == '"') 1198 if (quote == '"')
1199 quote = 0; 1199 quote = 0;
1200 break; 1200 break;
1201 case '\'': 1201 case '\'':
1202 if (quote == '\'') 1202 if (quote == '\'')
1203 quote = 0; 1203 quote = 0;
1204 break; 1204 break;
1205 case '*': 1205 case '*':
1206 if (*buf_ptr == '/' && in_comment) { 1206 if (*buf_ptr == '/' && in_comment) {
1207 in_comment = 0; 1207 in_comment = 0;
1208 *e_lab++ = *buf_ptr++; 1208 *e_lab++ = *buf_ptr++;
1209 com_end = e_lab - s_lab; 1209 com_end = e_lab - s_lab;
1210 } 1210 }
1211 break; 1211 break;
1212 } 1212 }
1213 } 1213 }
1214 1214
1215 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) 1215 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
1216 e_lab--; 1216 e_lab--;
1217 if (e_lab - s_lab == com_end && bp_save == NULL) { 1217 if (e_lab - s_lab == com_end && bp_save == NULL) {
1218 /* comment on preprocessor line */ 1218 /* comment on preprocessor line */
1219 if (sc_end == NULL) { /* if this is the first comment, 1219 if (sc_end == NULL) { /* if this is the first comment,
1220 * we must set up the buffer */ 1220 * we must set up the buffer */
1221 save_com = sc_buf; 1221 save_com = sc_buf;
1222 sc_end = &save_com[0]; 1222 sc_end = &save_com[0];
1223 } else { 1223 } else {
1224 *sc_end++ = '\n'; /* add newline between 1224 *sc_end++ = '\n'; /* add newline between
1225 * comments */ 1225 * comments */
1226 *sc_end++ = ' '; 1226 *sc_end++ = ' ';
1227 --line_no; 1227 --line_no;
1228 } 1228 }
1229 if (sc_end - save_com + com_end - com_start > sc_size) 1229 if (sc_end - save_com + com_end - com_start > sc_size)
1230 errx(1, "input too long"); 1230 errx(1, "input too long");
1231 memmove(sc_end, s_lab + com_start, com_end - com_start); 1231 memmove(sc_end, s_lab + com_start, com_end - com_start);
1232 sc_end += com_end - com_start; 1232 sc_end += com_end - com_start;
1233 e_lab = s_lab + com_start; 1233 e_lab = s_lab + com_start;
1234 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) 1234 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
1235 e_lab--; 1235 e_lab--;
1236 bp_save = buf_ptr; /* save current input buffer */ 1236 bp_save = buf_ptr; /* save current input buffer */
1237 be_save = buf_end; 1237 be_save = buf_end;
1238 buf_ptr = save_com; /* fix so that subsequent calls to 1238 buf_ptr = save_com; /* fix so that subsequent calls to
1239 * lexi will take tokens out of 1239 * lexi will take tokens out of
1240 * save_com */ 1240 * save_com */
1241 *sc_end++ = ' '; /* add trailing blank, just in case */ 1241 *sc_end++ = ' '; /* add trailing blank, just in case */
1242 buf_end = sc_end; 1242 buf_end = sc_end;
1243 sc_end = NULL; 1243 sc_end = NULL;
1244 } 1244 }
1245 check_size_label(1); 1245 check_size_label(1);
1246 *e_lab = '\0'; /* null terminate line */ 1246 *e_lab = '\0'; /* null terminate line */
1247 ps.pcase = false; 1247 ps.pcase = false;
1248 } 1248 }
1249 1249
1250 if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */ 1250 if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */
1251 if ((size_t)ifdef_level < nitems(state_stack)) { 1251 if ((size_t)ifdef_level < nitems(state_stack)) {
1252 match_state[ifdef_level].tos = -1; 1252 match_state[ifdef_level].tos = -1;
1253 state_stack[ifdef_level++] = ps; 1253 state_stack[ifdef_level++] = ps;
1254 } else 1254 } else
1255 diag(1, "#if stack overflow"); 1255 diag(1, "#if stack overflow");
1256 } else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */ 1256 } else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */
1257 if (ifdef_level <= 0) 1257 if (ifdef_level <= 0)
1258 diag(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else"); 1258 diag(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else");
1259 else { 1259 else {
1260 match_state[ifdef_level - 1] = ps; 1260 match_state[ifdef_level - 1] = ps;
1261 ps = state_stack[ifdef_level - 1]; 1261 ps = state_stack[ifdef_level - 1];
1262 } 1262 }
1263 } else if (strncmp(s_lab, "#endif", 6) == 0) { 1263 } else if (strncmp(s_lab, "#endif", 6) == 0) {
1264 if (ifdef_level <= 0) 1264 if (ifdef_level <= 0)
1265 diag(1, "Unmatched #endif"); 1265 diag(1, "Unmatched #endif");
1266 else 1266 else
1267 ifdef_level--; 1267 ifdef_level--;
1268 } else { 1268 } else {
1269 static const struct directives { 1269 static const struct directives {
1270 int size; 1270 int size;
1271 const char *string; 1271 const char *string;
1272 } recognized[] = { 1272 } recognized[] = {
1273 {7, "include"}, 1273 {7, "include"},
1274 {6, "define"}, 1274 {6, "define"},
1275 {5, "undef"}, 1275 {5, "undef"},
1276 {4, "line"}, 1276 {4, "line"},
1277 {5, "error"}, 1277 {5, "error"},
1278 {6, "pragma"} 1278 {6, "pragma"}
1279 }; 1279 };
1280 int d = nitems(recognized); 1280 int d = nitems(recognized);
1281 while (--d >= 0) 1281 while (--d >= 0)
1282 if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0) 1282 if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0)
1283 break; 1283 break;
1284 if (d < 0) { 1284 if (d < 0) {
1285 diag(1, "Unrecognized cpp directive"); 1285 diag(1, "Unrecognized cpp directive");
1286 break; 1286 break;
1287 } 1287 }
1288 } 1288 }
1289 if (opt.blanklines_around_conditional_compilation) { 1289 if (opt.blanklines_around_conditional_compilation) {
1290 postfix_blankline_requested++; 1290 postfix_blankline_requested++;
1291 n_real_blanklines = 0; 1291 n_real_blanklines = 0;
1292 } else { 1292 } else {
1293 postfix_blankline_requested = 0; 1293 postfix_blankline_requested = 0;
1294 prefix_blankline_requested = 0; 1294 prefix_blankline_requested = 0;
1295 } 1295 }
1296 break; /* subsequent processing of the newline 1296 break; /* subsequent processing of the newline
1297 * character will cause the line to be printed */ 1297 * character will cause the line to be printed */
1298 1298
1299 case comment: /* we have gotten a / followed by * this is a biggie */ 1299 case comment: /* we have gotten a / followed by * this is a biggie */
1300 pr_comment(); 1300 pr_comment();
1301 break; 1301 break;
1302 1302
1303 default: 1303 default:
1304 break; 1304 break;
1305 } /* end of big switch stmt */ 1305 } /* end of big switch stmt */
1306 1306
1307 *e_code = '\0'; /* make sure code section is null terminated */ 1307 *e_code = '\0'; /* make sure code section is null terminated */
1308 if (type_code != comment && 1308 if (type_code != comment &&
1309 type_code != newline && 1309 type_code != newline &&
1310 type_code != preprocessing) 1310 type_code != preprocessing)
1311 ps.last_token = type_code; 1311 ps.last_token = type_code;
1312 } /* end of main while (1) loop */ 1312 } /* end of main while (1) loop */
1313} 1313}
1314 1314
1315/* 1315/*
1316 * copy input file to backup file if in_name is /blah/blah/blah/file, then 1316 * copy input file to backup file if in_name is /blah/blah/blah/file, then
1317 * backup file will be ".Bfile" then make the backup file the input and 1317 * backup file will be ".Bfile" then make the backup file the input and
1318 * original input file the output 1318 * original input file the output
1319 */ 1319 */
1320static void 1320static void
1321bakcopy(void) 1321bakcopy(void)
1322{ 1322{
1323 int n, 1323 int n,
1324 bakchn; 1324 bakchn;
1325 char buff[8 * 1024]; 1325 char buff[8 * 1024];
1326 const char *p; 1326 const char *p;
1327 1327
1328 /* construct file name .Bfile */ 1328 /* construct file name .Bfile */
1329 for (p = in_name; *p; p++); /* skip to end of string */ 1329 for (p = in_name; *p; p++); /* skip to end of string */
1330 while (p > in_name && *p != '/') /* find last '/' */ 1330 while (p > in_name && *p != '/') /* find last '/' */
1331 p--; 1331 p--;
1332 if (*p == '/') 1332 if (*p == '/')
1333 p++; 1333 p++;
1334 sprintf(bakfile, "%s%s", p, simple_backup_suffix); 1334 sprintf(bakfile, "%s%s", p, simple_backup_suffix);
1335 1335
1336 /* copy in_name to backup file */ 1336 /* copy in_name to backup file */
1337 bakchn = creat(bakfile, 0600); 1337 bakchn = creat(bakfile, 0600);
1338 if (bakchn < 0) 1338 if (bakchn < 0)
1339 err(1, "%s", bakfile); 1339 err(1, "%s", bakfile);
1340 while ((n = read(fileno(input), buff, sizeof(buff))) > 0) 1340 while ((n = read(fileno(input), buff, sizeof(buff))) > 0)
1341 if (write(bakchn, buff, n) != n) 1341 if (write(bakchn, buff, n) != n)
1342 err(1, "%s", bakfile); 1342 err(1, "%s", bakfile);
1343 if (n < 0) 1343 if (n < 0)
1344 err(1, "%s", in_name); 1344 err(1, "%s", in_name);
1345 close(bakchn); 1345 close(bakchn);
1346 fclose(input); 1346 fclose(input);
1347 1347
1348 /* re-open backup file as the input file */ 1348 /* re-open backup file as the input file */
1349 input = fopen(bakfile, "r"); 1349 input = fopen(bakfile, "r");
1350 if (input == NULL) 1350 if (input == NULL)
1351 err(1, "%s", bakfile); 1351 err(1, "%s", bakfile);
1352 /* now the original input file will be the output */ 1352 /* now the original input file will be the output */
1353 output = fopen(in_name, "w"); 1353 output = fopen(in_name, "w");
1354 if (output == NULL) { 1354 if (output == NULL) {
1355 unlink(bakfile); 1355 unlink(bakfile);
1356 err(1, "%s", in_name); 1356 err(1, "%s", in_name);
1357 } 1357 }
1358} 1358}
1359 1359
1360static void 1360static void
1361indent_declaration(int cur_dec_ind, int tabs_to_var) 1361indent_declaration(int cur_dec_ind, int tabs_to_var)
1362{ 1362{
1363 int pos = e_code - s_code; 1363 int pos = e_code - s_code;
1364 char *startpos = e_code; 1364 char *startpos = e_code;
1365 1365
1366 /* 1366 /*
1367 * get the tab math right for indentations that are not multiples of tabsize 1367 * get the tab math right for indentations that are not multiples of tabsize
1368 */ 1368 */
1369 if ((ps.ind_level * opt.ind_size) % opt.tabsize != 0) { 1369 if ((ps.ind_level * opt.ind_size) % opt.tabsize != 0) {
1370 pos += (ps.ind_level * opt.ind_size) % opt.tabsize; 1370 pos += (ps.ind_level * opt.ind_size) % opt.tabsize;
1371 cur_dec_ind += (ps.ind_level * opt.ind_size) % opt.tabsize; 1371 cur_dec_ind += (ps.ind_level * opt.ind_size) % opt.tabsize;
1372 } 1372 }
1373 if (tabs_to_var) { 1373 if (tabs_to_var) {
1374 int tpos; 1374 int tpos;
1375 1375
1376 check_size_code(cur_dec_ind / opt.tabsize); 1376 check_size_code(cur_dec_ind / opt.tabsize);
1377 while ((tpos = opt.tabsize * (1 + pos / opt.tabsize)) <= cur_dec_ind) { 1377 while ((tpos = opt.tabsize * (1 + pos / opt.tabsize)) <= cur_dec_ind) {
1378 *e_code++ = '\t'; 1378 *e_code++ = '\t';
1379 pos = tpos; 1379 pos = tpos;
1380 } 1380 }
1381 } 1381 }
1382 check_size_code(cur_dec_ind - pos + 1); 1382 check_size_code(cur_dec_ind - pos + 1);
1383 while (pos < cur_dec_ind) { 1383 while (pos < cur_dec_ind) {
1384 *e_code++ = ' '; 1384 *e_code++ = ' ';
1385 pos++; 1385 pos++;
1386 } 1386 }
1387 if (e_code == startpos && ps.want_blank) { 1387 if (e_code == startpos && ps.want_blank) {
1388 *e_code++ = ' '; 1388 *e_code++ = ' ';
1389 ps.want_blank = false; 1389 ps.want_blank = false;
1390 } 1390 }
1391} 1391}
 1392
 1393#ifdef debug
 1394void
 1395debug_printf(const char *fmt, ...)
 1396{
 1397 FILE *f = output == stdout ? stderr : stdout;
 1398 va_list ap;
 1399
 1400 va_start(ap, fmt);
 1401 vfprintf(f, fmt, ap);
 1402 va_end(ap);
 1403}
 1404
 1405void
 1406debug_println(const char *fmt, ...)
 1407{
 1408 FILE *f = output == stdout ? stderr : stdout;
 1409 va_list ap;
 1410
 1411 va_start(ap, fmt);
 1412 vfprintf(f, fmt, ap);
 1413 va_end(ap);
 1414 fprintf(f, "\n");
 1415}
 1416
 1417void
 1418debug_vis_range(const char *prefix, const char *s, const char *e,
 1419 const char *suffix)
 1420{
 1421 debug_printf("%s", prefix);
 1422 for (const char *p = s; p < e; p++) {
 1423 if (isprint((unsigned char)*p) && *p != '\\' && *p != '"')
 1424 debug_printf("%c", *p);
 1425 else if (*p == '\n')
 1426 debug_printf("\\n");
 1427 else if (*p == '\t')
 1428 debug_printf("\\t");
 1429 else
 1430 debug_printf("\\x%02x", *p);
 1431 }
 1432 debug_printf("%s", suffix);
 1433}
 1434#endif

cvs diff -r1.8 -r1.9 src/usr.bin/indent/indent.h (switch to unified diff)

--- src/usr.bin/indent/indent.h 2021/03/13 00:26:56 1.8
+++ src/usr.bin/indent/indent.h 2021/03/13 09:21:57 1.9
@@ -1,64 +1,71 @@ @@ -1,64 +1,71 @@
1/* $NetBSD: indent.h,v 1.8 2021/03/13 00:26:56 rillig Exp $ */ 1/* $NetBSD: indent.h,v 1.9 2021/03/13 09:21:57 rillig Exp $ */
2 2
3/*- 3/*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * 5 *
6 * Copyright (c) 2001 Jens Schweikhardt 6 * Copyright (c) 2001 Jens Schweikhardt
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE. 28 * SUCH DAMAGE.
29 */ 29 */
30 30
31#if 0 31#if 0
32#if defined(__NetBSD__) 32#if defined(__NetBSD__)
33__RCSID("$NetBSD: indent.h,v 1.8 2021/03/13 00:26:56 rillig Exp $"); 33__RCSID("$NetBSD: indent.h,v 1.9 2021/03/13 09:21:57 rillig Exp $");
34#elif defined(__FreeBSD__) 34#elif defined(__FreeBSD__)
35__FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 336333 2018-07-16 05:46:50Z pstef $"); 35__FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 336333 2018-07-16 05:46:50Z pstef $");
36#endif 36#endif
37#endif 37#endif
38 38
39#include "indent_codes.h" 39#include "indent_codes.h"
40#include "indent_globs.h" 40#include "indent_globs.h"
41 41
42#ifndef nitems 42#ifndef nitems
43#define nitems(array) (sizeof (array) / sizeof (array[0])) 43#define nitems(array) (sizeof (array) / sizeof (array[0]))
44#endif 44#endif
45 45
46void add_typename(const char *); 46void add_typename(const char *);
47void alloc_typenames(void); 47void alloc_typenames(void);
48int compute_code_column(void); 48int compute_code_column(void);
49int compute_label_column(void); 49int compute_label_column(void);
50int count_spaces(int, const char *); 50int count_spaces(int, const char *);
51int count_spaces_until(int, const char *, const char *); 51int count_spaces_until(int, const char *, const char *);
52void init_constant_tt(void); 52void init_constant_tt(void);
53#ifdef debug 53#ifdef debug
 54void debug_vis_range(const char *, const char *, const char *, const char *);
 55void debug_printf(const char *, ...) __printflike(1, 2);
 56void debug_println(const char *, ...) __printflike(1, 2);
54const char *token_type_name(token_type); 57const char *token_type_name(token_type);
 58#else
 59#define debug_printf(fmt, ...) do { } while (false)
 60#define debug_println(fmt, ...) do { } while (false)
 61#define debug_vis_range(prefix, s, e, suffix) do { } while (false)
55#endif 62#endif
56token_type lexi(struct parser_state *); 63token_type lexi(struct parser_state *);
57void diag(int, const char *, ...) __printflike(2, 3); 64void diag(int, const char *, ...) __printflike(2, 3);
58void dump_line(void); 65void dump_line(void);
59void fill_buffer(void); 66void fill_buffer(void);
60void parse(token_type); 67void parse(token_type);
61void pr_comment(void); 68void pr_comment(void);
62void set_defaults(void); 69void set_defaults(void);
63void set_option(char *); 70void set_option(char *);
64void set_profile(const char *); 71void set_profile(const char *);

cvs diff -r1.35 -r1.36 src/usr.bin/indent/io.c (switch to unified diff)

--- src/usr.bin/indent/io.c 2021/03/13 09:06:12 1.35
+++ src/usr.bin/indent/io.c 2021/03/13 09:21:57 1.36
@@ -1,465 +1,481 @@ @@ -1,465 +1,481 @@
1/* $NetBSD: io.c,v 1.35 2021/03/13 09:06:12 rillig Exp $ */ 1/* $NetBSD: io.c,v 1.36 2021/03/13 09:21:57 rillig Exp $ */
2 2
3/*- 3/*-
4 * SPDX-License-Identifier: BSD-4-Clause 4 * SPDX-License-Identifier: BSD-4-Clause
5 * 5 *
6 * Copyright (c) 1985 Sun Microsystems, Inc. 6 * Copyright (c) 1985 Sun Microsystems, Inc.
7 * Copyright (c) 1980, 1993 7 * Copyright (c) 1980, 1993
8 * The Regents of the University of California. All rights reserved. 8 * The Regents of the University of California. All rights reserved.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software 19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement: 20 * must display the following acknowledgement:
21 * This product includes software developed by the University of 21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors. 22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors 23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software 24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission. 25 * without specific prior written permission.
26 * 26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE. 37 * SUCH DAMAGE.
38 */ 38 */
39 39
40#if 0 40#if 0
41#ifndef lint 41#ifndef lint
42static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; 42static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93";
43#endif /* not lint */ 43#endif /* not lint */
44#endif 44#endif
45 45
46#include <sys/cdefs.h> 46#include <sys/cdefs.h>
47#ifndef lint 47#ifndef lint
48#if defined(__NetBSD__) 48#if defined(__NetBSD__)
49__RCSID("$NetBSD: io.c,v 1.35 2021/03/13 09:06:12 rillig Exp $"); 49__RCSID("$NetBSD: io.c,v 1.36 2021/03/13 09:21:57 rillig Exp $");
50#elif defined(__FreeBSD__) 50#elif defined(__FreeBSD__)
51__FBSDID("$FreeBSD: head/usr.bin/indent/io.c 334927 2018-06-10 16:44:18Z pstef $"); 51__FBSDID("$FreeBSD: head/usr.bin/indent/io.c 334927 2018-06-10 16:44:18Z pstef $");
52#endif 52#endif
53#endif 53#endif
54 54
55#include <ctype.h> 55#include <ctype.h>
56#include <err.h> 56#include <err.h>
57#include <stdio.h> 57#include <stdio.h>
58#include <stdlib.h> 58#include <stdlib.h>
59#include <string.h> 59#include <string.h>
60#include <stdarg.h> 60#include <stdarg.h>
61 61
62#include "indent.h" 62#include "indent.h"
63 63
64int comment_open; 64int comment_open;
65static int paren_indent; 65static int paren_indent;
66 66
67static void 67static void
68output_char(char ch) 68output_char(char ch)
69{ 69{
70 fputc(ch, output); 70 fputc(ch, output);
 71 debug_vis_range("output_char '", &ch, &ch + 1, "'\n");
71} 72}
72 73
73static void 74static void
74output_range(const char *s, const char *e) 75output_range(const char *s, const char *e)
75{ 76{
76 fwrite(s, 1, (size_t)(e - s), output); 77 fwrite(s, 1, (size_t)(e - s), output);
 78 debug_vis_range("output_range \"", s, e, "\"\n");
77} 79}
78 80
79static inline void 81static inline void
80output_string(const char *s) 82output_string(const char *s)
81{ 83{
82 output_range(s, s + strlen(s)); 84 output_range(s, s + strlen(s));
83} 85}
84 86
85static int 87static int
86output_indent(int old_ind, int new_ind) 88output_indent(int old_ind, int new_ind)
87{ 89{
88 int ind = old_ind; 90 int ind = old_ind;
89 91
90 if (opt.use_tabs) { 92 if (opt.use_tabs) {
91 int tabsize = opt.tabsize; 93 int tabsize = opt.tabsize;
92 int n = new_ind / tabsize - ind / tabsize; 94 int n = new_ind / tabsize - ind / tabsize;
93 if (n > 0) 95 if (n > 0)
94 ind -= ind % tabsize; 96 ind -= ind % tabsize;
95 for (int i = 0; i < n; i++) { 97 for (int i = 0; i < n; i++) {
96 output_char('\t'); 98 fputc('\t', output);
97 ind += tabsize; 99 ind += tabsize;
98 } 100 }
99 } 101 }
100 102
101 for (; ind < new_ind; ind++) 103 for (; ind < new_ind; ind++)
102 output_char(' '); 104 fputc(' ', output);
103 105
 106 debug_println("output_indent %d", ind);
104 return ind; 107 return ind;
105} 108}
106 109
107/* 110/*
108 * dump_line is the routine that actually effects the printing of the new 111 * dump_line is the routine that actually effects the printing of the new
109 * source. It prints the label section, followed by the code section with 112 * source. It prints the label section, followed by the code section with
110 * the appropriate nesting level, followed by any comments. 113 * the appropriate nesting level, followed by any comments.
111 */ 114 */
112void 115void
113dump_line(void) 116dump_line(void)
114{ 117{
115 int cur_col, target_col; 118 int cur_col, target_col;
116 static int not_first_line; 119 static int not_first_line;
117 120
118 if (ps.procname[0]) { 121 if (ps.procname[0]) {
119 ps.ind_level = 0; 122 ps.ind_level = 0;
120 ps.procname[0] = 0; 123 ps.procname[0] = 0;
121 } 124 }
122 125
123 if (s_code == e_code && s_lab == e_lab && s_com == e_com) { 126 if (s_code == e_code && s_lab == e_lab && s_com == e_com) {
124 if (suppress_blanklines > 0) 127 if (suppress_blanklines > 0)
125 suppress_blanklines--; 128 suppress_blanklines--;
126 else { 129 else {
127 ps.bl_line = true; 130 ps.bl_line = true;
128 n_real_blanklines++; 131 n_real_blanklines++;
129 } 132 }
130 } else if (!inhibit_formatting) { 133 } else if (!inhibit_formatting) {
131 suppress_blanklines = 0; 134 suppress_blanklines = 0;
132 ps.bl_line = false; 135 ps.bl_line = false;
133 if (prefix_blankline_requested && not_first_line) { 136 if (prefix_blankline_requested && not_first_line) {
134 if (opt.swallow_optional_blanklines) { 137 if (opt.swallow_optional_blanklines) {
135 if (n_real_blanklines == 1) 138 if (n_real_blanklines == 1)
136 n_real_blanklines = 0; 139 n_real_blanklines = 0;
137 } else { 140 } else {
138 if (n_real_blanklines == 0) 141 if (n_real_blanklines == 0)
139 n_real_blanklines = 1; 142 n_real_blanklines = 1;
140 } 143 }
141 } 144 }
142 while (--n_real_blanklines >= 0) 145 while (--n_real_blanklines >= 0)
143 output_char('\n'); 146 output_char('\n');
144 n_real_blanklines = 0; 147 n_real_blanklines = 0;
145 if (ps.ind_level == 0) 148 if (ps.ind_level == 0)
146 ps.ind_stmt = 0; /* this is a class A kludge. dont do 149 ps.ind_stmt = 0; /* this is a class A kludge. dont do
147 * additional statement indentation if we are 150 * additional statement indentation if we are
148 * at bracket level 0 */ 151 * at bracket level 0 */
149 152
150 if (e_lab != s_lab || e_code != s_code) 153 if (e_lab != s_lab || e_code != s_code)
151 ++code_lines; /* keep count of lines with code */ 154 ++code_lines; /* keep count of lines with code */
152 155
153 156
154 if (e_lab != s_lab) { /* print lab, if any */ 157 if (e_lab != s_lab) { /* print lab, if any */
155 if (comment_open) { 158 if (comment_open) {
156 comment_open = 0; 159 comment_open = 0;
157 output_string(".*/\n"); 160 output_string(".*/\n");
158 } 161 }
159 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) 162 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
160 e_lab--; 163 e_lab--;
161 *e_lab = '\0'; 164 *e_lab = '\0';
162 cur_col = 1 + output_indent(0, compute_label_column() - 1); 165 cur_col = 1 + output_indent(0, compute_label_column() - 1);
163 if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 166 if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0
164 || strncmp(s_lab, "#endif", 6) == 0)) { 167 || strncmp(s_lab, "#endif", 6) == 0)) {
165 char *s = s_lab; 168 char *s = s_lab;
166 if (e_lab[-1] == '\n') e_lab--; 169 if (e_lab[-1] == '\n') e_lab--;
167 do { 170 do {
168 output_char(*s++); 171 output_char(*s++);
169 } while (s < e_lab && 'a' <= *s && *s <= 'z'); 172 } while (s < e_lab && 'a' <= *s && *s <= 'z');
170 while ((*s == ' ' || *s == '\t') && s < e_lab) 173 while ((*s == ' ' || *s == '\t') && s < e_lab)
171 s++; 174 s++;
172 if (s < e_lab) { 175 if (s < e_lab) {
173 if (s[0] == '/' && s[1] == '*') { 176 if (s[0] == '/' && s[1] == '*') {
174 output_char('\t'); 177 output_char('\t');
175 output_range(s, e_lab); 178 output_range(s, e_lab);
176 } else { 179 } else {
177 output_string("\t/* "); 180 output_string("\t/* ");
178 output_range(s, e_lab); 181 output_range(s, e_lab);
179 output_string(" */"); 182 output_string(" */");
180 } 183 }
181 } 184 }
182 } else 185 } else
183 output_range(s_lab, e_lab); 186 output_range(s_lab, e_lab);
184 cur_col = count_spaces(cur_col, s_lab); 187 cur_col = count_spaces(cur_col, s_lab);
185 } else 188 } else
186 cur_col = 1; /* there is no label section */ 189 cur_col = 1; /* there is no label section */
187 190
188 ps.pcase = false; 191 ps.pcase = false;
189 192
190 if (s_code != e_code) { /* print code section, if any */ 193 if (s_code != e_code) { /* print code section, if any */
191 if (comment_open) { 194 if (comment_open) {
192 comment_open = 0; 195 comment_open = 0;
193 output_string(".*/\n"); 196 output_string(".*/\n");
194 } 197 }
195 target_col = compute_code_column(); 198 target_col = compute_code_column();
196 { 199 {
197 int i; 200 int i;
198 201
199 for (i = 0; i < ps.p_l_follow; i++) 202 for (i = 0; i < ps.p_l_follow; i++) {
200 if (ps.paren_indents[i] >= 0) 203 if (ps.paren_indents[i] >= 0) {
201 ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); 204 int ind = ps.paren_indents[i];
 205 /*
 206 * XXX: this mix of 'indent' and 'column' smells like
 207 * an off-by-one error.
 208 */
 209 ps.paren_indents[i] = -(ind + target_col);
 210 debug_println(
 211 "setting pi[%d] from %d to %d for column %d",
 212 i, ind, ps.paren_indents[i], target_col);
 213 }
 214 }
202 } 215 }
203 cur_col = 1 + output_indent(cur_col - 1, target_col - 1); 216 cur_col = 1 + output_indent(cur_col - 1, target_col - 1);
204 output_range(s_code, e_code); 217 output_range(s_code, e_code);
205 cur_col = count_spaces(cur_col, s_code); 218 cur_col = count_spaces(cur_col, s_code);
206 } 219 }
207 if (s_com != e_com) { /* print comment, if any */ 220 if (s_com != e_com) { /* print comment, if any */
208 int target = ps.com_col; 221 int target = ps.com_col;
209 char *com_st = s_com; 222 char *com_st = s_com;
210 223
211 target += ps.comment_delta; 224 target += ps.comment_delta;
212 while (*com_st == '\t') /* consider original indentation in 225 while (*com_st == '\t') /* consider original indentation in
213 * case this is a box comment */ 226 * case this is a box comment */
214 com_st++, target += opt.tabsize; 227 com_st++, target += opt.tabsize;
215 while (target <= 0) 228 while (target <= 0)
216 if (*com_st == ' ') 229 if (*com_st == ' ')
217 target++, com_st++; 230 target++, com_st++;
218 else if (*com_st == '\t') { 231 else if (*com_st == '\t') {
219 target = opt.tabsize * (1 + (target - 1) / opt.tabsize) + 1; 232 target = opt.tabsize * (1 + (target - 1) / opt.tabsize) + 1;
220 com_st++; 233 com_st++;
221 } else 234 } else
222 target = 1; 235 target = 1;
223 if (cur_col > target) { /* if comment can't fit on this line, 236 if (cur_col > target) { /* if comment can't fit on this line,
224 * put it on next line */ 237 * put it on next line */
225 output_char('\n'); 238 output_char('\n');
226 cur_col = 1; 239 cur_col = 1;
227 ++ps.out_lines; 240 ++ps.out_lines;
228 } 241 }
229 while (e_com > com_st && isspace((unsigned char)e_com[-1])) 242 while (e_com > com_st && isspace((unsigned char)e_com[-1]))
230 e_com--; 243 e_com--;
231 (void)output_indent(cur_col - 1, target - 1); 244 (void)output_indent(cur_col - 1, target - 1);
232 output_range(com_st, e_com); 245 output_range(com_st, e_com);
233 ps.comment_delta = ps.n_comment_delta; 246 ps.comment_delta = ps.n_comment_delta;
234 ++ps.com_lines; /* count lines with comments */ 247 ++ps.com_lines; /* count lines with comments */
235 } 248 }
236 if (ps.use_ff) 249 if (ps.use_ff)
237 output_char('\014'); 250 output_char('\014');
238 else 251 else
239 output_char('\n'); 252 output_char('\n');
240 ++ps.out_lines; 253 ++ps.out_lines;
241 if (ps.just_saw_decl == 1 && opt.blanklines_after_declarations) { 254 if (ps.just_saw_decl == 1 && opt.blanklines_after_declarations) {
242 prefix_blankline_requested = 1; 255 prefix_blankline_requested = 1;
243 ps.just_saw_decl = 0; 256 ps.just_saw_decl = 0;
244 } else 257 } else
245 prefix_blankline_requested = postfix_blankline_requested; 258 prefix_blankline_requested = postfix_blankline_requested;
246 postfix_blankline_requested = 0; 259 postfix_blankline_requested = 0;
247 } 260 }
248 261
249 /* keep blank lines after '//' comments */ 262 /* keep blank lines after '//' comments */
250 if (e_com - s_com > 1 && s_com[1] == '/') 263 if (e_com - s_com > 1 && s_com[1] == '/')
251 output_range(s_token, e_token); 264 output_range(s_token, e_token);
252 265
253 ps.decl_on_line = ps.in_decl; /* if we are in the middle of a 266 ps.decl_on_line = ps.in_decl; /* if we are in the middle of a
254 * declaration, remember that fact for 267 * declaration, remember that fact for
255 * proper comment indentation */ 268 * proper comment indentation */
256 ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be 269 ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be
257 * indented if we have not 270 * indented if we have not
258 * completed this stmt and if 271 * completed this stmt and if
259 * we are not in the middle of 272 * we are not in the middle of
260 * a declaration */ 273 * a declaration */
261 ps.use_ff = false; 274 ps.use_ff = false;
262 ps.dumped_decl_indent = 0; 275 ps.dumped_decl_indent = 0;
263 *(e_lab = s_lab) = '\0'; /* reset buffers */ 276 *(e_lab = s_lab) = '\0'; /* reset buffers */
264 *(e_code = s_code) = '\0'; 277 *(e_code = s_code) = '\0';
265 *(e_com = s_com = combuf + 1) = '\0'; 278 *(e_com = s_com = combuf + 1) = '\0';
266 ps.ind_level = ps.i_l_follow; 279 ps.ind_level = ps.i_l_follow;
267 ps.paren_level = ps.p_l_follow; 280 ps.paren_level = ps.p_l_follow;
268 if (ps.paren_level > 0) 281 if (ps.paren_level > 0) {
 282 /* TODO: explain what negative indentation means */
269 paren_indent = -ps.paren_indents[ps.paren_level - 1]; 283 paren_indent = -ps.paren_indents[ps.paren_level - 1];
 284 debug_println("paren_indent is now %d", paren_indent);
 285 }
270 not_first_line = 1; 286 not_first_line = 1;
271} 287}
272 288
273int 289int
274compute_code_column(void) 290compute_code_column(void)
275{ 291{
276 int target_col = opt.ind_size * ps.ind_level + 1; 292 int target_col = opt.ind_size * ps.ind_level + 1;
277 293
278 if (ps.paren_level) { 294 if (ps.paren_level) {
279 if (!opt.lineup_to_parens) 295 if (!opt.lineup_to_parens)
280 target_col += opt.continuation_indent * 296 target_col += opt.continuation_indent *
281 (2 * opt.continuation_indent == opt.ind_size ? 1 : ps.paren_level); 297 (2 * opt.continuation_indent == opt.ind_size ? 1 : ps.paren_level);
282 else if (opt.lineup_to_parens_always) 298 else if (opt.lineup_to_parens_always)
283 target_col = paren_indent; 299 target_col = paren_indent;
284 else { 300 else {
285 int w; 301 int w;
286 int t = paren_indent; 302 int t = paren_indent;
287 303
288 if ((w = count_spaces(t, s_code) - opt.max_col) > 0 304 if ((w = count_spaces(t, s_code) - opt.max_col) > 0
289 && count_spaces(target_col, s_code) <= opt.max_col) { 305 && count_spaces(target_col, s_code) <= opt.max_col) {
290 t -= w + 1; 306 t -= w + 1;
291 if (t > target_col) 307 if (t > target_col)
292 target_col = t; 308 target_col = t;
293 } else 309 } else
294 target_col = t; 310 target_col = t;
295 } 311 }
296 } else if (ps.ind_stmt) 312 } else if (ps.ind_stmt)
297 target_col += opt.continuation_indent; 313 target_col += opt.continuation_indent;
298 return target_col; 314 return target_col;
299} 315}
300 316
301int 317int
302compute_label_column(void) 318compute_label_column(void)
303{ 319{
304 return 320 return
305 ps.pcase ? (int) (case_ind * opt.ind_size) + 1 321 ps.pcase ? (int) (case_ind * opt.ind_size) + 1
306 : *s_lab == '#' ? 1 322 : *s_lab == '#' ? 1
307 : opt.ind_size * (ps.ind_level - label_offset) + 1; 323 : opt.ind_size * (ps.ind_level - label_offset) + 1;
308} 324}
309 325
310 326
311/* 327/*
312 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 328 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
313 * 329 *
314 * All rights reserved 330 * All rights reserved
315 * 331 *
316 * FUNCTION: Reads one block of input into the input buffer 332 * FUNCTION: Reads one block of input into the input buffer
317 */ 333 */
318void 334void
319fill_buffer(void) 335fill_buffer(void)
320{ /* this routine reads stuff from the input */ 336{ /* this routine reads stuff from the input */
321 char *p; 337 char *p;
322 int i; 338 int i;
323 FILE *f = input; 339 FILE *f = input;
324 340
325 if (bp_save != NULL) { /* there is a partly filled input buffer left */ 341 if (bp_save != NULL) { /* there is a partly filled input buffer left */
326 buf_ptr = bp_save; /* do not read anything, just switch buffers */ 342 buf_ptr = bp_save; /* do not read anything, just switch buffers */
327 buf_end = be_save; 343 buf_end = be_save;
328 bp_save = be_save = NULL; 344 bp_save = be_save = NULL;
329 if (buf_ptr < buf_end) 345 if (buf_ptr < buf_end)
330 return; /* only return if there is really something in 346 return; /* only return if there is really something in
331 * this buffer */ 347 * this buffer */
332 } 348 }
333 for (p = in_buffer;;) { 349 for (p = in_buffer;;) {
334 if (p >= in_buffer_limit) { 350 if (p >= in_buffer_limit) {
335 int size = (in_buffer_limit - in_buffer) * 2 + 10; 351 int size = (in_buffer_limit - in_buffer) * 2 + 10;
336 int offset = p - in_buffer; 352 int offset = p - in_buffer;
337 in_buffer = realloc(in_buffer, size); 353 in_buffer = realloc(in_buffer, size);
338 if (in_buffer == NULL) 354 if (in_buffer == NULL)
339 errx(1, "input line too long"); 355 errx(1, "input line too long");
340 p = in_buffer + offset; 356 p = in_buffer + offset;
341 in_buffer_limit = in_buffer + size - 2; 357 in_buffer_limit = in_buffer + size - 2;
342 } 358 }
343 if ((i = getc(f)) == EOF) { 359 if ((i = getc(f)) == EOF) {
344 *p++ = ' '; 360 *p++ = ' ';
345 *p++ = '\n'; 361 *p++ = '\n';
346 had_eof = true; 362 had_eof = true;
347 break; 363 break;
348 } 364 }
349 if (i != '\0') 365 if (i != '\0')
350 *p++ = i; 366 *p++ = i;
351 if (i == '\n') 367 if (i == '\n')
352 break; 368 break;
353 } 369 }
354 buf_ptr = in_buffer; 370 buf_ptr = in_buffer;
355 buf_end = p; 371 buf_end = p;
356 if (p - in_buffer > 2 && p[-2] == '/' && p[-3] == '*') { 372 if (p - in_buffer > 2 && p[-2] == '/' && p[-3] == '*') {
357 if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) 373 if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
358 fill_buffer(); /* flush indent error message */ 374 fill_buffer(); /* flush indent error message */
359 else { 375 else {
360 int com = 0; 376 int com = 0;
361 377
362 p = in_buffer; 378 p = in_buffer;
363 while (*p == ' ' || *p == '\t') 379 while (*p == ' ' || *p == '\t')
364 p++; 380 p++;
365 if (*p == '/' && p[1] == '*') { 381 if (*p == '/' && p[1] == '*') {
366 p += 2; 382 p += 2;
367 while (*p == ' ' || *p == '\t') 383 while (*p == ' ' || *p == '\t')
368 p++; 384 p++;
369 if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' 385 if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
370 && p[4] == 'N' && p[5] == 'T') { 386 && p[4] == 'N' && p[5] == 'T') {
371 p += 6; 387 p += 6;
372 while (*p == ' ' || *p == '\t') 388 while (*p == ' ' || *p == '\t')
373 p++; 389 p++;
374 if (*p == '*') 390 if (*p == '*')
375 com = 1; 391 com = 1;
376 else if (*p == 'O') { 392 else if (*p == 'O') {
377 if (*++p == 'N') 393 if (*++p == 'N')
378 p++, com = 1; 394 p++, com = 1;
379 else if (*p == 'F' && *++p == 'F') 395 else if (*p == 'F' && *++p == 'F')
380 p++, com = 2; 396 p++, com = 2;
381 } 397 }
382 while (*p == ' ' || *p == '\t') 398 while (*p == ' ' || *p == '\t')
383 p++; 399 p++;
384 if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { 400 if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) {
385 if (s_com != e_com || s_lab != e_lab || s_code != e_code) 401 if (s_com != e_com || s_lab != e_lab || s_code != e_code)
386 dump_line(); 402 dump_line();
387 if (!(inhibit_formatting = com - 1)) { 403 if (!(inhibit_formatting = com - 1)) {
388 n_real_blanklines = 0; 404 n_real_blanklines = 0;
389 postfix_blankline_requested = 0; 405 postfix_blankline_requested = 0;
390 prefix_blankline_requested = 0; 406 prefix_blankline_requested = 0;
391 suppress_blanklines = 1; 407 suppress_blanklines = 1;
392 } 408 }
393 } 409 }
394 } 410 }
395 } 411 }
396 } 412 }
397 } 413 }
398 if (inhibit_formatting) { 414 if (inhibit_formatting) {
399 p = in_buffer; 415 p = in_buffer;
400 do { 416 do {
401 output_char(*p); 417 output_char(*p);
402 } while (*p++ != '\n'); 418 } while (*p++ != '\n');
403 } 419 }
404} 420}
405 421
406/* 422/*
407 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 423 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
408 * 424 *
409 * All rights reserved 425 * All rights reserved
410 */ 426 */
411int 427int
412count_spaces_until(int col, const char *buffer, const char *end) 428count_spaces_until(int col, const char *buffer, const char *end)
413{ 429{
414 for (const char *p = buffer; *p != '\0' && p != end; ++p) { 430 for (const char *p = buffer; *p != '\0' && p != end; ++p) {
415 switch (*p) { 431 switch (*p) {
416 432
417 case '\n': 433 case '\n':
418 case 014: /* form feed */ 434 case 014: /* form feed */
419 col = 1; 435 col = 1;
420 break; 436 break;
421 437
422 case '\t': 438 case '\t':
423 col = 1 + opt.tabsize * ((col - 1) / opt.tabsize + 1); 439 col = 1 + opt.tabsize * ((col - 1) / opt.tabsize + 1);
424 break; 440 break;
425 441
426 case 010: /* backspace */ 442 case 010: /* backspace */
427 --col; 443 --col;
428 break; 444 break;
429 445
430 default: 446 default:
431 ++col; 447 ++col;
432 break; 448 break;
433 } /* end of switch */ 449 } /* end of switch */
434 } /* end of for loop */ 450 } /* end of for loop */
435 return col; 451 return col;
436} 452}
437 453
438int 454int
439count_spaces(int col, const char *buffer) 455count_spaces(int col, const char *buffer)
440{ 456{
441 return count_spaces_until(col, buffer, NULL); 457 return count_spaces_until(col, buffer, NULL);
442} 458}
443 459
444void 460void
445diag(int level, const char *msg, ...) 461diag(int level, const char *msg, ...)
446{ 462{
447 va_list ap; 463 va_list ap;
448 const char *s, *e; 464 const char *s, *e;
449 465
450 if (level) 466 if (level)
451 found_err = 1; 467 found_err = 1;
452 468
453 if (output == stdout) { 469 if (output == stdout) {
454 s = "/**INDENT** "; 470 s = "/**INDENT** ";
455 e = " */"; 471 e = " */";
456 } else { 472 } else {
457 s = e = ""; 473 s = e = "";
458 } 474 }
459 475
460 va_start(ap, msg); 476 va_start(ap, msg);
461 fprintf(stderr, "%s%s@%d: ", s, level == 0 ? "Warning" : "Error", line_no); 477 fprintf(stderr, "%s%s@%d: ", s, level == 0 ? "Warning" : "Error", line_no);
462 vfprintf(stderr, msg, ap); 478 vfprintf(stderr, msg, ap);
463 fprintf(stderr, "%s\n", e); 479 fprintf(stderr, "%s\n", e);
464 va_end(ap); 480 va_end(ap);
465} 481}

cvs diff -r1.38 -r1.39 src/usr.bin/indent/lexi.c (switch to unified diff)

--- src/usr.bin/indent/lexi.c 2021/03/12 23:10:18 1.38
+++ src/usr.bin/indent/lexi.c 2021/03/13 09:21:57 1.39
@@ -1,730 +1,720 @@ @@ -1,730 +1,720 @@
1/* $NetBSD: lexi.c,v 1.38 2021/03/12 23:10:18 rillig Exp $ */ 1/* $NetBSD: lexi.c,v 1.39 2021/03/13 09:21:57 rillig Exp $ */
2 2
3/*- 3/*-
4 * SPDX-License-Identifier: BSD-4-Clause 4 * SPDX-License-Identifier: BSD-4-Clause
5 * 5 *
6 * Copyright (c) 1985 Sun Microsystems, Inc. 6 * Copyright (c) 1985 Sun Microsystems, Inc.
7 * Copyright (c) 1980, 1993 7 * Copyright (c) 1980, 1993
8 * The Regents of the University of California. All rights reserved. 8 * The Regents of the University of California. All rights reserved.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software 19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement: 20 * must display the following acknowledgement:
21 * This product includes software developed by the University of 21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors. 22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors 23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software 24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission. 25 * without specific prior written permission.
26 * 26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE. 37 * SUCH DAMAGE.
38 */ 38 */
39 39
40#if 0 40#if 0
41#ifndef lint 41#ifndef lint
42static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93"; 42static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93";
43#endif /* not lint */ 43#endif /* not lint */
44#endif 44#endif
45 45
46#include <sys/cdefs.h> 46#include <sys/cdefs.h>
47#ifndef lint 47#ifndef lint
48#if defined(__NetBSD__) 48#if defined(__NetBSD__)
49__RCSID("$NetBSD: lexi.c,v 1.38 2021/03/12 23:10:18 rillig Exp $"); 49__RCSID("$NetBSD: lexi.c,v 1.39 2021/03/13 09:21:57 rillig Exp $");
50#elif defined(__FreeBSD__) 50#elif defined(__FreeBSD__)
51__FBSDID("$FreeBSD: head/usr.bin/indent/lexi.c 337862 2018-08-15 18:19:45Z pstef $"); 51__FBSDID("$FreeBSD: head/usr.bin/indent/lexi.c 337862 2018-08-15 18:19:45Z pstef $");
52#endif 52#endif
53#endif 53#endif
54 54
55/* 55/*
56 * Here we have the token scanner for indent. It scans off one token and puts 56 * Here we have the token scanner for indent. It scans off one token and puts
57 * it in the global variable "token". It returns a code, indicating the type 57 * it in the global variable "token". It returns a code, indicating the type
58 * of token scanned. 58 * of token scanned.
59 */ 59 */
60 60
61#include <assert.h> 61#include <assert.h>
62#include <err.h> 62#include <err.h>
63#include <stdio.h> 63#include <stdio.h>
64#include <ctype.h> 64#include <ctype.h>
65#include <stdlib.h> 65#include <stdlib.h>
66#include <string.h> 66#include <string.h>
67#include <sys/param.h> 67#include <sys/param.h>
68 68
69#include "indent.h" 69#include "indent.h"
70 70
71struct templ { 71struct templ {
72 const char *rwd; 72 const char *rwd;
73 enum rwcode rwcode; 73 enum rwcode rwcode;
74}; 74};
75 75
76/* 76/*
77 * This table has to be sorted alphabetically, because it'll be used in binary 77 * This table has to be sorted alphabetically, because it'll be used in binary
78 * search. 78 * search.
79 */ 79 */
80const struct templ specials[] = 80const struct templ specials[] =
81{ 81{
82 {"_Bool", rw_type}, 82 {"_Bool", rw_type},
83 {"_Complex", rw_type}, 83 {"_Complex", rw_type},
84 {"_Imaginary", rw_type}, 84 {"_Imaginary", rw_type},
85 {"auto", rw_storage_class}, 85 {"auto", rw_storage_class},
86 {"bool", rw_type}, 86 {"bool", rw_type},
87 {"break", rw_jump}, 87 {"break", rw_jump},
88 {"case", rw_case_or_default}, 88 {"case", rw_case_or_default},
89 {"char", rw_type}, 89 {"char", rw_type},
90 {"complex", rw_type}, 90 {"complex", rw_type},
91 {"const", rw_type}, 91 {"const", rw_type},
92 {"continue", rw_jump}, 92 {"continue", rw_jump},
93 {"default", rw_case_or_default}, 93 {"default", rw_case_or_default},
94 {"do", rw_do_or_else}, 94 {"do", rw_do_or_else},
95 {"double", rw_type}, 95 {"double", rw_type},
96 {"else", rw_do_or_else}, 96 {"else", rw_do_or_else},
97 {"enum", rw_struct_or_union_or_enum}, 97 {"enum", rw_struct_or_union_or_enum},
98 {"extern", rw_storage_class}, 98 {"extern", rw_storage_class},
99 {"float", rw_type}, 99 {"float", rw_type},
100 {"for", rw_for_or_if_or_while}, 100 {"for", rw_for_or_if_or_while},
101 {"global", rw_type}, 101 {"global", rw_type},
102 {"goto", rw_jump}, 102 {"goto", rw_jump},
103 {"if", rw_for_or_if_or_while}, 103 {"if", rw_for_or_if_or_while},
104 {"imaginary", rw_type}, 104 {"imaginary", rw_type},
105 {"inline", rw_inline_or_restrict}, 105 {"inline", rw_inline_or_restrict},
106 {"int", rw_type}, 106 {"int", rw_type},
107 {"long", rw_type}, 107 {"long", rw_type},
108 {"offsetof", rw_offsetof}, 108 {"offsetof", rw_offsetof},
109 {"register", rw_storage_class}, 109 {"register", rw_storage_class},
110 {"restrict", rw_inline_or_restrict}, 110 {"restrict", rw_inline_or_restrict},
111 {"return", rw_jump}, 111 {"return", rw_jump},
112 {"short", rw_type}, 112 {"short", rw_type},
113 {"signed", rw_type}, 113 {"signed", rw_type},
114 {"sizeof", rw_sizeof}, 114 {"sizeof", rw_sizeof},
115 {"static", rw_storage_class}, 115 {"static", rw_storage_class},
116 {"struct", rw_struct_or_union_or_enum}, 116 {"struct", rw_struct_or_union_or_enum},
117 {"switch", rw_switch}, 117 {"switch", rw_switch},
118 {"typedef", rw_typedef}, 118 {"typedef", rw_typedef},
119 {"union", rw_struct_or_union_or_enum}, 119 {"union", rw_struct_or_union_or_enum},
120 {"unsigned", rw_type}, 120 {"unsigned", rw_type},
121 {"void", rw_type}, 121 {"void", rw_type},
122 {"volatile", rw_type}, 122 {"volatile", rw_type},
123 {"while", rw_for_or_if_or_while} 123 {"while", rw_for_or_if_or_while}
124}; 124};
125 125
126const char **typenames; 126const char **typenames;
127int typename_count; 127int typename_count;
128int typename_top = -1; 128int typename_top = -1;
129 129
130/* 130/*
131 * The transition table below was rewritten by hand from lx's output, given 131 * The transition table below was rewritten by hand from lx's output, given
132 * the following definitions. lx is Katherine Flavel's lexer generator. 132 * the following definitions. lx is Katherine Flavel's lexer generator.
133 * 133 *
134 * O = /[0-7]/; D = /[0-9]/; NZ = /[1-9]/; 134 * O = /[0-7]/; D = /[0-9]/; NZ = /[1-9]/;
135 * H = /[a-f0-9]/i; B = /[0-1]/; HP = /0x/i; 135 * H = /[a-f0-9]/i; B = /[0-1]/; HP = /0x/i;
136 * BP = /0b/i; E = /e[+\-]?/i D+; P = /p[+\-]?/i D+; 136 * BP = /0b/i; E = /e[+\-]?/i D+; P = /p[+\-]?/i D+;
137 * FS = /[fl]/i; IS = /u/i /(l|L|ll|LL)/? | /(l|L|ll|LL)/ /u/i?; 137 * FS = /[fl]/i; IS = /u/i /(l|L|ll|LL)/? | /(l|L|ll|LL)/ /u/i?;
138 * 138 *
139 * D+ E FS? -> $float; 139 * D+ E FS? -> $float;
140 * D* "." D+ E? FS? -> $float; 140 * D* "." D+ E? FS? -> $float;
141 * D+ "." E? FS? -> $float; HP H+ IS? -> $int; 141 * D+ "." E? FS? -> $float; HP H+ IS? -> $int;
142 * HP H+ P FS? -> $float; NZ D* IS? -> $int; 142 * HP H+ P FS? -> $float; NZ D* IS? -> $int;
143 * HP H* "." H+ P FS? -> $float; "0" O* IS? -> $int; 143 * HP H* "." H+ P FS? -> $float; "0" O* IS? -> $int;
144 * HP H+ "." P FS -> $float; BP B+ IS? -> $int; 144 * HP H+ "." P FS -> $float; BP B+ IS? -> $int;
145 */ 145 */
146static char const *table[] = { 146static char const *table[] = {
147 /* examples: 147 /* examples:
148 00 148 00
149 s 0xx 149 s 0xx
150 t 00xaa 150 t 00xaa
151 a 11 101100xxa.. 151 a 11 101100xxa..
152 r 11ee0001101lbuuxx.a.pp 152 r 11ee0001101lbuuxx.a.pp
153 t.01.e+008bLuxll0Ll.aa.p+0 153 t.01.e+008bLuxll0Ll.aa.p+0
154 states: ABCDEFGHIJKLMNOPQRSTUVWXYZ */ 154 states: ABCDEFGHIJKLMNOPQRSTUVWXYZ */
155 ['0'] = "CEIDEHHHIJQ U Q VUVVZZZ", 155 ['0'] = "CEIDEHHHIJQ U Q VUVVZZZ",
156 ['1'] = "DEIDEHHHIJQ U Q VUVVZZZ", 156 ['1'] = "DEIDEHHHIJQ U Q VUVVZZZ",
157 ['7'] = "DEIDEHHHIJ U VUVVZZZ", 157 ['7'] = "DEIDEHHHIJ U VUVVZZZ",
158 ['9'] = "DEJDEHHHJJ U VUVVZZZ", 158 ['9'] = "DEJDEHHHJJ U VUVVZZZ",
159 ['a'] = " U VUVV ", 159 ['a'] = " U VUVV ",
160 ['b'] = " K U VUVV ", 160 ['b'] = " K U VUVV ",
161 ['e'] = " FFF FF U VUVV ", 161 ['e'] = " FFF FF U VUVV ",
162 ['f'] = " f f U VUVV f", 162 ['f'] = " f f U VUVV f",
163 ['u'] = " MM M i iiM M ", 163 ['u'] = " MM M i iiM M ",
164 ['x'] = " N ", 164 ['x'] = " N ",
165 ['p'] = " FFX ", 165 ['p'] = " FFX ",
166 ['L'] = " LLf fL PR Li L f", 166 ['L'] = " LLf fL PR Li L f",
167 ['l'] = " OOf fO S P O i O f", 167 ['l'] = " OOf fO S P O i O f",
168 ['+'] = " G Y ", 168 ['+'] = " G Y ",
169 ['.'] = "B EE EE T W ", 169 ['.'] = "B EE EE T W ",
170 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ 170 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
171 [0] = "uuiifuufiuuiiuiiiiiuiuuuuu", 171 [0] = "uuiifuufiuuiiuiiiiiuiuuuuu",
172}; 172};
173 173
174/* Initialize constant transition table */ 174/* Initialize constant transition table */
175void 175void
176init_constant_tt(void) 176init_constant_tt(void)
177{ 177{
178 table['-'] = table['+']; 178 table['-'] = table['+'];
179 table['8'] = table['9']; 179 table['8'] = table['9'];
180 table['2'] = table['3'] = table['4'] = table['5'] = table['6'] = table['7']; 180 table['2'] = table['3'] = table['4'] = table['5'] = table['6'] = table['7'];
181 table['A'] = table['C'] = table['D'] = table['c'] = table['d'] = table['a']; 181 table['A'] = table['C'] = table['D'] = table['c'] = table['d'] = table['a'];
182 table['B'] = table['b']; 182 table['B'] = table['b'];
183 table['E'] = table['e']; 183 table['E'] = table['e'];
184 table['U'] = table['u']; 184 table['U'] = table['u'];
185 table['X'] = table['x']; 185 table['X'] = table['x'];
186 table['P'] = table['p']; 186 table['P'] = table['p'];
187 table['F'] = table['f']; 187 table['F'] = table['f'];
188} 188}
189 189
190static char 190static char
191inbuf_peek(void) 191inbuf_peek(void)
192{ 192{
193 return *buf_ptr; 193 return *buf_ptr;
194} 194}
195 195
196static void 196static void
197inbuf_skip(void) 197inbuf_skip(void)
198{ 198{
199 buf_ptr++; 199 buf_ptr++;
200 if (buf_ptr >= buf_end) 200 if (buf_ptr >= buf_end)
201 fill_buffer(); 201 fill_buffer();
202} 202}
203 203
204static char 204static char
205inbuf_next(void) 205inbuf_next(void)
206{ 206{
207 char ch = inbuf_peek(); 207 char ch = inbuf_peek();
208 inbuf_skip(); 208 inbuf_skip();
209 return ch; 209 return ch;
210} 210}
211 211
212static void 212static void
213check_size_token(size_t desired_size) 213check_size_token(size_t desired_size)
214{ 214{
215 if (e_token + (desired_size) < l_token) 215 if (e_token + (desired_size) < l_token)
216 return; 216 return;
217 217
218 size_t nsize = l_token - s_token + 400 + desired_size; 218 size_t nsize = l_token - s_token + 400 + desired_size;
219 size_t token_len = e_token - s_token; 219 size_t token_len = e_token - s_token;
220 tokenbuf = realloc(tokenbuf, nsize); 220 tokenbuf = realloc(tokenbuf, nsize);
221 if (tokenbuf == NULL) 221 if (tokenbuf == NULL)
222 err(1, NULL); 222 err(1, NULL);
223 e_token = tokenbuf + token_len + 1; 223 e_token = tokenbuf + token_len + 1;
224 l_token = tokenbuf + nsize - 5; 224 l_token = tokenbuf + nsize - 5;
225 s_token = tokenbuf + 1; 225 s_token = tokenbuf + 1;
226} 226}
227 227
228static int 228static int
229compare_templ_array(const void *key, const void *elem) 229compare_templ_array(const void *key, const void *elem)
230{ 230{
231 return strcmp(key, ((const struct templ *)elem)->rwd); 231 return strcmp(key, ((const struct templ *)elem)->rwd);
232} 232}
233 233
234static int 234static int
235compare_string_array(const void *key, const void *elem) 235compare_string_array(const void *key, const void *elem)
236{ 236{
237 return strcmp(key, *((const char *const *)elem)); 237 return strcmp(key, *((const char *const *)elem));
238} 238}
239 239
240#ifdef debug 240#ifdef debug
241const char * 241const char *
242token_type_name(token_type tk) 242token_type_name(token_type tk)
243{ 243{
244 static const char *const name[] = { 244 static const char *const name[] = {
245 "end_of_file", "newline", "lparen", "rparen", "unary_op", 245 "end_of_file", "newline", "lparen", "rparen", "unary_op",
246 "binary_op", "postfix_op", "question", "case_label", "colon", 246 "binary_op", "postfix_op", "question", "case_label", "colon",
247 "semicolon", "lbrace", "rbrace", "ident", "comma", 247 "semicolon", "lbrace", "rbrace", "ident", "comma",
248 "comment", "switch_expr", "preprocessing", "form_feed", "decl", 248 "comment", "switch_expr", "preprocessing", "form_feed", "decl",
249 "keyword_for_if_while", "keyword_do_else", 249 "keyword_for_if_while", "keyword_do_else",
250 "if_expr", "while_expr", "for_exprs", 250 "if_expr", "while_expr", "for_exprs",
251 "stmt", "stmt_list", "keyword_else", "keyword_do", "do_stmt", 251 "stmt", "stmt_list", "keyword_else", "keyword_do", "do_stmt",
252 "if_expr_stmt", "if_expr_stmt_else", "period", "string_prefix", 252 "if_expr_stmt", "if_expr_stmt_else", "period", "string_prefix",
253 "storage_class", "funcname", "type_def", "keyword_struct_union_enum" 253 "storage_class", "funcname", "type_def", "keyword_struct_union_enum"
254 }; 254 };
255 255
256 assert(0 <= tk && tk < sizeof name / sizeof name[0]); 256 assert(0 <= tk && tk < sizeof name / sizeof name[0]);
257 257
258 return name[tk]; 258 return name[tk];
259} 259}
260 260
261static void 261static void
262print_buf(const char *name, const char *s, const char *e) 262print_buf(const char *name, const char *s, const char *e)
263{ 263{
264 if (s == e) 264 if (s < e) {
265 return; 265 debug_printf(" %s ", name);
266 266 debug_vis_range("\"", s, e, "\"");
267 printf(" %s \"", name); 
268 for (const char *p = s; p < e; p++) { 
269 if (isprint((unsigned char)*p) && *p != '\\' && *p != '"') 
270 printf("%c", *p); 
271 else if (*p == '\n') 
272 printf("\\n"); 
273 else if (*p == '\t') 
274 printf("\\t"); 
275 else 
276 printf("\\x%02x", *p); 
277 } 267 }
278 printf("\""); 
279} 268}
280 269
281static token_type 270static token_type
282lexi_end(token_type code) 271lexi_end(token_type code)
283{ 272{
284 printf("in line %d, lexi returns '%s'", line_no, token_type_name(code)); 273 debug_printf("in line %d, lexi returns '%s'",
 274 line_no, token_type_name(code));
285 print_buf("token", s_token, e_token); 275 print_buf("token", s_token, e_token);
286 print_buf("label", s_lab, e_lab); 276 print_buf("label", s_lab, e_lab);
287 print_buf("code", s_code, e_code); 277 print_buf("code", s_code, e_code);
288 print_buf("comment", s_com, e_com); 278 print_buf("comment", s_com, e_com);
289 printf("\n"); 279 debug_printf("\n");
290 280
291 return code; 281 return code;
292} 282}
293#else 283#else
294# define lexi_end(tk) (tk) 284# define lexi_end(tk) (tk)
295#endif 285#endif
296 286
297token_type 287token_type
298lexi(struct parser_state *state) 288lexi(struct parser_state *state)
299{ 289{
300 int unary_delim; /* this is set to 1 if the current token 290 int unary_delim; /* this is set to 1 if the current token
301 * forces a following operator to be unary */ 291 * forces a following operator to be unary */
302 token_type code; /* internal code to be returned */ 292 token_type code; /* internal code to be returned */
303 char qchar; /* the delimiter character for a string */ 293 char qchar; /* the delimiter character for a string */
304 294
305 e_token = s_token; /* point to start of place to save token */ 295 e_token = s_token; /* point to start of place to save token */
306 unary_delim = false; 296 unary_delim = false;
307 state->col_1 = state->last_nl; /* tell world that this token started 297 state->col_1 = state->last_nl; /* tell world that this token started
308 * in column 1 iff the last thing 298 * in column 1 iff the last thing
309 * scanned was a newline */ 299 * scanned was a newline */
310 state->last_nl = false; 300 state->last_nl = false;
311 301
312 while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ 302 while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
313 state->col_1 = false; /* leading blanks imply token is not in column 303 state->col_1 = false; /* leading blanks imply token is not in column
314 * 1 */ 304 * 1 */
315 inbuf_skip(); 305 inbuf_skip();
316 } 306 }
317 307
318 /* Scan an alphanumeric token */ 308 /* Scan an alphanumeric token */
319 if (isalnum((unsigned char)*buf_ptr) || 309 if (isalnum((unsigned char)*buf_ptr) ||
320 *buf_ptr == '_' || *buf_ptr == '$' || 310 *buf_ptr == '_' || *buf_ptr == '$' ||
321 (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { 311 (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
322 /* 312 /*
323 * we have a character or number 313 * we have a character or number
324 */ 314 */
325 struct templ *p; 315 struct templ *p;
326 316
327 if (isdigit((unsigned char)*buf_ptr) || 317 if (isdigit((unsigned char)*buf_ptr) ||
328 (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { 318 (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
329 char s; 319 char s;
330 unsigned char i; 320 unsigned char i;
331 321
332 for (s = 'A'; s != 'f' && s != 'i' && s != 'u'; ) { 322 for (s = 'A'; s != 'f' && s != 'i' && s != 'u'; ) {
333 i = (unsigned char)*buf_ptr; 323 i = (unsigned char)*buf_ptr;
334 if (i >= nitems(table) || table[i] == NULL || 324 if (i >= nitems(table) || table[i] == NULL ||
335 table[i][s - 'A'] == ' ') { 325 table[i][s - 'A'] == ' ') {
336 s = table[0][s - 'A']; 326 s = table[0][s - 'A'];
337 break; 327 break;
338 } 328 }
339 s = table[i][s - 'A']; 329 s = table[i][s - 'A'];
340 check_size_token(1); 330 check_size_token(1);
341 *e_token++ = inbuf_next(); 331 *e_token++ = inbuf_next();
342 } 332 }
343 /* s now indicates the type: f(loating), i(integer), u(nknown) */ 333 /* s now indicates the type: f(loating), i(integer), u(nknown) */
344 } else { 334 } else {
345 while (isalnum((unsigned char)*buf_ptr) || 335 while (isalnum((unsigned char)*buf_ptr) ||
346 *buf_ptr == '\\' || 336 *buf_ptr == '\\' ||
347 *buf_ptr == '_' || *buf_ptr == '$') { 337 *buf_ptr == '_' || *buf_ptr == '$') {
348 /* fill_buffer() terminates buffer with newline */ 338 /* fill_buffer() terminates buffer with newline */
349 if (*buf_ptr == '\\') { 339 if (*buf_ptr == '\\') {
350 if (buf_ptr[1] == '\n') { 340 if (buf_ptr[1] == '\n') {
351 buf_ptr += 2; 341 buf_ptr += 2;
352 if (buf_ptr >= buf_end) 342 if (buf_ptr >= buf_end)
353 fill_buffer(); 343 fill_buffer();
354 } else 344 } else
355 break; 345 break;
356 } 346 }
357 check_size_token(1); 347 check_size_token(1);
358 *e_token++ = inbuf_next(); 348 *e_token++ = inbuf_next();
359 } 349 }
360 } 350 }
361 *e_token = '\0'; 351 *e_token = '\0';
362 352
363 if (s_token[0] == 'L' && s_token[1] == '\0' && 353 if (s_token[0] == 'L' && s_token[1] == '\0' &&
364 (*buf_ptr == '"' || *buf_ptr == '\'')) 354 (*buf_ptr == '"' || *buf_ptr == '\''))
365 return lexi_end(string_prefix); 355 return lexi_end(string_prefix);
366 356
367 while (*buf_ptr == ' ' || *buf_ptr == '\t') /* get rid of blanks */ 357 while (*buf_ptr == ' ' || *buf_ptr == '\t') /* get rid of blanks */
368 inbuf_next(); 358 inbuf_next();
369 state->keyword = rw_0; 359 state->keyword = rw_0;
370 if (state->last_token == keyword_struct_union_enum && 360 if (state->last_token == keyword_struct_union_enum &&
371 !state->p_l_follow) { 361 !state->p_l_follow) {
372 /* if last token was 'struct' and we're not in parentheses, then 362 /* if last token was 'struct' and we're not in parentheses, then
373 * this token should be treated as a declaration */ 363 * this token should be treated as a declaration */
374 state->last_u_d = true; 364 state->last_u_d = true;
375 return lexi_end(decl); 365 return lexi_end(decl);
376 } 366 }
377 /* 367 /*
378 * Operator after identifier is binary unless last token was 'struct' 368 * Operator after identifier is binary unless last token was 'struct'
379 */ 369 */
380 state->last_u_d = (state->last_token == keyword_struct_union_enum); 370 state->last_u_d = (state->last_token == keyword_struct_union_enum);
381 371
382 p = bsearch(s_token, specials, sizeof specials / sizeof specials[0], 372 p = bsearch(s_token, specials, sizeof specials / sizeof specials[0],
383 sizeof specials[0], compare_templ_array); 373 sizeof specials[0], compare_templ_array);
384 if (p == NULL) { /* not a special keyword... */ 374 if (p == NULL) { /* not a special keyword... */
385 char *u; 375 char *u;
386 376
387 /* ... so maybe a type_t or a typedef */ 377 /* ... so maybe a type_t or a typedef */
388 if ((opt.auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) && 378 if ((opt.auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
389 strcmp(u, "_t") == 0) || (typename_top >= 0 && 379 strcmp(u, "_t") == 0) || (typename_top >= 0 &&
390 bsearch(s_token, typenames, typename_top + 1, 380 bsearch(s_token, typenames, typename_top + 1,
391 sizeof typenames[0], compare_string_array))) { 381 sizeof typenames[0], compare_string_array))) {
392 state->keyword = rw_type; 382 state->keyword = rw_type;
393 state->last_u_d = true; 383 state->last_u_d = true;
394 goto found_typename; 384 goto found_typename;
395 } 385 }
396 } else { /* we have a keyword */ 386 } else { /* we have a keyword */
397 state->keyword = p->rwcode; 387 state->keyword = p->rwcode;
398 state->last_u_d = true; 388 state->last_u_d = true;
399 switch (p->rwcode) { 389 switch (p->rwcode) {
400 case rw_switch: 390 case rw_switch:
401 return lexi_end(switch_expr); 391 return lexi_end(switch_expr);
402 case rw_case_or_default: 392 case rw_case_or_default:
403 return lexi_end(case_label); 393 return lexi_end(case_label);
404 case rw_struct_or_union_or_enum: 394 case rw_struct_or_union_or_enum:
405 case rw_type: 395 case rw_type:
406 found_typename: 396 found_typename:
407 if (state->p_l_follow) { 397 if (state->p_l_follow) {
408 /* inside parens: cast, param list, offsetof or sizeof */ 398 /* inside parens: cast, param list, offsetof or sizeof */
409 state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask; 399 state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask;
410 } 400 }
411 if (state->last_token == period || state->last_token == unary_op) { 401 if (state->last_token == period || state->last_token == unary_op) {
412 state->keyword = rw_0; 402 state->keyword = rw_0;
413 break; 403 break;
414 } 404 }
415 if (p != NULL && p->rwcode == rw_struct_or_union_or_enum) 405 if (p != NULL && p->rwcode == rw_struct_or_union_or_enum)
416 return lexi_end(keyword_struct_union_enum); 406 return lexi_end(keyword_struct_union_enum);
417 if (state->p_l_follow) 407 if (state->p_l_follow)
418 break; 408 break;
419 return lexi_end(decl); 409 return lexi_end(decl);
420 410
421 case rw_for_or_if_or_while: 411 case rw_for_or_if_or_while:
422 return lexi_end(keyword_for_if_while); 412 return lexi_end(keyword_for_if_while);
423 413
424 case rw_do_or_else: 414 case rw_do_or_else:
425 return lexi_end(keyword_do_else); 415 return lexi_end(keyword_do_else);
426 416
427 case rw_storage_class: 417 case rw_storage_class:
428 return lexi_end(storage_class); 418 return lexi_end(storage_class);
429 419
430 case rw_typedef: 420 case rw_typedef:
431 return lexi_end(type_def); 421 return lexi_end(type_def);
432 422
433 default: /* all others are treated like any other 423 default: /* all others are treated like any other
434 * identifier */ 424 * identifier */
435 return lexi_end(ident); 425 return lexi_end(ident);
436 } /* end of switch */ 426 } /* end of switch */
437 } /* end of if (found_it) */ 427 } /* end of if (found_it) */
438 if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 && 428 if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 &&
439 state->in_parameter_declaration == 0 && state->block_init == 0) { 429 state->in_parameter_declaration == 0 && state->block_init == 0) {
440 char *tp = buf_ptr; 430 char *tp = buf_ptr;
441 while (tp < buf_end) 431 while (tp < buf_end)
442 if (*tp++ == ')' && (*tp == ';' || *tp == ',')) 432 if (*tp++ == ')' && (*tp == ';' || *tp == ','))
443 goto not_proc; 433 goto not_proc;
444 strncpy(state->procname, token, sizeof state->procname - 1); 434 strncpy(state->procname, token, sizeof state->procname - 1);
445 if (state->in_decl) 435 if (state->in_decl)
446 state->in_parameter_declaration = 1; 436 state->in_parameter_declaration = 1;
447 return lexi_end(funcname); 437 return lexi_end(funcname);
448 not_proc:; 438 not_proc:;
449 } 439 }
450 /* 440 /*
451 * The following hack attempts to guess whether or not the current 441 * The following hack attempts to guess whether or not the current
452 * token is in fact a declaration keyword -- one that has been 442 * token is in fact a declaration keyword -- one that has been
453 * typedefd 443 * typedefd
454 */ 444 */
455 else if (!state->p_l_follow && !state->block_init && 445 else if (!state->p_l_follow && !state->block_init &&
456 !state->in_stmt && 446 !state->in_stmt &&
457 ((*buf_ptr == '*' && buf_ptr[1] != '=') || 447 ((*buf_ptr == '*' && buf_ptr[1] != '=') ||
458 isalpha((unsigned char)*buf_ptr)) && 448 isalpha((unsigned char)*buf_ptr)) &&
459 (state->last_token == semicolon || state->last_token == lbrace || 449 (state->last_token == semicolon || state->last_token == lbrace ||
460 state->last_token == rbrace)) { 450 state->last_token == rbrace)) {
461 state->keyword = rw_type; 451 state->keyword = rw_type;
462 state->last_u_d = true; 452 state->last_u_d = true;
463 return lexi_end(decl); 453 return lexi_end(decl);
464 } 454 }
465 if (state->last_token == decl) /* if this is a declared variable, 455 if (state->last_token == decl) /* if this is a declared variable,
466 * then following sign is unary */ 456 * then following sign is unary */
467 state->last_u_d = true; /* will make "int a -1" work */ 457 state->last_u_d = true; /* will make "int a -1" work */
468 return lexi_end(ident); /* the ident is not in the list */ 458 return lexi_end(ident); /* the ident is not in the list */
469 } /* end of procesing for alpanum character */ 459 } /* end of procesing for alpanum character */
470 460
471 /* Scan a non-alphanumeric token */ 461 /* Scan a non-alphanumeric token */
472 462
473 check_size_token(3); /* things like "<<=" */ 463 check_size_token(3); /* things like "<<=" */
474 *e_token++ = inbuf_next(); /* if it is only a one-character token, it is 464 *e_token++ = inbuf_next(); /* if it is only a one-character token, it is
475 * moved here */ 465 * moved here */
476 *e_token = '\0'; 466 *e_token = '\0';
477 467
478 switch (*token) { 468 switch (*token) {
479 case '\n': 469 case '\n':
480 unary_delim = state->last_u_d; 470 unary_delim = state->last_u_d;
481 state->last_nl = true; /* remember that we just had a newline */ 471 state->last_nl = true; /* remember that we just had a newline */
482 code = (had_eof ? end_of_file : newline); 472 code = (had_eof ? end_of_file : newline);
483 473
484 /* 474 /*
485 * if data has been exhausted, the newline is a dummy, and we should 475 * if data has been exhausted, the newline is a dummy, and we should
486 * return code to stop 476 * return code to stop
487 */ 477 */
488 break; 478 break;
489 479
490 case '\'': /* start of quoted character */ 480 case '\'': /* start of quoted character */
491 case '"': /* start of string */ 481 case '"': /* start of string */
492 qchar = *token; 482 qchar = *token;
493 do { /* copy the string */ 483 do { /* copy the string */
494 while (1) { /* move one character or [/<char>]<char> */ 484 while (1) { /* move one character or [/<char>]<char> */
495 if (*buf_ptr == '\n') { 485 if (*buf_ptr == '\n') {
496 diag(1, "Unterminated literal"); 486 diag(1, "Unterminated literal");
497 goto stop_lit; 487 goto stop_lit;
498 } 488 }
499 check_size_token(2); 489 check_size_token(2);
500 *e_token = inbuf_next(); 490 *e_token = inbuf_next();
501 if (*e_token == '\\') { /* if escape, copy extra char */ 491 if (*e_token == '\\') { /* if escape, copy extra char */
502 if (*buf_ptr == '\n') /* check for escaped newline */ 492 if (*buf_ptr == '\n') /* check for escaped newline */
503 ++line_no; 493 ++line_no;
504 *++e_token = inbuf_next(); 494 *++e_token = inbuf_next();
505 ++e_token; /* we must increment this again because we 495 ++e_token; /* we must increment this again because we
506 * copied two chars */ 496 * copied two chars */
507 } else 497 } else
508 break; /* we copied one character */ 498 break; /* we copied one character */
509 } /* end of while (1) */ 499 } /* end of while (1) */
510 } while (*e_token++ != qchar); 500 } while (*e_token++ != qchar);
511stop_lit: 501stop_lit:
512 code = ident; 502 code = ident;
513 break; 503 break;
514 504
515 case ('('): 505 case ('('):
516 case ('['): 506 case ('['):
517 unary_delim = true; 507 unary_delim = true;
518 code = lparen; 508 code = lparen;
519 break; 509 break;
520 510
521 case (')'): 511 case (')'):
522 case (']'): 512 case (']'):
523 code = rparen; 513 code = rparen;
524 break; 514 break;
525 515
526 case '#': 516 case '#':
527 unary_delim = state->last_u_d; 517 unary_delim = state->last_u_d;
528 code = preprocessing; 518 code = preprocessing;
529 break; 519 break;
530 520
531 case '?': 521 case '?':
532 unary_delim = true; 522 unary_delim = true;
533 code = question; 523 code = question;
534 break; 524 break;
535 525
536 case (':'): 526 case (':'):
537 code = colon; 527 code = colon;
538 unary_delim = true; 528 unary_delim = true;
539 break; 529 break;
540 530
541 case (';'): 531 case (';'):
542 unary_delim = true; 532 unary_delim = true;
543 code = semicolon; 533 code = semicolon;
544 break; 534 break;
545 535
546 case ('{'): 536 case ('{'):
547 unary_delim = true; 537 unary_delim = true;
548 538
549 /* 539 /*
550 * if (state->in_or_st) state->block_init = 1; 540 * if (state->in_or_st) state->block_init = 1;
551 */ 541 */
552 /* ? code = state->block_init ? lparen : lbrace; */ 542 /* ? code = state->block_init ? lparen : lbrace; */
553 code = lbrace; 543 code = lbrace;
554 break; 544 break;
555 545
556 case ('}'): 546 case ('}'):
557 unary_delim = true; 547 unary_delim = true;
558 /* ? code = state->block_init ? rparen : rbrace; */ 548 /* ? code = state->block_init ? rparen : rbrace; */
559 code = rbrace; 549 code = rbrace;
560 break; 550 break;
561 551
562 case 014: /* a form feed */ 552 case 014: /* a form feed */
563 unary_delim = state->last_u_d; 553 unary_delim = state->last_u_d;
564 state->last_nl = true; /* remember this so we can set 'state->col_1' 554 state->last_nl = true; /* remember this so we can set 'state->col_1'
565 * right */ 555 * right */
566 code = form_feed; 556 code = form_feed;
567 break; 557 break;
568 558
569 case (','): 559 case (','):
570 unary_delim = true; 560 unary_delim = true;
571 code = comma; 561 code = comma;
572 break; 562 break;
573 563
574 case '.': 564 case '.':
575 unary_delim = false; 565 unary_delim = false;
576 code = period; 566 code = period;
577 break; 567 break;
578 568
579 case '-': 569 case '-':
580 case '+': /* check for -, +, --, ++ */ 570 case '+': /* check for -, +, --, ++ */
581 code = (state->last_u_d ? unary_op : binary_op); 571 code = (state->last_u_d ? unary_op : binary_op);
582 unary_delim = true; 572 unary_delim = true;
583 573
584 if (*buf_ptr == token[0]) { 574 if (*buf_ptr == token[0]) {
585 /* check for doubled character */ 575 /* check for doubled character */
586 *e_token++ = *buf_ptr++; 576 *e_token++ = *buf_ptr++;
587 /* buffer overflow will be checked at end of loop */ 577 /* buffer overflow will be checked at end of loop */
588 if (state->last_token == ident || state->last_token == rparen) { 578 if (state->last_token == ident || state->last_token == rparen) {
589 code = (state->last_u_d ? unary_op : postfix_op); 579 code = (state->last_u_d ? unary_op : postfix_op);
590 /* check for following ++ or -- */ 580 /* check for following ++ or -- */
591 unary_delim = false; 581 unary_delim = false;
592 } 582 }
593 } else if (*buf_ptr == '=') 583 } else if (*buf_ptr == '=')
594 /* check for operator += */ 584 /* check for operator += */
595 *e_token++ = *buf_ptr++; 585 *e_token++ = *buf_ptr++;
596 else if (*buf_ptr == '>') { 586 else if (*buf_ptr == '>') {
597 /* check for operator -> */ 587 /* check for operator -> */
598 *e_token++ = *buf_ptr++; 588 *e_token++ = *buf_ptr++;
599 unary_delim = false; 589 unary_delim = false;
600 code = unary_op; 590 code = unary_op;
601 state->want_blank = false; 591 state->want_blank = false;
602 } 592 }
603 break; /* buffer overflow will be checked at end of 593 break; /* buffer overflow will be checked at end of
604 * switch */ 594 * switch */
605 595
606 case '=': 596 case '=':
607 if (state->in_or_st) 597 if (state->in_or_st)
608 state->block_init = 1; 598 state->block_init = 1;
609 if (*buf_ptr == '=') { /* == */ 599 if (*buf_ptr == '=') { /* == */
610 *e_token++ = '='; /* Flip =+ to += */ 600 *e_token++ = '='; /* Flip =+ to += */
611 buf_ptr++; 601 buf_ptr++;
612 *e_token = 0; 602 *e_token = 0;
613 } 603 }
614 code = binary_op; 604 code = binary_op;
615 unary_delim = true; 605 unary_delim = true;
616 break; 606 break;
617 /* can drop thru!!! */ 607 /* can drop thru!!! */
618 608
619 case '>': 609 case '>':
620 case '<': 610 case '<':
621 case '!': /* ops like <, <<, <=, !=, etc */ 611 case '!': /* ops like <, <<, <=, !=, etc */
622 if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') 612 if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=')
623 *e_token++ = inbuf_next(); 613 *e_token++ = inbuf_next();
624 if (*buf_ptr == '=') 614 if (*buf_ptr == '=')
625 *e_token++ = *buf_ptr++; 615 *e_token++ = *buf_ptr++;
626 code = (state->last_u_d ? unary_op : binary_op); 616 code = (state->last_u_d ? unary_op : binary_op);
627 unary_delim = true; 617 unary_delim = true;
628 break; 618 break;
629 619
630 case '*': 620 case '*':
631 unary_delim = true; 621 unary_delim = true;
632 if (!state->last_u_d) { 622 if (!state->last_u_d) {
633 if (*buf_ptr == '=') 623 if (*buf_ptr == '=')
634 *e_token++ = *buf_ptr++; 624 *e_token++ = *buf_ptr++;
635 code = binary_op; 625 code = binary_op;
636 break; 626 break;
637 } 627 }
638 while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) { 628 while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) {
639 if (*buf_ptr == '*') { 629 if (*buf_ptr == '*') {
640 check_size_token(1); 630 check_size_token(1);
641 *e_token++ = *buf_ptr; 631 *e_token++ = *buf_ptr;
642 } 632 }
643 inbuf_skip(); 633 inbuf_skip();
644 } 634 }
645 if (ps.in_decl) { 635 if (ps.in_decl) {
646 char *tp = buf_ptr; 636 char *tp = buf_ptr;
647 637
648 while (isalpha((unsigned char)*tp) || 638 while (isalpha((unsigned char)*tp) ||
649 isspace((unsigned char)*tp)) { 639 isspace((unsigned char)*tp)) {
650 if (++tp >= buf_end) 640 if (++tp >= buf_end)
651 fill_buffer(); 641 fill_buffer();
652 } 642 }
653 if (*tp == '(') 643 if (*tp == '(')
654 ps.procname[0] = ' '; 644 ps.procname[0] = ' ';
655 } 645 }
656 code = unary_op; 646 code = unary_op;
657 break; 647 break;
658 648
659 default: 649 default:
660 if (token[0] == '/' && (*buf_ptr == '*' || *buf_ptr == '/')) { 650 if (token[0] == '/' && (*buf_ptr == '*' || *buf_ptr == '/')) {
661 /* it is start of comment */ 651 /* it is start of comment */
662 *e_token++ = inbuf_next(); 652 *e_token++ = inbuf_next();
663 653
664 code = comment; 654 code = comment;
665 unary_delim = state->last_u_d; 655 unary_delim = state->last_u_d;
666 break; 656 break;
667 } 657 }
668 while (e_token[-1] == *buf_ptr || *buf_ptr == '=') { 658 while (e_token[-1] == *buf_ptr || *buf_ptr == '=') {
669 /* 659 /*
670 * handle ||, &&, etc, and also things as in int *****i 660 * handle ||, &&, etc, and also things as in int *****i
671 */ 661 */
672 check_size_token(1); 662 check_size_token(1);
673 *e_token++ = inbuf_next(); 663 *e_token++ = inbuf_next();
674 } 664 }
675 code = (state->last_u_d ? unary_op : binary_op); 665 code = (state->last_u_d ? unary_op : binary_op);
676 unary_delim = true; 666 unary_delim = true;
677 667
678 668
679 } /* end of switch */ 669 } /* end of switch */
680 if (buf_ptr >= buf_end) /* check for input buffer empty */ 670 if (buf_ptr >= buf_end) /* check for input buffer empty */
681 fill_buffer(); 671 fill_buffer();
682 state->last_u_d = unary_delim; 672 state->last_u_d = unary_delim;
683 check_size_token(1); 673 check_size_token(1);
684 *e_token = '\0'; /* null terminate the token */ 674 *e_token = '\0'; /* null terminate the token */
685 return lexi_end(code); 675 return lexi_end(code);
686} 676}
687 677
688void 678void
689alloc_typenames(void) 679alloc_typenames(void)
690{ 680{
691 681
692 typenames = malloc(sizeof(typenames[0]) * (typename_count = 16)); 682 typenames = malloc(sizeof(typenames[0]) * (typename_count = 16));
693 if (typenames == NULL) 683 if (typenames == NULL)
694 err(1, NULL); 684 err(1, NULL);
695} 685}
696 686
697void 687void
698add_typename(const char *key) 688add_typename(const char *key)
699{ 689{
700 int comparison; 690 int comparison;
701 const char *copy; 691 const char *copy;
702 692
703 if (typename_top + 1 >= typename_count) { 693 if (typename_top + 1 >= typename_count) {
704 typenames = realloc((void *)typenames, 694 typenames = realloc((void *)typenames,
705 sizeof(typenames[0]) * (typename_count *= 2)); 695 sizeof(typenames[0]) * (typename_count *= 2));
706 if (typenames == NULL) 696 if (typenames == NULL)
707 err(1, NULL); 697 err(1, NULL);
708 } 698 }
709 if (typename_top == -1) 699 if (typename_top == -1)
710 typenames[++typename_top] = copy = strdup(key); 700 typenames[++typename_top] = copy = strdup(key);
711 else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) { 701 else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) {
712 /* take advantage of sorted input */ 702 /* take advantage of sorted input */
713 if (comparison == 0) /* remove duplicates */ 703 if (comparison == 0) /* remove duplicates */
714 return; 704 return;
715 typenames[++typename_top] = copy = strdup(key); 705 typenames[++typename_top] = copy = strdup(key);
716 } else { 706 } else {
717 int p; 707 int p;
718 708
719 for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++) 709 for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++)
720 /* find place for the new key */; 710 /* find place for the new key */;
721 if (comparison == 0) /* remove duplicates */ 711 if (comparison == 0) /* remove duplicates */
722 return; 712 return;
723 memmove(&typenames[p + 1], &typenames[p], 713 memmove(&typenames[p + 1], &typenames[p],
724 sizeof(typenames[0]) * (++typename_top - p)); 714 sizeof(typenames[0]) * (++typename_top - p));
725 typenames[p] = copy = strdup(key); 715 typenames[p] = copy = strdup(key);
726 } 716 }
727 717
728 if (copy == NULL) 718 if (copy == NULL)
729 err(1, NULL); 719 err(1, NULL);
730} 720}