1 /* $NetBSD: indent.c,v 1.17 2008/07/21 14:19:23 lukem Exp $ */
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 1976 Board of Trustees of the University of Illinois.
34 * Copyright (c) 1985 Sun Microsystems, Inc.
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 #include <sys/cdefs.h>
68 __COPYRIGHT("@(#) Copyright (c) 1985 Sun Microsystems, Inc.\
69 Copyright (c) 1976 Board of Trustees of the University of Illinois.\
70 Copyright (c) 1980, 1993\
71 The Regents of the University of California. All rights reserved.");
76 static char sccsid
[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93";
78 __RCSID("$NetBSD: indent.c,v 1.17 2008/07/21 14:19:23 lukem Exp $");
82 #include <sys/param.h>
93 #include "indent_globs.h"
95 #include "indent_codes.h"
97 const char *in_name
= "Standard Input"; /* will always point to name of
99 const char *out_name
= "Standard Output"; /* will always point to name of
101 char bakfile
[MAXPATHLEN
] = "";
103 int main(int, char **);
106 main(int argc
, char **argv
)
109 extern int found_err
; /* flag set in diag() on error */
110 int dec_ind
; /* current indentation for declarations */
111 int di_stack
[20]; /* a stack of structure indentation levels */
112 int flushed_nl
; /* used when buffering up comments to remember
113 * that a newline was passed over */
114 int force_nl
; /* when true, code must be broken */
115 int hd_type
; /* used to store type of stmt for if (...),
117 int i
; /* local loop counter */
118 int scase
; /* set to true when we see a case, so we will
119 * know what to do with the following colon */
120 int sp_sw
; /* when true, we are in the expressin of
121 * if(...), while(...), etc. */
122 int squest
; /* when this is positive, we have seen a ?
123 * without the matching : in a <c>?<s>:<s>
125 const char *t_ptr
; /* used for copying tokens */
126 int type_code
; /* the type of token, returned by lexi */
128 int last_else
= 0; /* true iff last keyword was an else */
131 /*-----------------------------------------------*\
133 \*-----------------------------------------------*/
135 if (!setlocale(LC_ALL
, ""))
136 fprintf(stderr
, "indent: can't set locale.\n");
139 ps
.p_stack
[0] = stmt
; /* this is the parser's stack */
140 ps
.last_nl
= true; /* this is true if the last thing scanned was
142 ps
.last_token
= semicolon
;
143 combuf
= (char *) malloc(bufsize
);
144 labbuf
= (char *) malloc(bufsize
);
145 codebuf
= (char *) malloc(bufsize
);
146 tokenbuf
= (char *) malloc(bufsize
);
147 l_com
= combuf
+ bufsize
- 5;
148 l_lab
= labbuf
+ bufsize
- 5;
149 l_code
= codebuf
+ bufsize
- 5;
150 l_token
= tokenbuf
+ bufsize
- 5;
151 combuf
[0] = codebuf
[0] = labbuf
[0] = ' '; /* set up code, label,
152 * and comment buffers */
153 combuf
[1] = codebuf
[1] = labbuf
[1] = '\0';
154 ps
.else_if
= 1; /* Default else-if special processing to on */
155 s_lab
= e_lab
= labbuf
+ 1;
156 s_code
= e_code
= codebuf
+ 1;
157 s_com
= e_com
= combuf
+ 1;
158 s_token
= e_token
= tokenbuf
+ 1;
160 in_buffer
= (char *) malloc(10);
161 in_buffer_limit
= in_buffer
+ 8;
162 buf_ptr
= buf_end
= in_buffer
;
164 had_eof
= ps
.in_decl
= ps
.decl_on_line
= break_comma
= false;
165 sp_sw
= force_nl
= false;
169 di_stack
[ps
.dec_nest
= 0] = 0;
170 ps
.want_blank
= ps
.in_stmt
= ps
.ind_stmt
= false;
173 scase
= ps
.pcase
= false;
183 /*--------------------------------------------------*\
184 | COMMAND LINE SCAN |
185 \*--------------------------------------------------*/
188 max_col
= 78; /* -l78 */
189 lineup_to_parens
= 1; /* -lp */
190 ps
.ljust_decl
= 0; /* -ndj */
191 ps
.com_ind
= 33; /* -c33 */
192 star_comment_cont
= 1; /* -sc */
193 ps
.ind_size
= 8; /* -i8 */
195 ps
.decl_indent
= 16; /* -di16 */
196 ps
.indent_parameters
= 1; /* -ip */
197 ps
.decl_com_ind
= 0; /* if this is not set to some positive value
198 * by an arg, we will set this equal to
200 btype_2
= 1; /* -br */
201 cuddle_else
= 1; /* -ce */
202 ps
.unindent_displace
= 0; /* -d0 */
203 ps
.case_indent
= 0; /* -cli0 */
204 format_col1_comments
= 1; /* -fc1 */
205 procnames_start_line
= 1; /* -psl */
206 proc_calls_space
= 0; /* -npcs */
207 comment_delimiter_on_blankline
= 1; /* -cdb */
208 ps
.leave_comma
= 1; /* -nbc */
211 for (i
= 1; i
< argc
; ++i
)
212 if (strcmp(argv
[i
], "-npro") == 0)
218 for (i
= 1; i
< argc
; ++i
) {
221 * look thru args (if any) for changes to defaults
223 if (argv
[i
][0] != '-') { /* no flag on parameter */
224 if (input
== 0) { /* we must have the input file */
225 in_name
= argv
[i
]; /* remember name of
227 input
= fopen(in_name
, "r");
228 if (input
== 0) /* check for open error */
229 err(1, "%s", in_name
);
232 if (output
== 0) { /* we have the output
234 out_name
= argv
[i
]; /* remember name of
236 if (strcmp(in_name
, out_name
) == 0) { /* attempt to overwrite
238 fprintf(stderr
, "indent: input and output files must be different\n");
241 output
= fopen(out_name
, "w");
242 if (output
== 0) /* check for create
244 err(1, "%s", out_name
);
247 fprintf(stderr
, "indent: unknown parameter: %s\n", argv
[i
]);
256 if (troff
|| input
== stdin
)
264 ps
.com_ind
= 2; /* dont put normal comments before column 2 */
266 if (bodyf
.font
[0] == 0)
267 parsefont(&bodyf
, "R");
268 if (scomf
.font
[0] == 0)
269 parsefont(&scomf
, "I");
270 if (blkcomf
.font
[0] == 0)
271 blkcomf
= scomf
, blkcomf
.size
+= 2;
272 if (boxcomf
.font
[0] == 0)
274 if (stringf
.font
[0] == 0)
275 parsefont(&stringf
, "L");
276 if (keywordf
.font
[0] == 0)
277 parsefont(&keywordf
, "B");
278 writefdef(&bodyf
, 'B');
279 writefdef(&scomf
, 'C');
280 writefdef(&blkcomf
, 'L');
281 writefdef(&boxcomf
, 'X');
282 writefdef(&stringf
, 'S');
283 writefdef(&keywordf
, 'K');
285 if (block_comment_max_col
<= 0)
286 block_comment_max_col
= max_col
;
287 if (ps
.decl_com_ind
<= 0) /* if not specified by user, set this */
288 ps
.decl_com_ind
= ps
.ljust_decl
? (ps
.com_ind
<= 10 ? 2 : ps
.com_ind
- 8) : ps
.com_ind
;
289 if (continuation_indent
== 0)
290 continuation_indent
= ps
.ind_size
;
291 fill_buffer(); /* get first batch of stuff into input buffer */
303 col
= ((col
- 1) & ~7) + 9;
308 if (col
> ps
.ind_size
)
309 ps
.ind_level
= ps
.i_l_follow
= col
/ ps
.ind_size
;
312 const char *p
= in_name
, *beg
= in_name
;
317 fprintf(output
, ".Fn \"%s\"\n", beg
);
323 while (1) { /* this is the main loop. it will go until we
327 type_code
= lexi(); /* lexi reads one token. The actual
328 * characters read are stored in
329 * "token". lexi returns a code
330 * indicating the type of token */
331 is_procname
= ps
.procname
[0];
334 * The following code moves everything following an if (), while (),
335 * else, etc. up to the start of the following stmt to a buffer. This
336 * allows proper handling of both kinds of brace placement.
340 while (ps
.search_brace
) { /* if we scanned an if(),
341 * while(), etc., we might
342 * need to copy stuff into a
343 * buffer we must loop,
345 * save_com, until we find the
346 * start of the stmt which
347 * follows the if, or whatever */
353 break; /* form feeds and newlines found here
356 case lbrace
: /* this is a brace that starts the
358 if (sc_end
== 0) { /* ignore buffering if a
359 * comment wasnt stored
361 ps
.search_brace
= false;
365 save_com
[0] = '{'; /* we either want to put
366 * the brace right after
368 goto sw_buffer
; /* go to common code to
369 * get out of this loop */
371 case comment
: /* we have a comment, so we must copy
372 * it into the buffer */
373 if (!flushed_nl
|| sc_end
!= 0) {
374 if (sc_end
== 0) { /* if this is the first
375 * comment, we must set
377 save_com
[0] = save_com
[1] = ' ';
378 sc_end
= &(save_com
[2]);
380 *sc_end
++ = '\n'; /* add newline between
385 *sc_end
++ = '/'; /* copy in start of
389 for (;;) { /* loop until we get to
392 *sc_end
= *buf_ptr
++;
393 if (buf_ptr
>= buf_end
)
396 if (*sc_end
++ == '*' && *buf_ptr
== '/')
397 break; /* we are at end of
400 if (sc_end
>= &(save_com
[sc_size
])) { /* check for temp buffer
402 diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
407 *sc_end
++ = '/'; /* add ending slash */
408 if (++buf_ptr
>= buf_end
) /* get past / in buffer */
412 default: /* it is the start of a normal
414 if (flushed_nl
) /* if we flushed a newline,
415 * make sure it is put back */
417 if ((type_code
== sp_paren
&& *token
== 'i'
418 && last_else
&& ps
.else_if
) ||
419 (type_code
== sp_nparen
&& *token
== 'e'
420 && e_code
!= s_code
&& e_code
[-1] == '}'))
423 if (sc_end
== 0) { /* ignore buffering if
424 * comment wasnt saved
426 ps
.search_brace
= false;
429 if (force_nl
) { /* if we should insert a nl
430 * here, put it into the
433 --line_no
; /* this will be
434 * re-increased when the
435 * nl is read from the
439 if (verbose
&& !flushed_nl
) /* print error msg if
442 diag(0, "Line broken");
445 for (t_ptr
= token
; *t_ptr
; ++t_ptr
)
446 *sc_end
++ = *t_ptr
; /* copy token into temp
451 ps
.search_brace
= false; /* stop looking for
453 bp_save
= buf_ptr
; /* save current input
456 buf_ptr
= save_com
; /* fix so that
457 * subsequent calls to
458 * lexi will take tokens
460 *sc_end
++ = ' '; /* add trailing blank,
465 } /* end of switch */
466 if (type_code
!= 0) /* we must make this check,
467 * just in case there was an
469 type_code
= lexi(); /* read another token */
470 /* if (ps.search_brace) ps.procname[0] = 0; */
471 if ((is_procname
= ps
.procname
[0]) && flushed_nl
472 && !procnames_start_line
&& ps
.in_decl
473 && type_code
== ident
)
475 } /* end of while (search_brace) */
478 if (type_code
== 0) { /* we got eof */
479 if (s_lab
!= e_lab
|| s_code
!= e_code
480 || s_com
!= e_com
) /* must dump end of line */
482 if (ps
.tos
> 1) /* check for balanced braces */
483 diag(1, "Stuff missing from end of file.");
486 printf("There were %d output lines and %d comments\n",
487 ps
.out_lines
, ps
.out_coms
);
488 printf("(Lines with comments)/(Lines with code): %6.3f\n",
489 (1.0 * ps
.com_lines
) / code_lines
);
495 (type_code
!= comment
) &&
496 (type_code
!= newline
) &&
497 (type_code
!= preesc
) &&
498 (type_code
!= form_feed
)) {
500 (type_code
!= semicolon
) &&
501 (type_code
!= lbrace
|| !btype_2
)) {
502 /* we should force a broken line here */
503 if (verbose
&& !flushed_nl
)
504 diag(0, "Line broken");
507 ps
.want_blank
= false; /* dont insert blank at
511 ps
.in_stmt
= true; /* turn on flag which causes
513 * indentation. this is turned
514 * off by a ; or '}' */
515 if (s_com
!= e_com
) { /* the turkey has embedded a
516 * comment in a line. fix it */
518 for (t_ptr
= s_com
; *t_ptr
; ++t_ptr
) {
523 *e_code
= '\0'; /* null terminate code sect */
524 ps
.want_blank
= false;
528 if (type_code
!= comment
) /* preserve force_nl
530 force_nl
= false; /* cancel forced newline
531 * after newline, form
536 /*-----------------------------------------------------*\
537 | do switch on type of token scanned |
538 \*-----------------------------------------------------*/
540 switch (type_code
) { /* now, decide what to do with the
543 case form_feed
:/* found a form feed in line */
544 ps
.use_ff
= true; /* a form feed is treated much
547 ps
.want_blank
= false;
551 if (ps
.last_token
!= comma
|| ps
.p_l_follow
> 0
552 || !ps
.leave_comma
|| ps
.block_init
|| !break_comma
|| s_com
!= e_com
) {
554 ps
.want_blank
= false;
556 ++line_no
; /* keep track of input line number */
559 case lparen
: /* got a '(' or '[' */
560 ++ps
.p_l_follow
; /* count parens to make Healy
562 if (ps
.want_blank
&& *token
!= '[' &&
563 (ps
.last_token
!= ident
|| proc_calls_space
564 || (ps
.its_a_keyword
&& (!ps
.sizeof_keyword
|| Bill_Shannon
))))
566 if (ps
.in_decl
&& !ps
.block_init
) {
567 if (troff
&& !ps
.dumped_decl_indent
&& !is_procname
&& ps
.last_token
== decl
) {
568 ps
.dumped_decl_indent
= 1;
569 sprintf(e_code
, "\n.Du %dp+\200p \"%s\"\n", dec_ind
* 7, token
);
570 e_code
+= strlen(e_code
);
572 while ((e_code
- s_code
) < dec_ind
) {
576 *e_code
++ = token
[0];
579 *e_code
++ = token
[0];
580 ps
.paren_indents
[ps
.p_l_follow
- 1] = e_code
- s_code
;
581 if (sp_sw
&& ps
.p_l_follow
== 1 && extra_expression_indent
582 && ps
.paren_indents
[0] < 2 * ps
.ind_size
)
583 ps
.paren_indents
[0] = 2 * ps
.ind_size
;
584 ps
.want_blank
= false;
585 if (ps
.in_or_st
&& *token
== '(' && ps
.tos
<= 2) {
587 * this is a kluge to make sure that declarations will be
588 * aligned right if proc decl has an explicit type on it, i.e.
591 parse(semicolon
); /* I said this was a
593 ps
.in_or_st
= false; /* turn off flag for
597 if (ps
.sizeof_keyword
)
598 ps
.sizeof_mask
|= 1 << ps
.p_l_follow
;
601 case rparen
: /* got a ')' or ']' */
603 if (ps
.cast_mask
& (1 << ps
.p_l_follow
) & ~ps
.sizeof_mask
) {
605 ps
.cast_mask
&= (1 << ps
.p_l_follow
) - 1;
607 ps
.sizeof_mask
&= (1 << ps
.p_l_follow
) - 1;
608 if (--ps
.p_l_follow
< 0) {
610 diag(0, "Extra %c", *token
);
612 if (e_code
== s_code
) /* if the paren starts the
614 ps
.paren_level
= ps
.p_l_follow
; /* then indent it */
616 *e_code
++ = token
[0];
617 ps
.want_blank
= true;
619 if (sp_sw
&& (ps
.p_l_follow
== 0)) { /* check for end of if
620 * (...), or some such */
622 force_nl
= true; /* must force newline
624 ps
.last_u_d
= true; /* inform lexi that a
625 * following operator is
627 ps
.in_stmt
= false; /* dont use stmt
631 parse(hd_type
); /* let parser worry about if,
634 ps
.search_brace
= btype_2
; /* this should insure
635 * that constructs such
637 * int[]{...} have their
642 case unary_op
: /* this could be any unary operation */
646 if (troff
&& !ps
.dumped_decl_indent
&& ps
.in_decl
&& !is_procname
) {
647 sprintf(e_code
, "\n.Du %dp+\200p \"%s\"\n", dec_ind
* 7, token
);
648 ps
.dumped_decl_indent
= 1;
649 e_code
+= strlen(e_code
);
651 const char *res
= token
;
653 if (ps
.in_decl
&& !ps
.block_init
) { /* if this is a unary op
654 * in a declaration, we
657 for (i
= 0; token
[i
]; ++i
); /* find length of token */
658 while ((e_code
- s_code
) < (dec_ind
- i
)) {
660 *e_code
++ = ' '; /* pad it */
663 if (troff
&& token
[0] == '-' && token
[1] == '>')
665 for (t_ptr
= res
; *t_ptr
; ++t_ptr
) {
670 ps
.want_blank
= false;
673 case binary_op
:/* any binary operation */
677 const char *res
= token
;
701 for (t_ptr
= res
; *t_ptr
; ++t_ptr
) {
703 *e_code
++ = *t_ptr
; /* move the operator */
706 ps
.want_blank
= true;
709 case postop
: /* got a trailing ++ or -- */
710 *e_code
++ = token
[0];
711 *e_code
++ = token
[1];
712 ps
.want_blank
= true;
715 case question
: /* got a ? */
716 squest
++; /* this will be used when a later
717 * colon appears so we can distinguish
718 * the <c>?<n>:<n> construct */
722 ps
.want_blank
= true;
725 case casestmt
: /* got word 'case' or 'default' */
726 scase
= true; /* so we can process the later colon
730 case colon
: /* got a ':' */
731 if (squest
> 0) { /* it is part of the <c>?<n>:
737 ps
.want_blank
= true;
742 ps
.want_blank
= false;
745 ps
.in_stmt
= false; /* seeing a label does not
746 * imply we are in a stmt */
747 for (t_ptr
= s_code
; *t_ptr
; ++t_ptr
)
748 *e_lab
++ = *t_ptr
; /* turn everything so
749 * far into a label */
755 force_nl
= ps
.pcase
= scase
; /* ps.pcase will be used
757 * decide how to indent
758 * the label. force_nl
759 * will force a case n:
763 ps
.want_blank
= false;
766 case semicolon
:/* got a ';' */
767 ps
.in_or_st
= false; /* we are not in an
768 * initialization or structure
770 scase
= false; /* these will only need resetting in a
773 if (ps
.last_token
== rparen
&& rparen_count
== 0)
774 ps
.in_parameter_declaration
= 0;
778 ps
.block_init_level
= 0;
781 if (ps
.in_decl
&& s_code
== e_code
&& !ps
.block_init
)
782 while ((e_code
- s_code
) < (dec_ind
- 1)) {
787 ps
.in_decl
= (ps
.dec_nest
> 0); /* if we were in a first
789 * declaration, we arent
792 if ((!sp_sw
|| hd_type
!= forstmt
) && ps
.p_l_follow
> 0) {
795 * This should be true iff there were unbalanced parens in the
796 * stmt. It is a bit complicated, because the semicolon might
799 diag(1, "Unbalanced parens");
801 if (sp_sw
) { /* this is a check for a if,
802 * while, etc. with unbalanced
805 parse(hd_type
); /* dont lose the if, or
810 ps
.want_blank
= true;
811 ps
.in_stmt
= (ps
.p_l_follow
> 0); /* we are no longer in
812 * the middle of a stmt */
814 if (!sp_sw
) { /* if not if for (;;) */
815 parse(semicolon
); /* let parser know about
817 force_nl
= true; /* force newline after a
822 case lbrace
: /* got a '{' */
823 ps
.in_stmt
= false; /* dont indent the {} */
825 force_nl
= true; /* force other stuff on
826 * same line as '{' onto
829 if (ps
.block_init_level
<= 0)
830 ps
.block_init_level
= 1;
832 ps
.block_init_level
++;
834 if (s_code
!= e_code
&& !ps
.block_init
) {
837 ps
.want_blank
= false;
839 if (ps
.in_parameter_declaration
&& !ps
.in_or_st
) {
842 ps
.want_blank
= false;
845 if (ps
.in_parameter_declaration
)
846 prefix_blankline_requested
= 0;
848 if (ps
.p_l_follow
> 0) { /* check for preceding
849 * unbalanced parens */
850 diag(1, "Unbalanced parens");
852 if (sp_sw
) { /* check for unclosed if, for,
856 ps
.ind_level
= ps
.i_l_follow
;
859 if (s_code
== e_code
)
860 ps
.ind_stmt
= false; /* dont put extra
861 * indentation on line
863 if (ps
.in_decl
&& ps
.in_or_st
) { /* this is either a
864 * structure declaration
866 di_stack
[ps
.dec_nest
++] = dec_ind
;
869 ps
.decl_on_line
= false; /* we cant be in the
871 * declaration, so dont
875 if (blanklines_after_declarations_at_proctop
876 && ps
.in_parameter_declaration
)
877 postfix_blankline_requested
= 1;
878 ps
.in_parameter_declaration
= 0;
881 parse(lbrace
); /* let parser know about this */
882 if (ps
.want_blank
) /* put a blank before '{' if
883 * '{' is not at start of line */
885 ps
.want_blank
= false;
887 ps
.just_saw_decl
= 0;
890 case rbrace
: /* got a '}' */
891 if (ps
.p_stack
[ps
.tos
] == decl
&& !ps
.block_init
) /* semicolons can be
895 if (ps
.p_l_follow
) { /* check for unclosed if, for,
897 diag(1, "Unbalanced parens");
901 ps
.just_saw_decl
= 0;
902 ps
.block_init_level
--;
903 if (s_code
!= e_code
&& !ps
.block_init
) { /* '}' must be first on
906 diag(0, "Line broken");
910 ps
.want_blank
= true;
911 ps
.in_stmt
= ps
.ind_stmt
= false;
912 if (ps
.dec_nest
> 0) { /* we are in multi-level
913 * structure declaration */
914 dec_ind
= di_stack
[--ps
.dec_nest
];
915 if (ps
.dec_nest
== 0 && !ps
.in_parameter_declaration
)
916 ps
.just_saw_decl
= 2;
919 prefix_blankline_requested
= 0;
920 parse(rbrace
); /* let parser know about this */
921 ps
.search_brace
= cuddle_else
&& ps
.p_stack
[ps
.tos
] == ifhead
922 && ps
.il
[ps
.tos
] >= ps
.ind_level
;
923 if (ps
.tos
<= 1 && blanklines_after_procs
&& ps
.dec_nest
<= 0)
924 postfix_blankline_requested
= 1;
927 case swstmt
: /* got keyword "switch" */
929 hd_type
= swstmt
; /* keep this for when we have
930 * seen the expression */
931 goto copy_id
; /* go move the token into buffer */
933 case sp_paren
: /* token is if, while, for */
934 sp_sw
= true; /* the interesting stuff is done after
935 * the expression is scanned */
936 hd_type
= (*token
== 'i' ? ifstmt
:
937 (*token
== 'w' ? whilestmt
: forstmt
));
940 * remember the type of header for later use by parser
942 goto copy_id
; /* copy the token into line */
944 case sp_nparen
:/* got else, do */
947 if (e_code
!= s_code
&& (!cuddle_else
|| e_code
[-1] != '}')) {
949 diag(0, "Line broken");
950 dump_line(); /* make sure this starts
952 ps
.want_blank
= false;
954 force_nl
= true; /* also, following stuff
955 * must go onto new line */
959 if (e_code
!= s_code
) { /* make sure this starts
962 diag(0, "Line broken");
964 ps
.want_blank
= false;
966 force_nl
= true; /* also, following stuff
967 * must go onto new line */
971 goto copy_id
; /* move the token into line */
973 case decl
: /* we have a declaration type (int, register,
975 parse(decl
); /* let parser worry about indentation */
976 if (ps
.last_token
== rparen
&& ps
.tos
<= 1) {
977 ps
.in_parameter_declaration
= 1;
978 if (s_code
!= e_code
) {
983 if (ps
.in_parameter_declaration
&& ps
.indent_parameters
&& ps
.dec_nest
== 0) {
984 ps
.ind_level
= ps
.i_l_follow
= 1;
987 ps
.in_or_st
= true; /* this might be a structure
990 ps
.in_decl
= ps
.decl_on_line
= true;
991 if ( /* !ps.in_or_st && */ ps
.dec_nest
<= 0)
992 ps
.just_saw_decl
= 2;
993 prefix_blankline_requested
= 0;
994 for (i
= 0; token
[i
++];); /* get length of token */
997 * dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent
1000 dec_ind
= ps
.decl_indent
> 0 ? ps
.decl_indent
: i
;
1003 case ident
: /* got an identifier or constant */
1004 if (ps
.in_decl
) { /* if we are in a declaration,
1005 * we must indent identifier */
1008 ps
.want_blank
= false;
1009 if (is_procname
== 0 || !procnames_start_line
) {
1010 if (!ps
.block_init
) {
1011 if (troff
&& !ps
.dumped_decl_indent
) {
1012 sprintf(e_code
, "\n.De %dp+\200p\n", dec_ind
* 7);
1013 ps
.dumped_decl_indent
= 1;
1014 e_code
+= strlen(e_code
);
1016 while ((e_code
- s_code
) < dec_ind
) {
1022 if (dec_ind
&& s_code
!= e_code
)
1025 ps
.want_blank
= false;
1028 if (sp_sw
&& ps
.p_l_follow
== 0) {
1038 if (troff
&& ps
.its_a_keyword
) {
1039 e_code
= chfont(&bodyf
, &keywordf
, e_code
);
1040 for (t_ptr
= token
; *t_ptr
; ++t_ptr
) {
1042 *e_code
++ = keywordf
.allcaps
1043 ? toupper((unsigned char)*t_ptr
)
1046 e_code
= chfont(&keywordf
, &bodyf
, e_code
);
1048 for (t_ptr
= token
; *t_ptr
; ++t_ptr
) {
1052 ps
.want_blank
= true;
1055 case period
: /* treat a period kind of like a binary
1057 *e_code
++ = '.'; /* move the period into line */
1058 ps
.want_blank
= false; /* dont put a blank after a
1063 ps
.want_blank
= (s_code
!= e_code
); /* only put blank after
1064 * comma if comma does
1065 * not start the line */
1066 if (ps
.in_decl
&& is_procname
== 0 && !ps
.block_init
)
1067 while ((e_code
- s_code
) < (dec_ind
- 1)) {
1073 if (ps
.p_l_follow
== 0) {
1074 if (ps
.block_init_level
<= 0)
1076 if (break_comma
&& (!ps
.leave_comma
|| compute_code_target() + (e_code
- s_code
) > max_col
- 8))
1081 case preesc
: /* got the character '#' */
1082 if ((s_com
!= e_com
) ||
1086 *e_lab
++ = '#'; /* move whole line to 'label' buffer */
1093 while (*buf_ptr
== ' ' || *buf_ptr
== '\t') {
1095 if (buf_ptr
>= buf_end
)
1098 while (*buf_ptr
!= '\n' || in_comment
) {
1100 *e_lab
= *buf_ptr
++;
1101 if (buf_ptr
>= buf_end
)
1106 *e_lab
++ = BACKSLASH
;
1108 *e_lab
++ = *buf_ptr
++;
1109 if (buf_ptr
>= buf_end
)
1114 if (*buf_ptr
== '*' && !in_comment
&& !quote
) {
1116 *e_lab
++ = *buf_ptr
++;
1117 com_start
= e_lab
- s_lab
- 2;
1129 if (*buf_ptr
== '/' && in_comment
) {
1131 *e_lab
++ = *buf_ptr
++;
1132 com_end
= e_lab
- s_lab
;
1138 while (e_lab
> s_lab
&& (e_lab
[-1] == ' ' || e_lab
[-1] == '\t'))
1140 if (e_lab
- s_lab
== com_end
&& bp_save
== 0) { /* comment on
1141 * preprocessor line */
1142 if (sc_end
== 0) /* if this is the first
1143 * comment, we must set
1145 sc_end
= &(save_com
[0]);
1147 *sc_end
++ = '\n'; /* add newline between
1152 memmove(sc_end
, s_lab
+ com_start
, com_end
- com_start
);
1153 sc_end
+= com_end
- com_start
;
1154 if (sc_end
>= &save_com
[sc_size
])
1156 e_lab
= s_lab
+ com_start
;
1157 while (e_lab
> s_lab
&& (e_lab
[-1] == ' ' || e_lab
[-1] == '\t'))
1159 bp_save
= buf_ptr
; /* save current input
1162 buf_ptr
= save_com
; /* fix so that
1163 * subsequent calls to
1164 * lexi will take tokens
1165 * out of save_com */
1166 *sc_end
++ = ' '; /* add trailing blank,
1171 *e_lab
= '\0'; /* null terminate line */
1175 if (strncmp(s_lab
, "#if", 3) == 0) {
1176 if (blanklines_around_conditional_compilation
) {
1178 prefix_blankline_requested
++;
1179 while ((c
= getc(input
)) == '\n');
1182 if (ifdef_level
< (int)(sizeof state_stack
/ sizeof state_stack
[0])) {
1183 match_state
[ifdef_level
].tos
= -1;
1184 state_stack
[ifdef_level
++] = ps
;
1186 diag(1, "#if stack overflow");
1188 if (strncmp(s_lab
, "#else", 5) == 0) {
1189 if (ifdef_level
<= 0)
1190 diag(1, "Unmatched #else");
1192 match_state
[ifdef_level
- 1] = ps
;
1193 ps
= state_stack
[ifdef_level
- 1];
1196 if (strncmp(s_lab
, "#endif", 6) == 0) {
1197 if (ifdef_level
<= 0)
1198 diag(1, "Unmatched #endif");
1204 * This match needs to be more intelligent before the
1207 if (match_state
[ifdef_level
].tos
>= 0
1208 && memcmp(&ps
, &match_state
[ifdef_level
], sizeof ps
))
1209 diag(0, "Syntactically inconsistant #ifdef alternatives.");
1212 if (blanklines_around_conditional_compilation
) {
1213 postfix_blankline_requested
++;
1214 n_real_blanklines
= 0;
1217 break; /* subsequent processing of the newline
1218 * character will cause the line to be printed */
1220 case comment
: /* we have gotten a start comment */
1221 /* this is a biggie */
1222 if (flushed_nl
) { /* we should force a broken
1226 ps
.want_blank
= false; /* dont insert blank at
1232 } /* end of big switch stmt */
1234 *e_code
= '\0'; /* make sure code section is null terminated */
1235 if (type_code
!= comment
&& type_code
!= newline
&& type_code
!= preesc
)
1236 ps
.last_token
= type_code
;
1237 } /* end of main while (1) loop */
1240 * copy input file to backup file if in_name is /blah/blah/blah/file, then
1241 * backup file will be ".Bfile" then make the backup file the input and
1242 * original input file the output
1248 char buff
[8 * 1024];
1251 /* construct file name .Bfile */
1252 for (p
= in_name
; *p
; p
++); /* skip to end of string */
1253 while (p
> in_name
&& *p
!= '/') /* find last '/' */
1257 sprintf(bakfile
, "%s.BAK", p
);
1259 /* copy in_name to backup file */
1260 bakchn
= creat(bakfile
, 0600);
1262 err(1, "%s", bakfile
);
1263 while ((n
= read(fileno(input
), buff
, sizeof buff
)) > 0)
1264 if (write(bakchn
, buff
, n
) != n
)
1265 err(1, "%s", bakfile
);
1267 err(1, "%s", in_name
);
1271 /* re-open backup file as the input file */
1272 input
= fopen(bakfile
, "r");
1274 err(1, "%s", bakfile
);
1275 /* now the original input file will be the output */
1276 output
= fopen(in_name
, "w");
1279 err(1, "%s", in_name
);