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