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