2 * SPDX-License-Identifier: BSD-4-Clause
4 * Copyright (c) 1985 Sun Microsystems, Inc.
5 * Copyright (c) 1976 Board of Trustees of the University of Illinois.
6 * Copyright (c) 1980, 1993
7 * The Regents of the University of California. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)indent.c 5.17 (Berkeley) 6/7/93
34 * $FreeBSD: head/usr.bin/indent/indent.c 340138 2018-11-04 19:24:49Z oshogbo $
37 #include <sys/param.h>
46 #include "indent_globs.h"
47 #include "indent_codes.h"
52 char *labbuf
, *s_lab
, *e_lab
, *l_lab
;
53 char *codebuf
, *s_code
, *e_code
, *l_code
;
54 char *combuf
, *s_com
, *e_com
, *l_com
;
55 char *tokenbuf
, *s_token
, *e_token
, *l_token
;
56 char *in_buffer
, *in_buffer_limit
;
57 char *buf_ptr
, *buf_end
;
61 char *save_com
, *sc_end
;
68 struct parser_state ps
;
70 struct parser_state state_stack
[5];
71 struct parser_state match_state
[5];
74 static void bakcopy(void);
75 static void indent_declaration(int, int);
77 const char *in_name
= "Standard Input"; /* will always point to name of input
79 const char *out_name
= "Standard Output"; /* will always point to name
81 const char *simple_backup_suffix
= ".BAK"; /* Suffix to use for backup
83 char bakfile
[MAXPATHLEN
] = "";
86 main(int argc
, char **argv
)
88 int dec_ind
; /* current indentation for declarations */
89 int di_stack
[20]; /* a stack of structure indentation levels */
90 int force_nl
; /* when true, code must be broken */
91 int hd_type
= 0; /* used to store type of stmt for if (...),
93 int i
; /* local loop counter */
94 int scase
; /* set to true when we see a case, so we will
95 * know what to do with the following colon */
96 int sp_sw
; /* when true, we are in the expression of
97 * if(...), while(...), etc. */
98 int squest
; /* when this is positive, we have seen a ?
99 * without the matching : in a <c>?<s>:<s>
101 const char *t_ptr
; /* used for copying tokens */
102 int tabs_to_var
; /* true if using tabs to indent to var name */
103 int type_code
; /* the type of token, returned by lexi */
105 int last_else
= 0; /* true iff last keyword was an else */
106 const char *profile_name
= NULL
;
107 const char *envval
= NULL
;
108 struct parser_state transient_state
; /* a copy for lookup */
110 /*-----------------------------------------------*\
112 \*-----------------------------------------------*/
116 ps
.p_stack
[0] = stmt
; /* this is the parser's stack */
117 ps
.last_nl
= true; /* this is true if the last thing scanned was
119 ps
.last_token
= semicolon
;
120 combuf
= (char *) malloc(bufsize
);
123 labbuf
= (char *) malloc(bufsize
);
126 codebuf
= (char *) malloc(bufsize
);
129 tokenbuf
= (char *) malloc(bufsize
);
130 if (tokenbuf
== NULL
)
134 l_com
= combuf
+ bufsize
- 5;
135 l_lab
= labbuf
+ bufsize
- 5;
136 l_code
= codebuf
+ bufsize
- 5;
137 l_token
= tokenbuf
+ bufsize
- 5;
138 combuf
[0] = codebuf
[0] = labbuf
[0] = ' '; /* set up code, label, and
140 combuf
[1] = codebuf
[1] = labbuf
[1] = '\0';
141 opt
.else_if
= 1; /* Default else-if special processing to on */
142 s_lab
= e_lab
= labbuf
+ 1;
143 s_code
= e_code
= codebuf
+ 1;
144 s_com
= e_com
= combuf
+ 1;
145 s_token
= e_token
= tokenbuf
+ 1;
147 in_buffer
= (char *) malloc(10);
148 if (in_buffer
== NULL
)
150 in_buffer_limit
= in_buffer
+ 8;
151 buf_ptr
= buf_end
= in_buffer
;
153 had_eof
= ps
.in_decl
= ps
.decl_on_line
= break_comma
= false;
154 sp_sw
= force_nl
= false;
158 di_stack
[ps
.dec_nest
= 0] = 0;
159 ps
.want_blank
= ps
.in_stmt
= ps
.ind_stmt
= false;
161 scase
= ps
.pcase
= false;
170 envval
= getenv("SIMPLE_BACKUP_SUFFIX");
172 simple_backup_suffix
= envval
;
174 /*--------------------------------------------------*\
175 | COMMAND LINE SCAN |
176 \*--------------------------------------------------*/
179 max_col
= 78; /* -l78 */
180 lineup_to_parens
= 1; /* -lp */
181 lineup_to_parens_always
= 0; /* -nlpl */
182 ps
.ljust_decl
= 0; /* -ndj */
183 ps
.com_ind
= 33; /* -c33 */
184 star_comment_cont
= 1; /* -sc */
185 ps
.ind_size
= 8; /* -i8 */
187 ps
.decl_indent
= 16; /* -di16 */
188 ps
.local_decl_indent
= -1; /* if this is not set to some nonnegative value
189 * by an arg, we will set this equal to
191 ps
.indent_parameters
= 1; /* -ip */
192 ps
.decl_com_ind
= 0; /* if this is not set to some positive value
193 * by an arg, we will set this equal to
195 btype_2
= 1; /* -br */
196 cuddle_else
= 1; /* -ce */
197 ps
.unindent_displace
= 0; /* -d0 */
198 ps
.case_indent
= 0; /* -cli0 */
199 format_block_comments
= 1; /* -fcb */
200 format_col1_comments
= 1; /* -fc1 */
201 procnames_start_line
= 1; /* -psl */
202 proc_calls_space
= 0; /* -npcs */
203 comment_delimiter_on_blankline
= 1; /* -cdb */
204 ps
.leave_comma
= 1; /* -nbc */
207 for (i
= 1; i
< argc
; ++i
)
208 if (strcmp(argv
[i
], "-npro") == 0)
210 else if (argv
[i
][0] == '-' && argv
[i
][1] == 'P' && argv
[i
][2] != '\0')
211 profile_name
= argv
[i
]; /* non-empty -P (set profile) */
214 set_profile(profile_name
);
216 for (i
= 1; i
< argc
; ++i
) {
219 * look thru args (if any) for changes to defaults
221 if (argv
[i
][0] != '-') { /* no flag on parameter */
222 if (input
== NULL
) { /* we must have the input file */
223 in_name
= argv
[i
]; /* remember name of input file */
224 input
= fopen(in_name
, "r");
225 if (input
== NULL
) /* check for open error */
226 err(1, "%s", in_name
);
229 else if (output
== NULL
) { /* we have the output file */
230 out_name
= argv
[i
]; /* remember name of output file */
231 if (strcmp(in_name
, out_name
) == 0) { /* attempt to overwrite
233 errx(1, "input and output files must be different");
235 output
= fopen(out_name
, "w");
236 if (output
== NULL
) /* check for create error */
237 err(1, "%s", out_name
);
240 errx(1, "unknown parameter: %s", argv
[i
]);
247 if (output
== NULL
) {
256 if (opt
.com_ind
<= 1)
257 opt
.com_ind
= 2; /* don't put normal comments before column 2 */
258 if (opt
.block_comment_max_col
<= 0)
259 opt
.block_comment_max_col
= opt
.max_col
;
260 if (opt
.local_decl_indent
< 0) /* if not specified by user, set this */
261 opt
.local_decl_indent
= opt
.decl_indent
;
262 if (opt
.decl_com_ind
<= 0) /* if not specified by user, set this */
263 opt
.decl_com_ind
= opt
.ljust_decl
? (opt
.com_ind
<= 10 ? 2 : opt
.com_ind
- 8) : opt
.com_ind
;
264 if (opt
.continuation_indent
== 0)
265 opt
.continuation_indent
= opt
.ind_size
;
266 fill_buffer(); /* get first batch of stuff into input buffer */
277 col
= opt
.tabsize
* (1 + (col
- 1) / opt
.tabsize
) + 1;
282 if (col
> opt
.ind_size
)
283 ps
.ind_level
= ps
.i_l_follow
= col
/ opt
.ind_size
;
290 while (1) { /* this is the main loop. it will go until we
292 int comment_buffered
= false;
294 type_code
= lexi(&ps
); /* lexi reads one token. The actual
295 * characters read are stored in "token". lexi
296 * returns a code indicating the type of token */
299 * The following code moves newlines and comments following an if (),
300 * while (), else, etc. up to the start of the following stmt to
301 * a buffer. This allows proper handling of both kinds of brace
302 * placement (-br, -bl) and cuddling "else" (-ce).
305 while (ps
.search_brace
) {
308 if (sc_end
== NULL
) {
310 save_com
[0] = save_com
[1] = ' ';
311 sc_end
= &save_com
[2];
315 * We may have inherited a force_nl == true from the previous
316 * token (like a semicolon). But once we know that a newline
317 * has been scanned in this loop, force_nl should be false.
319 * However, the force_nl == true must be preserved if newline
320 * is never scanned in this loop, so this assignment cannot be
327 if (sc_end
== NULL
) {
329 * Copy everything from the start of the line, because
330 * pr_comment() will use that to calculate original
331 * indentation of a boxed comment.
333 memcpy(sc_buf
, in_buffer
, buf_ptr
- in_buffer
- 4);
334 save_com
= sc_buf
+ (buf_ptr
- in_buffer
- 4);
335 save_com
[0] = save_com
[1] = ' ';
336 sc_end
= &save_com
[2];
338 comment_buffered
= true;
339 *sc_end
++ = '/'; /* copy in start of comment */
341 for (;;) { /* loop until we get to the end of the comment */
342 *sc_end
= *buf_ptr
++;
343 if (buf_ptr
>= buf_end
)
345 if (*sc_end
++ == '*' && *buf_ptr
== '/')
346 break; /* we are at end of comment */
347 if (sc_end
>= &save_com
[sc_size
]) { /* check for temp buffer
349 diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever");
355 *sc_end
++ = '/'; /* add ending slash */
356 if (++buf_ptr
>= buf_end
) /* get past / in buffer */
361 * Put KNF-style lbraces before the buffered up tokens and
362 * jump out of this loop in order to avoid copying the token
363 * again under the default case of the switch below.
365 if (sc_end
!= NULL
&& opt
.btype_2
) {
368 * Originally the lbrace may have been alone on its own
369 * line, but it will be moved into "the else's line", so
370 * if there was a newline resulting from the "{" before,
371 * it must be scanned now and ignored.
373 while (isspace((unsigned char)*buf_ptr
)) {
374 if (++buf_ptr
>= buf_end
)
376 if (*buf_ptr
== '\n')
382 default: /* it is the start of a normal statement */
388 (type_code
== sp_nparen
&& *token
== 'e' &&
389 e_code
!= s_code
&& e_code
[-1] == '}')
391 || (type_code
== sp_paren
&& *token
== 'i' &&
392 last_else
&& opt
.else_if
);
395 if (sc_end
== NULL
) { /* ignore buffering if
396 * comment wasn't saved up */
397 ps
.search_brace
= false;
400 while (sc_end
> save_com
&& isblank((unsigned char)sc_end
[-1])) {
403 if (opt
.swallow_optional_blanklines
||
404 (!comment_buffered
&& remove_newlines
)) {
405 force_nl
= !remove_newlines
;
406 while (sc_end
> save_com
&& sc_end
[-1] == '\n') {
410 if (force_nl
) { /* if we should insert a nl here, put
411 * it into the buffer */
413 --line_no
; /* this will be re-increased when the
414 * newline is read from the buffer */
417 if (opt
.verbose
) /* print error msg if the line was
418 * not already broken */
419 diag2(0, "Line broken");
421 for (t_ptr
= token
; *t_ptr
; ++t_ptr
)
425 ps
.search_brace
= false; /* stop looking for start of
427 bp_save
= buf_ptr
; /* save current input buffer */
429 buf_ptr
= save_com
; /* fix so that subsequent calls to
430 * lexi will take tokens out of
432 *sc_end
++ = ' ';/* add trailing blank, just in case */
437 } /* end of switch */
439 * We must make this check, just in case there was an unexpected
442 if (type_code
!= 0) {
444 * The only intended purpose of calling lexi() below is to
445 * categorize the next token in order to decide whether to
446 * continue buffering forthcoming tokens. Once the buffering
447 * is over, lexi() will be called again elsewhere on all of
448 * the tokens - this time for normal processing.
450 * Calling it for this purpose is a bug, because lexi() also
451 * changes the parser state and discards leading whitespace,
452 * which is needed mostly for comment-related considerations.
454 * Work around the former problem by giving lexi() a copy of
455 * the current parser state and discard it if the call turned
456 * out to be just a look ahead.
458 * Work around the latter problem by copying all whitespace
459 * characters into the buffer so that the later lexi() call
462 if (sc_end
!= NULL
) {
463 while (*buf_ptr
== ' ' || *buf_ptr
== '\t') {
464 *sc_end
++ = *buf_ptr
++;
465 if (sc_end
>= &save_com
[sc_size
]) {
466 errx(1, "input too long");
469 if (buf_ptr
>= buf_end
) {
473 transient_state
= ps
;
474 type_code
= lexi(&transient_state
); /* read another token */
475 if (type_code
!= newline
&& type_code
!= form_feed
&&
476 type_code
!= comment
&& !transient_state
.search_brace
) {
477 ps
= transient_state
;
480 } /* end of while (search_brace) */
483 if (type_code
== 0) { /* we got eof */
484 if (s_lab
!= e_lab
|| s_code
!= e_code
485 || s_com
!= e_com
) /* must dump end of line */
487 if (ps
.tos
> 1) /* check for balanced braces */
488 diag2(1, "Stuff missing from end of file");
491 printf("There were %d output lines and %d comments\n",
492 ps
.out_lines
, ps
.out_coms
);
493 printf("(Lines with comments)/(Lines with code): %6.3f\n",
494 (1.0 * ps
.com_lines
) / code_lines
);
500 (type_code
!= comment
) &&
501 (type_code
!= newline
) &&
502 (type_code
!= preesc
) &&
503 (type_code
!= form_feed
)) {
505 (type_code
!= semicolon
) &&
506 (type_code
!= lbrace
|| !opt
.btype_2
)) {
507 /* we should force a broken line here */
509 diag2(0, "Line broken");
511 ps
.want_blank
= false; /* dont insert blank at line start */
514 ps
.in_stmt
= true; /* turn on flag which causes an extra level of
515 * indentation. this is turned off by a ; or
517 if (s_com
!= e_com
) { /* the turkey has embedded a comment
518 * in a line. fix it */
519 int len
= e_com
- s_com
;
521 CHECK_SIZE_CODE(len
+ 3);
523 memcpy(e_code
, s_com
, len
);
526 *e_code
= '\0'; /* null terminate code sect */
527 ps
.want_blank
= false;
531 else if (type_code
!= comment
) /* preserve force_nl thru a comment */
532 force_nl
= false; /* cancel forced newline after newline, form
537 /*-----------------------------------------------------*\
538 | do switch on type of token scanned |
539 \*-----------------------------------------------------*/
540 CHECK_SIZE_CODE(3); /* maximum number of increments of e_code
541 * before the next CHECK_SIZE_CODE or
542 * dump_line() is 2. After that there's the
543 * final increment for the null character. */
544 switch (type_code
) { /* now, decide what to do with the token */
546 case form_feed
: /* found a form feed in line */
547 ps
.use_ff
= true; /* a form feed is treated much like a newline */
549 ps
.want_blank
= false;
553 if (ps
.last_token
!= comma
|| ps
.p_l_follow
> 0
554 || !opt
.leave_comma
|| ps
.block_init
|| !break_comma
|| s_com
!= e_com
) {
556 ps
.want_blank
= false;
558 ++line_no
; /* keep track of input line number */
561 case lparen
: /* got a '(' or '[' */
562 /* count parens to make Healy happy */
563 if (++ps
.p_l_follow
== nitems(ps
.paren_indents
)) {
564 diag3(0, "Reached internal limit of %d unclosed parens",
565 nitems(ps
.paren_indents
));
569 /* not a function pointer declaration or a function call */;
570 else if (ps
.in_decl
&& !ps
.block_init
&& !ps
.dumped_decl_indent
&&
571 ps
.procname
[0] == '\0' && ps
.paren_level
== 0) {
572 /* function pointer declarations */
573 indent_declaration(dec_ind
, tabs_to_var
);
574 ps
.dumped_decl_indent
= true;
576 else if (ps
.want_blank
&&
577 ((ps
.last_token
!= ident
&& ps
.last_token
!= funcname
) ||
578 opt
.proc_calls_space
||
579 /* offsetof (1) is never allowed a space; sizeof (2) gets
580 * one iff -bs; all other keywords (>2) always get a space
582 ps
.keyword
+ opt
.Bill_Shannon
> 2))
584 ps
.want_blank
= false;
585 *e_code
++ = token
[0];
586 ps
.paren_indents
[ps
.p_l_follow
- 1] = count_spaces_until(1, s_code
, e_code
) - 1;
587 if (sp_sw
&& ps
.p_l_follow
== 1 && opt
.extra_expression_indent
588 && ps
.paren_indents
[0] < 2 * opt
.ind_size
)
589 ps
.paren_indents
[0] = 2 * opt
.ind_size
;
590 if (ps
.in_or_st
&& *token
== '(' && ps
.tos
<= 2) {
592 * this is a kluge to make sure that declarations will be
593 * aligned right if proc decl has an explicit type on it, i.e.
596 parse(semicolon
); /* I said this was a kluge... */
597 ps
.in_or_st
= false; /* turn off flag for structure decl or
600 /* parenthesized type following sizeof or offsetof is not a cast */
601 if (ps
.keyword
== 1 || ps
.keyword
== 2)
602 ps
.not_cast_mask
|= 1 << ps
.p_l_follow
;
605 case rparen
: /* got a ')' or ']' */
606 if (ps
.cast_mask
& (1 << ps
.p_l_follow
) & ~ps
.not_cast_mask
) {
608 ps
.cast_mask
&= (1 << ps
.p_l_follow
) - 1;
609 ps
.want_blank
= opt
.space_after_cast
;
611 ps
.want_blank
= true;
612 ps
.not_cast_mask
&= (1 << ps
.p_l_follow
) - 1;
613 if (--ps
.p_l_follow
< 0) {
615 diag3(0, "Extra %c", *token
);
617 if (e_code
== s_code
) /* if the paren starts the line */
618 ps
.paren_level
= ps
.p_l_follow
; /* then indent it */
620 *e_code
++ = token
[0];
622 if (sp_sw
&& (ps
.p_l_follow
== 0)) { /* check for end of if
623 * (...), or some such */
625 force_nl
= true;/* must force newline after if */
626 ps
.last_u_d
= true; /* inform lexi that a following
627 * operator is unary */
628 ps
.in_stmt
= false; /* dont use stmt continuation
631 parse(hd_type
); /* let parser worry about if, or whatever */
633 ps
.search_brace
= opt
.btype_2
; /* this should ensure that
634 * constructs such as main(){...}
635 * and int[]{...} have their braces
636 * put in the right place */
639 case unary_op
: /* this could be any unary operation */
640 if (!ps
.dumped_decl_indent
&& ps
.in_decl
&& !ps
.block_init
&&
641 ps
.procname
[0] == '\0' && ps
.paren_level
== 0) {
642 /* pointer declarations */
645 * if this is a unary op in a declaration, we should indent
648 for (i
= 0; token
[i
]; ++i
)
649 /* find length of token */;
650 indent_declaration(dec_ind
- i
, tabs_to_var
);
651 ps
.dumped_decl_indent
= true;
653 else if (ps
.want_blank
)
657 int len
= e_token
- s_token
;
659 CHECK_SIZE_CODE(len
);
660 memcpy(e_code
, token
, len
);
663 ps
.want_blank
= false;
666 case binary_op
: /* any binary operation */
668 int len
= e_token
- s_token
;
670 CHECK_SIZE_CODE(len
+ 1);
673 memcpy(e_code
, token
, len
);
676 ps
.want_blank
= true;
679 case postop
: /* got a trailing ++ or -- */
680 *e_code
++ = token
[0];
681 *e_code
++ = token
[1];
682 ps
.want_blank
= true;
685 case question
: /* got a ? */
686 squest
++; /* this will be used when a later colon
687 * appears so we can distinguish the
688 * <c>?<n>:<n> construct */
692 ps
.want_blank
= true;
695 case casestmt
: /* got word 'case' or 'default' */
696 scase
= true; /* so we can process the later colon properly */
699 case colon
: /* got a ':' */
700 if (squest
> 0) { /* it is part of the <c>?<n>: <n> construct */
705 ps
.want_blank
= true;
710 ps
.want_blank
= false;
713 ps
.in_stmt
= false; /* seeing a label does not imply we are in a
716 * turn everything so far into a label
719 int len
= e_code
- s_code
;
721 CHECK_SIZE_LAB(len
+ 3);
722 memcpy(e_lab
, s_code
, len
);
728 force_nl
= ps
.pcase
= scase
; /* ps.pcase will be used by
729 * dump_line to decide how to
730 * indent the label. force_nl
731 * will force a case n: to be
732 * on a line by itself */
734 ps
.want_blank
= false;
737 case semicolon
: /* got a ';' */
738 if (ps
.dec_nest
== 0)
739 ps
.in_or_st
= false;/* we are not in an initialization or
740 * structure declaration */
741 scase
= false; /* these will only need resetting in an error */
743 if (ps
.last_token
== rparen
)
744 ps
.in_parameter_declaration
= 0;
746 ps
.not_cast_mask
= 0;
748 ps
.block_init_level
= 0;
751 if (ps
.in_decl
&& s_code
== e_code
&& !ps
.block_init
&&
752 !ps
.dumped_decl_indent
&& ps
.paren_level
== 0) {
753 /* indent stray semicolons in declarations */
754 indent_declaration(dec_ind
- 1, tabs_to_var
);
755 ps
.dumped_decl_indent
= true;
758 ps
.in_decl
= (ps
.dec_nest
> 0); /* if we were in a first level
759 * structure declaration, we
762 if ((!sp_sw
|| hd_type
!= forstmt
) && ps
.p_l_follow
> 0) {
765 * This should be true iff there were unbalanced parens in the
766 * stmt. It is a bit complicated, because the semicolon might
769 diag2(1, "Unbalanced parens");
771 if (sp_sw
) { /* this is a check for an if, while, etc. with
772 * unbalanced parens */
774 parse(hd_type
); /* dont lose the if, or whatever */
778 ps
.want_blank
= true;
779 ps
.in_stmt
= (ps
.p_l_follow
> 0); /* we are no longer in the
780 * middle of a stmt */
782 if (!sp_sw
) { /* if not if for (;;) */
783 parse(semicolon
); /* let parser know about end of stmt */
784 force_nl
= true;/* force newline after an end of stmt */
788 case lbrace
: /* got a '{' */
789 ps
.in_stmt
= false; /* dont indent the {} */
791 force_nl
= true;/* force other stuff on same line as '{' onto
793 else if (ps
.block_init_level
<= 0)
794 ps
.block_init_level
= 1;
796 ps
.block_init_level
++;
798 if (s_code
!= e_code
&& !ps
.block_init
) {
801 ps
.want_blank
= false;
803 else if (ps
.in_parameter_declaration
&& !ps
.in_or_st
) {
805 if (opt
.function_brace_split
) { /* dump the line prior
806 * to the brace ... */
808 ps
.want_blank
= false;
809 } else /* add a space between the decl and brace */
810 ps
.want_blank
= true;
813 if (ps
.in_parameter_declaration
)
814 prefix_blankline_requested
= 0;
816 if (ps
.p_l_follow
> 0) { /* check for preceding unbalanced
818 diag2(1, "Unbalanced parens");
820 if (sp_sw
) { /* check for unclosed if, for, etc. */
823 ps
.ind_level
= ps
.i_l_follow
;
826 if (s_code
== e_code
)
827 ps
.ind_stmt
= false; /* dont put extra indentation on line
829 if (ps
.in_decl
&& ps
.in_or_st
) { /* this is either a structure
830 * declaration or an init */
831 di_stack
[ps
.dec_nest
] = dec_ind
;
832 if (++ps
.dec_nest
== nitems(di_stack
)) {
833 diag3(0, "Reached internal limit of %d struct levels",
840 ps
.decl_on_line
= false; /* we can't be in the middle of
841 * a declaration, so don't do
842 * special indentation of
844 if (opt
.blanklines_after_declarations_at_proctop
845 && ps
.in_parameter_declaration
)
846 postfix_blankline_requested
= 1;
847 ps
.in_parameter_declaration
= 0;
851 parse(lbrace
); /* let parser know about this */
852 if (ps
.want_blank
) /* put a blank before '{' if '{' is not at
855 ps
.want_blank
= false;
857 ps
.just_saw_decl
= 0;
860 case rbrace
: /* got a '}' */
861 if (ps
.p_stack
[ps
.tos
] == decl
&& !ps
.block_init
) /* semicolons can be
865 if (ps
.p_l_follow
) {/* check for unclosed if, for, else. */
866 diag2(1, "Unbalanced parens");
870 ps
.just_saw_decl
= 0;
871 ps
.block_init_level
--;
872 if (s_code
!= e_code
&& !ps
.block_init
) { /* '}' must be first on
875 diag2(0, "Line broken");
879 ps
.want_blank
= true;
880 ps
.in_stmt
= ps
.ind_stmt
= false;
881 if (ps
.dec_nest
> 0) { /* we are in multi-level structure
883 dec_ind
= di_stack
[--ps
.dec_nest
];
884 if (ps
.dec_nest
== 0 && !ps
.in_parameter_declaration
)
885 ps
.just_saw_decl
= 2;
888 prefix_blankline_requested
= 0;
889 parse(rbrace
); /* let parser know about this */
890 ps
.search_brace
= opt
.cuddle_else
&& ps
.p_stack
[ps
.tos
] == ifhead
891 && ps
.il
[ps
.tos
] >= ps
.ind_level
;
892 if (ps
.tos
<= 1 && opt
.blanklines_after_procs
&& ps
.dec_nest
<= 0)
893 postfix_blankline_requested
= 1;
896 case swstmt
: /* got keyword "switch" */
898 hd_type
= swstmt
; /* keep this for when we have seen the
900 goto copy_id
; /* go move the token into buffer */
902 case sp_paren
: /* token is if, while, for */
903 sp_sw
= true; /* the interesting stuff is done after the
904 * expression is scanned */
905 hd_type
= (*token
== 'i' ? ifstmt
:
906 (*token
== 'w' ? whilestmt
: forstmt
));
909 * remember the type of header for later use by parser
911 goto copy_id
; /* copy the token into line */
913 case sp_nparen
: /* got else, do */
916 if (e_code
!= s_code
&& (!opt
.cuddle_else
|| e_code
[-1] != '}')) {
918 diag2(0, "Line broken");
919 dump_line();/* make sure this starts a line */
920 ps
.want_blank
= false;
922 force_nl
= true;/* also, following stuff must go onto new line */
927 if (e_code
!= s_code
) { /* make sure this starts a line */
929 diag2(0, "Line broken");
931 ps
.want_blank
= false;
933 force_nl
= true;/* also, following stuff must go onto new line */
937 goto copy_id
; /* move the token into line */
941 prefix_blankline_requested
= 0;
945 if (ps
.p_l_follow
> 0)
948 case decl
: /* we have a declaration type (int, etc.) */
949 parse(decl
); /* let parser worry about indentation */
950 if (ps
.last_token
== rparen
&& ps
.tos
<= 1) {
951 if (s_code
!= e_code
) {
956 if (ps
.in_parameter_declaration
&& opt
.indent_parameters
&& ps
.dec_nest
== 0) {
957 ps
.ind_level
= ps
.i_l_follow
= 1;
960 ps
.in_or_st
= true; /* this might be a structure or initialization
962 ps
.in_decl
= ps
.decl_on_line
= ps
.last_token
!= type_def
;
963 if ( /* !ps.in_or_st && */ ps
.dec_nest
<= 0)
964 ps
.just_saw_decl
= 2;
965 prefix_blankline_requested
= 0;
966 for (i
= 0; token
[i
++];); /* get length of token */
968 if (ps
.ind_level
== 0 || ps
.dec_nest
> 0) {
969 /* global variable or struct member in local variable */
970 dec_ind
= opt
.decl_indent
> 0 ? opt
.decl_indent
: i
;
971 tabs_to_var
= (opt
.use_tabs
? opt
.decl_indent
> 0 : 0);
974 dec_ind
= opt
.local_decl_indent
> 0 ? opt
.local_decl_indent
: i
;
975 tabs_to_var
= (opt
.use_tabs
? opt
.local_decl_indent
> 0 : 0);
980 case ident
: /* got an identifier or constant */
982 if (type_code
== funcname
) {
984 if (opt
.procnames_start_line
&& s_code
!= e_code
) {
988 else if (ps
.want_blank
) {
991 ps
.want_blank
= false;
993 else if (!ps
.block_init
&& !ps
.dumped_decl_indent
&&
994 ps
.paren_level
== 0) { /* if we are in a declaration, we
995 * must indent identifier */
996 indent_declaration(dec_ind
, tabs_to_var
);
997 ps
.dumped_decl_indent
= true;
998 ps
.want_blank
= false;
1001 else if (sp_sw
&& ps
.p_l_follow
== 0) {
1010 int len
= e_token
- s_token
;
1012 CHECK_SIZE_CODE(len
+ 1);
1015 memcpy(e_code
, s_token
, len
);
1018 if (type_code
!= funcname
)
1019 ps
.want_blank
= true;
1024 int len
= e_token
- s_token
;
1026 CHECK_SIZE_CODE(len
+ 1);
1029 memcpy(e_code
, token
, len
);
1032 ps
.want_blank
= false;
1035 case period
: /* treat a period kind of like a binary
1037 *e_code
++ = '.'; /* move the period into line */
1038 ps
.want_blank
= false; /* dont put a blank after a period */
1042 ps
.want_blank
= (s_code
!= e_code
); /* only put blank after comma
1043 * if comma does not start the
1045 if (ps
.in_decl
&& ps
.procname
[0] == '\0' && !ps
.block_init
&&
1046 !ps
.dumped_decl_indent
&& ps
.paren_level
== 0) {
1047 /* indent leading commas and not the actual identifiers */
1048 indent_declaration(dec_ind
- 1, tabs_to_var
);
1049 ps
.dumped_decl_indent
= true;
1052 if (ps
.p_l_follow
== 0) {
1053 if (ps
.block_init_level
<= 0)
1055 if (break_comma
&& (!opt
.leave_comma
||
1056 count_spaces_until(compute_code_target(), s_code
, e_code
) >
1057 opt
.max_col
- opt
.tabsize
))
1062 case preesc
: /* got the character '#' */
1063 if ((s_com
!= e_com
) ||
1068 *e_lab
++ = '#'; /* move whole line to 'label' buffer */
1075 while (*buf_ptr
== ' ' || *buf_ptr
== '\t') {
1077 if (buf_ptr
>= buf_end
)
1080 while (*buf_ptr
!= '\n' || (in_comment
&& !had_eof
)) {
1082 *e_lab
= *buf_ptr
++;
1083 if (buf_ptr
>= buf_end
)
1088 *e_lab
++ = *buf_ptr
++;
1089 if (buf_ptr
>= buf_end
)
1094 if (*buf_ptr
== '*' && !in_comment
&& !quote
) {
1096 *e_lab
++ = *buf_ptr
++;
1097 com_start
= e_lab
- s_lab
- 2;
1109 if (*buf_ptr
== '/' && in_comment
) {
1111 *e_lab
++ = *buf_ptr
++;
1112 com_end
= e_lab
- s_lab
;
1118 while (e_lab
> s_lab
&& (e_lab
[-1] == ' ' || e_lab
[-1] == '\t'))
1120 if (e_lab
- s_lab
== com_end
&& bp_save
== NULL
) {
1121 /* comment on preprocessor line */
1122 if (sc_end
== NULL
) { /* if this is the first comment,
1123 * we must set up the buffer */
1125 sc_end
= &save_com
[0];
1128 *sc_end
++ = '\n'; /* add newline between
1133 if (sc_end
- save_com
+ com_end
- com_start
> sc_size
)
1134 errx(1, "input too long");
1135 memmove(sc_end
, s_lab
+ com_start
, com_end
- com_start
);
1136 sc_end
+= com_end
- com_start
;
1137 e_lab
= s_lab
+ com_start
;
1138 while (e_lab
> s_lab
&& (e_lab
[-1] == ' ' || e_lab
[-1] == '\t'))
1140 bp_save
= buf_ptr
; /* save current input buffer */
1142 buf_ptr
= save_com
; /* fix so that subsequent calls to
1143 * lexi will take tokens out of
1145 *sc_end
++ = ' '; /* add trailing blank, just in case */
1150 *e_lab
= '\0'; /* null terminate line */
1154 if (strncmp(s_lab
, "#if", 3) == 0) { /* also ifdef, ifndef */
1155 if ((size_t)ifdef_level
< nitems(state_stack
)) {
1156 match_state
[ifdef_level
].tos
= -1;
1157 state_stack
[ifdef_level
++] = ps
;
1160 diag2(1, "#if stack overflow");
1162 else if (strncmp(s_lab
, "#el", 3) == 0) { /* else, elif */
1163 if (ifdef_level
<= 0)
1164 diag2(1, s_lab
[3] == 'i' ? "Unmatched #elif" : "Unmatched #else");
1166 match_state
[ifdef_level
- 1] = ps
;
1167 ps
= state_stack
[ifdef_level
- 1];
1170 else if (strncmp(s_lab
, "#endif", 6) == 0) {
1171 if (ifdef_level
<= 0)
1172 diag2(1, "Unmatched #endif");
1188 int d
= nitems(recognized
);
1190 if (strncmp(s_lab
+ 1, recognized
[d
].string
, recognized
[d
].size
) == 0)
1193 diag2(1, "Unrecognized cpp directive");
1197 if (opt
.blanklines_around_conditional_compilation
) {
1198 postfix_blankline_requested
++;
1199 n_real_blanklines
= 0;
1202 postfix_blankline_requested
= 0;
1203 prefix_blankline_requested
= 0;
1205 break; /* subsequent processing of the newline
1206 * character will cause the line to be printed */
1208 case comment
: /* we have gotten a / followed by * this is a biggie */
1211 } /* end of big switch stmt */
1213 *e_code
= '\0'; /* make sure code section is null terminated */
1214 if (type_code
!= comment
&& type_code
!= newline
&& type_code
!= preesc
)
1215 ps
.last_token
= type_code
;
1216 } /* end of main while (1) loop */
1220 * copy input file to backup file if in_name is /blah/blah/blah/file, then
1221 * backup file will be ".Bfile" then make the backup file the input and
1222 * original input file the output
1229 char buff
[8 * 1024];
1232 /* construct file name .Bfile */
1233 for (p
= in_name
; *p
; p
++); /* skip to end of string */
1234 while (p
> in_name
&& *p
!= '/') /* find last '/' */
1238 sprintf(bakfile
, "%s%s", p
, simple_backup_suffix
);
1240 /* copy in_name to backup file */
1241 bakchn
= creat(bakfile
, 0600);
1243 err(1, "%s", bakfile
);
1244 while ((n
= read(fileno(input
), buff
, sizeof(buff
))) > 0)
1245 if (write(bakchn
, buff
, n
) != n
)
1246 err(1, "%s", bakfile
);
1248 err(1, "%s", in_name
);
1252 /* re-open backup file as the input file */
1253 input
= fopen(bakfile
, "r");
1255 err(1, "%s", bakfile
);
1256 /* now the original input file will be the output */
1257 output
= fopen(in_name
, "w");
1258 if (output
== NULL
) {
1260 err(1, "%s", in_name
);
1265 indent_declaration(int cur_dec_ind
, int tabs_to_var
)
1267 int pos
= e_code
- s_code
;
1268 char *startpos
= e_code
;
1271 * get the tab math right for indentations that are not multiples of tabsize
1273 if ((ps
.ind_level
* opt
.ind_size
) % opt
.tabsize
!= 0) {
1274 pos
+= (ps
.ind_level
* opt
.ind_size
) % opt
.tabsize
;
1275 cur_dec_ind
+= (ps
.ind_level
* opt
.ind_size
) % opt
.tabsize
;
1280 CHECK_SIZE_CODE(cur_dec_ind
/ opt
.tabsize
);
1281 while ((tpos
= opt
.tabsize
* (1 + pos
/ opt
.tabsize
)) <= cur_dec_ind
) {
1286 CHECK_SIZE_CODE(cur_dec_ind
- pos
+ 1);
1287 while (pos
< cur_dec_ind
) {
1291 if (e_code
== startpos
&& ps
.want_blank
) {
1293 ps
.want_blank
= false;