1 /* $NetBSD: indent.c,v 1.19 2014/09/04 04:06:07 mrg 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.19 2014/09/04 04:06:07 mrg 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 tabs_to_var
= 0; /* true if using tabs to indent to var name */
127 int type_code
; /* the type of token, returned by lexi */
129 int last_else
= 0; /* true iff last keyword was an else */
132 /*-----------------------------------------------*\
134 \*-----------------------------------------------*/
136 if (!setlocale(LC_ALL
, ""))
137 fprintf(stderr
, "indent: can't set locale.\n");
140 ps
.p_stack
[0] = stmt
; /* this is the parser's stack */
141 ps
.last_nl
= true; /* this is true if the last thing scanned was
143 ps
.last_token
= semicolon
;
144 combuf
= (char *) malloc(bufsize
);
145 labbuf
= (char *) malloc(bufsize
);
146 codebuf
= (char *) malloc(bufsize
);
147 tokenbuf
= (char *) malloc(bufsize
);
148 l_com
= combuf
+ bufsize
- 5;
149 l_lab
= labbuf
+ bufsize
- 5;
150 l_code
= codebuf
+ bufsize
- 5;
151 l_token
= tokenbuf
+ bufsize
- 5;
152 combuf
[0] = codebuf
[0] = labbuf
[0] = ' '; /* set up code, label,
153 * and comment buffers */
154 combuf
[1] = codebuf
[1] = labbuf
[1] = '\0';
155 ps
.else_if
= 1; /* Default else-if special processing to on */
156 s_lab
= e_lab
= labbuf
+ 1;
157 s_code
= e_code
= codebuf
+ 1;
158 s_com
= e_com
= combuf
+ 1;
159 s_token
= e_token
= tokenbuf
+ 1;
161 in_buffer
= (char *) malloc(10);
162 in_buffer_limit
= in_buffer
+ 8;
163 buf_ptr
= buf_end
= in_buffer
;
165 had_eof
= ps
.in_decl
= ps
.decl_on_line
= break_comma
= false;
166 sp_sw
= force_nl
= false;
170 di_stack
[ps
.dec_nest
= 0] = 0;
171 ps
.want_blank
= ps
.in_stmt
= ps
.ind_stmt
= false;
174 scase
= ps
.pcase
= false;
184 /*--------------------------------------------------*\
185 | COMMAND LINE SCAN |
186 \*--------------------------------------------------*/
189 max_col
= 78; /* -l78 */
190 lineup_to_parens
= 1; /* -lp */
191 ps
.ljust_decl
= 0; /* -ndj */
192 ps
.com_ind
= 33; /* -c33 */
193 star_comment_cont
= 1; /* -sc */
194 ps
.ind_size
= 8; /* -i8 */
196 ps
.decl_indent
= 16; /* -di16 */
197 ps
.indent_parameters
= 1; /* -ip */
198 ps
.decl_com_ind
= 0; /* if this is not set to some positive value
199 * by an arg, we will set this equal to
201 btype_2
= 1; /* -br */
202 cuddle_else
= 1; /* -ce */
203 ps
.unindent_displace
= 0; /* -d0 */
204 ps
.case_indent
= 0; /* -cli0 */
205 format_col1_comments
= 1; /* -fc1 */
206 procnames_start_line
= 1; /* -psl */
207 proc_calls_space
= 0; /* -npcs */
208 comment_delimiter_on_blankline
= 1; /* -cdb */
209 ps
.leave_comma
= 1; /* -nbc */
212 for (i
= 1; i
< argc
; ++i
)
213 if (strcmp(argv
[i
], "-npro") == 0)
219 for (i
= 1; i
< argc
; ++i
) {
222 * look thru args (if any) for changes to defaults
224 if (argv
[i
][0] != '-') { /* no flag on parameter */
225 if (input
== 0) { /* we must have the input file */
226 in_name
= argv
[i
]; /* remember name of
228 input
= fopen(in_name
, "r");
229 if (input
== 0) /* check for open error */
230 err(1, "%s", in_name
);
233 if (output
== 0) { /* we have the output
235 out_name
= argv
[i
]; /* remember name of
237 if (strcmp(in_name
, out_name
) == 0) { /* attempt to overwrite
239 fprintf(stderr
, "indent: input and output files must be different\n");
242 output
= fopen(out_name
, "w");
243 if (output
== 0) /* check for create
245 err(1, "%s", out_name
);
248 fprintf(stderr
, "indent: unknown parameter: %s\n", argv
[i
]);
257 if (troff
|| input
== stdin
)
265 ps
.com_ind
= 2; /* dont put normal comments before column 2 */
267 if (bodyf
.font
[0] == 0)
268 parsefont(&bodyf
, "R");
269 if (scomf
.font
[0] == 0)
270 parsefont(&scomf
, "I");
271 if (blkcomf
.font
[0] == 0)
272 blkcomf
= scomf
, blkcomf
.size
+= 2;
273 if (boxcomf
.font
[0] == 0)
275 if (stringf
.font
[0] == 0)
276 parsefont(&stringf
, "L");
277 if (keywordf
.font
[0] == 0)
278 parsefont(&keywordf
, "B");
279 writefdef(&bodyf
, 'B');
280 writefdef(&scomf
, 'C');
281 writefdef(&blkcomf
, 'L');
282 writefdef(&boxcomf
, 'X');
283 writefdef(&stringf
, 'S');
284 writefdef(&keywordf
, 'K');
286 if (block_comment_max_col
<= 0)
287 block_comment_max_col
= max_col
;
288 if (ps
.decl_com_ind
<= 0) /* if not specified by user, set this */
289 ps
.decl_com_ind
= ps
.ljust_decl
? (ps
.com_ind
<= 10 ? 2 : ps
.com_ind
- 8) : ps
.com_ind
;
290 if (continuation_indent
== 0)
291 continuation_indent
= ps
.ind_size
;
292 fill_buffer(); /* get first batch of stuff into input buffer */
304 col
= ((col
- 1) & ~7) + 9;
309 if (col
> ps
.ind_size
)
310 ps
.ind_level
= ps
.i_l_follow
= col
/ ps
.ind_size
;
313 const char *p
= in_name
, *beg
= in_name
;
318 fprintf(output
, ".Fn \"%s\"\n", beg
);
324 while (1) { /* this is the main loop. it will go until we
328 type_code
= lexi(); /* lexi reads one token. The actual
329 * characters read are stored in
330 * "token". lexi returns a code
331 * indicating the type of token */
332 is_procname
= ps
.procname
[0];
335 * The following code moves everything following an if (), while (),
336 * else, etc. up to the start of the following stmt to a buffer. This
337 * allows proper handling of both kinds of brace placement.
341 while (ps
.search_brace
) { /* if we scanned an if(),
342 * while(), etc., we might
343 * need to copy stuff into a
344 * buffer we must loop,
346 * save_com, until we find the
347 * start of the stmt which
348 * follows the if, or whatever */
354 break; /* form feeds and newlines found here
357 case lbrace
: /* this is a brace that starts the
359 if (sc_end
== 0) { /* ignore buffering if a
360 * comment wasnt stored
362 ps
.search_brace
= false;
366 save_com
[0] = '{'; /* we either want to put
367 * the brace right after
369 goto sw_buffer
; /* go to common code to
370 * get out of this loop */
372 case comment
: /* we have a comment, so we must copy
373 * it into the buffer */
374 if (!flushed_nl
|| sc_end
!= 0) {
375 if (sc_end
== 0) { /* if this is the first
376 * comment, we must set
378 save_com
[0] = save_com
[1] = ' ';
379 sc_end
= &(save_com
[2]);
381 *sc_end
++ = '\n'; /* add newline between
386 *sc_end
++ = '/'; /* copy in start of
390 for (;;) { /* loop until we get to
393 *sc_end
= *buf_ptr
++;
394 if (buf_ptr
>= buf_end
)
397 if (*sc_end
++ == '*' && *buf_ptr
== '/')
398 break; /* we are at end of
401 if (sc_end
>= &(save_com
[sc_size
])) { /* check for temp buffer
403 diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
408 *sc_end
++ = '/'; /* add ending slash */
409 if (++buf_ptr
>= buf_end
) /* get past / in buffer */
413 default: /* it is the start of a normal
415 if (flushed_nl
) /* if we flushed a newline,
416 * make sure it is put back */
418 if ((type_code
== sp_paren
&& *token
== 'i'
419 && last_else
&& ps
.else_if
) ||
420 (type_code
== sp_nparen
&& *token
== 'e'
421 && e_code
!= s_code
&& e_code
[-1] == '}'))
424 if (sc_end
== 0) { /* ignore buffering if
425 * comment wasnt saved
427 ps
.search_brace
= false;
430 if (force_nl
) { /* if we should insert a nl
431 * here, put it into the
434 --line_no
; /* this will be
435 * re-increased when the
436 * nl is read from the
440 if (verbose
&& !flushed_nl
) /* print error msg if
443 diag(0, "Line broken");
446 for (t_ptr
= token
; *t_ptr
; ++t_ptr
)
447 *sc_end
++ = *t_ptr
; /* copy token into temp
452 ps
.search_brace
= false; /* stop looking for
454 bp_save
= buf_ptr
; /* save current input
457 buf_ptr
= save_com
; /* fix so that
458 * subsequent calls to
459 * lexi will take tokens
461 *sc_end
++ = ' '; /* add trailing blank,
466 } /* end of switch */
467 if (type_code
!= 0) /* we must make this check,
468 * just in case there was an
470 type_code
= lexi(); /* read another token */
471 /* if (ps.search_brace) ps.procname[0] = 0; */
472 if ((is_procname
= ps
.procname
[0]) && flushed_nl
473 && !procnames_start_line
&& ps
.in_decl
474 && type_code
== ident
)
476 } /* end of while (search_brace) */
479 if (type_code
== 0) { /* we got eof */
480 if (s_lab
!= e_lab
|| s_code
!= e_code
481 || s_com
!= e_com
) /* must dump end of line */
483 if (ps
.tos
> 1) /* check for balanced braces */
484 diag(1, "Stuff missing from end of file.");
487 printf("There were %d output lines and %d comments\n",
488 ps
.out_lines
, ps
.out_coms
);
489 printf("(Lines with comments)/(Lines with code): %6.3f\n",
490 (1.0 * ps
.com_lines
) / code_lines
);
496 (type_code
!= comment
) &&
497 (type_code
!= newline
) &&
498 (type_code
!= preesc
) &&
499 (type_code
!= form_feed
)) {
501 (type_code
!= semicolon
) &&
502 (type_code
!= lbrace
|| !btype_2
)) {
503 /* we should force a broken line here */
504 if (verbose
&& !flushed_nl
)
505 diag(0, "Line broken");
508 ps
.want_blank
= false; /* dont insert blank at
512 ps
.in_stmt
= true; /* turn on flag which causes
514 * indentation. this is turned
515 * off by a ; or '}' */
516 if (s_com
!= e_com
) { /* the turkey has embedded a
517 * comment in a line. fix it */
519 for (t_ptr
= s_com
; *t_ptr
; ++t_ptr
) {
524 *e_code
= '\0'; /* null terminate code sect */
525 ps
.want_blank
= false;
529 if (type_code
!= comment
) /* preserve force_nl
531 force_nl
= false; /* cancel forced newline
532 * after newline, form
537 /*-----------------------------------------------------*\
538 | do switch on type of token scanned |
539 \*-----------------------------------------------------*/
541 switch (type_code
) { /* now, decide what to do with the
544 case form_feed
:/* found a form feed in line */
545 ps
.use_ff
= true; /* a form feed is treated much
548 ps
.want_blank
= false;
552 if (ps
.last_token
!= comma
|| ps
.p_l_follow
> 0
553 || !ps
.leave_comma
|| ps
.block_init
|| !break_comma
|| s_com
!= e_com
) {
555 ps
.want_blank
= false;
557 ++line_no
; /* keep track of input line number */
560 case lparen
: /* got a '(' or '[' */
561 ++ps
.p_l_follow
; /* count parens to make Healy
563 if (ps
.want_blank
&& *token
!= '[' &&
564 (ps
.last_token
!= ident
|| proc_calls_space
565 || (ps
.its_a_keyword
&& (!ps
.sizeof_keyword
|| Bill_Shannon
))))
567 if (ps
.in_decl
&& !ps
.block_init
) {
568 if (troff
&& !ps
.dumped_decl_indent
&& !is_procname
&& ps
.last_token
== decl
) {
569 ps
.dumped_decl_indent
= 1;
570 sprintf(e_code
, "\n.Du %dp+\200p \"%s\"\n", dec_ind
* 7, token
);
571 e_code
+= strlen(e_code
);
573 while ((e_code
- s_code
) < dec_ind
) {
577 *e_code
++ = token
[0];
580 *e_code
++ = token
[0];
581 ps
.paren_indents
[ps
.p_l_follow
- 1] = e_code
- s_code
;
582 if (sp_sw
&& ps
.p_l_follow
== 1 && extra_expression_indent
583 && ps
.paren_indents
[0] < 2 * ps
.ind_size
)
584 ps
.paren_indents
[0] = 2 * ps
.ind_size
;
585 ps
.want_blank
= false;
586 if (ps
.in_or_st
&& *token
== '(' && ps
.tos
<= 2) {
588 * this is a kluge to make sure that declarations will be
589 * aligned right if proc decl has an explicit type on it, i.e.
592 parse(semicolon
); /* I said this was a
594 ps
.in_or_st
= false; /* turn off flag for
598 if (ps
.sizeof_keyword
)
599 ps
.sizeof_mask
|= 1 << ps
.p_l_follow
;
602 case rparen
: /* got a ')' or ']' */
604 if (ps
.cast_mask
& (1 << ps
.p_l_follow
) & ~ps
.sizeof_mask
) {
606 ps
.cast_mask
&= (1 << ps
.p_l_follow
) - 1;
608 ps
.sizeof_mask
&= (1 << ps
.p_l_follow
) - 1;
609 if (--ps
.p_l_follow
< 0) {
611 diag(0, "Extra %c", *token
);
613 if (e_code
== s_code
) /* if the paren starts the
615 ps
.paren_level
= ps
.p_l_follow
; /* then indent it */
617 *e_code
++ = token
[0];
618 ps
.want_blank
= true;
620 if (sp_sw
&& (ps
.p_l_follow
== 0)) { /* check for end of if
621 * (...), or some such */
623 force_nl
= true; /* must force newline
625 ps
.last_u_d
= true; /* inform lexi that a
626 * following operator is
628 ps
.in_stmt
= false; /* dont use stmt
632 parse(hd_type
); /* let parser worry about if,
635 ps
.search_brace
= btype_2
; /* this should insure
636 * that constructs such
638 * int[]{...} have their
643 case unary_op
: /* this could be any unary operation */
647 if (troff
&& !ps
.dumped_decl_indent
&& ps
.in_decl
&& !is_procname
) {
648 sprintf(e_code
, "\n.Du %dp+\200p \"%s\"\n", dec_ind
* 7, token
);
649 ps
.dumped_decl_indent
= 1;
650 e_code
+= strlen(e_code
);
652 const char *res
= token
;
654 if (ps
.in_decl
&& !ps
.block_init
) { /* if this is a unary op
655 * in a declaration, we
658 for (i
= 0; token
[i
]; ++i
); /* find length of token */
659 while ((e_code
- s_code
) < (dec_ind
- i
)) {
661 *e_code
++ = ' '; /* pad it */
664 if (troff
&& token
[0] == '-' && token
[1] == '>')
666 for (t_ptr
= res
; *t_ptr
; ++t_ptr
) {
671 ps
.want_blank
= false;
674 case binary_op
:/* any binary operation */
678 const char *res
= token
;
702 for (t_ptr
= res
; *t_ptr
; ++t_ptr
) {
704 *e_code
++ = *t_ptr
; /* move the operator */
707 ps
.want_blank
= true;
710 case postop
: /* got a trailing ++ or -- */
711 *e_code
++ = token
[0];
712 *e_code
++ = token
[1];
713 ps
.want_blank
= true;
716 case question
: /* got a ? */
717 squest
++; /* this will be used when a later
718 * colon appears so we can distinguish
719 * the <c>?<n>:<n> construct */
723 ps
.want_blank
= true;
726 case casestmt
: /* got word 'case' or 'default' */
727 scase
= true; /* so we can process the later colon
731 case colon
: /* got a ':' */
732 if (squest
> 0) { /* it is part of the <c>?<n>:
738 ps
.want_blank
= true;
743 ps
.want_blank
= false;
746 ps
.in_stmt
= false; /* seeing a label does not
747 * imply we are in a stmt */
748 for (t_ptr
= s_code
; *t_ptr
; ++t_ptr
)
749 *e_lab
++ = *t_ptr
; /* turn everything so
750 * far into a label */
756 force_nl
= ps
.pcase
= scase
; /* ps.pcase will be used
758 * decide how to indent
759 * the label. force_nl
760 * will force a case n:
764 ps
.want_blank
= false;
767 case semicolon
:/* got a ';' */
768 ps
.in_or_st
= false; /* we are not in an
769 * initialization or structure
771 scase
= false; /* these will only need resetting in a
774 if (ps
.last_token
== rparen
&& rparen_count
== 0)
775 ps
.in_parameter_declaration
= 0;
779 ps
.block_init_level
= 0;
782 if (ps
.in_decl
&& s_code
== e_code
&& !ps
.block_init
)
783 while ((e_code
- s_code
) < (dec_ind
- 1)) {
788 ps
.in_decl
= (ps
.dec_nest
> 0); /* if we were in a first
790 * declaration, we arent
793 if ((!sp_sw
|| hd_type
!= forstmt
) && ps
.p_l_follow
> 0) {
796 * This should be true iff there were unbalanced parens in the
797 * stmt. It is a bit complicated, because the semicolon might
800 diag(1, "Unbalanced parens");
802 if (sp_sw
) { /* this is a check for a if,
803 * while, etc. with unbalanced
806 parse(hd_type
); /* dont lose the if, or
811 ps
.want_blank
= true;
812 ps
.in_stmt
= (ps
.p_l_follow
> 0); /* we are no longer in
813 * the middle of a stmt */
815 if (!sp_sw
) { /* if not if for (;;) */
816 parse(semicolon
); /* let parser know about
818 force_nl
= true; /* force newline after a
823 case lbrace
: /* got a '{' */
824 ps
.in_stmt
= false; /* dont indent the {} */
826 force_nl
= true; /* force other stuff on
827 * same line as '{' onto
830 if (ps
.block_init_level
<= 0)
831 ps
.block_init_level
= 1;
833 ps
.block_init_level
++;
835 if (s_code
!= e_code
&& !ps
.block_init
) {
838 ps
.want_blank
= false;
840 if (ps
.in_parameter_declaration
&& !ps
.in_or_st
) {
843 ps
.want_blank
= false;
846 if (ps
.in_parameter_declaration
)
847 prefix_blankline_requested
= 0;
849 if (ps
.p_l_follow
> 0) { /* check for preceding
850 * unbalanced parens */
851 diag(1, "Unbalanced parens");
853 if (sp_sw
) { /* check for unclosed if, for,
857 ps
.ind_level
= ps
.i_l_follow
;
860 if (s_code
== e_code
)
861 ps
.ind_stmt
= false; /* dont put extra
862 * indentation on line
864 if (ps
.in_decl
&& ps
.in_or_st
) { /* this is either a
865 * structure declaration
867 di_stack
[ps
.dec_nest
++] = dec_ind
;
870 ps
.decl_on_line
= false; /* we cant be in the
872 * declaration, so dont
876 if (blanklines_after_declarations_at_proctop
877 && ps
.in_parameter_declaration
)
878 postfix_blankline_requested
= 1;
879 ps
.in_parameter_declaration
= 0;
882 parse(lbrace
); /* let parser know about this */
883 if (ps
.want_blank
) /* put a blank before '{' if
884 * '{' is not at start of line */
886 ps
.want_blank
= false;
888 ps
.just_saw_decl
= 0;
891 case rbrace
: /* got a '}' */
892 if (ps
.p_stack
[ps
.tos
] == decl
&& !ps
.block_init
) /* semicolons can be
896 if (ps
.p_l_follow
) { /* check for unclosed if, for,
898 diag(1, "Unbalanced parens");
902 ps
.just_saw_decl
= 0;
903 ps
.block_init_level
--;
904 if (s_code
!= e_code
&& !ps
.block_init
) { /* '}' must be first on
907 diag(0, "Line broken");
911 ps
.want_blank
= true;
912 ps
.in_stmt
= ps
.ind_stmt
= false;
913 if (ps
.dec_nest
> 0) { /* we are in multi-level
914 * structure declaration */
915 dec_ind
= di_stack
[--ps
.dec_nest
];
916 if (ps
.dec_nest
== 0 && !ps
.in_parameter_declaration
)
917 ps
.just_saw_decl
= 2;
920 prefix_blankline_requested
= 0;
921 parse(rbrace
); /* let parser know about this */
922 ps
.search_brace
= cuddle_else
&& ps
.p_stack
[ps
.tos
] == ifhead
923 && ps
.il
[ps
.tos
] >= ps
.ind_level
;
924 if (ps
.tos
<= 1 && blanklines_after_procs
&& ps
.dec_nest
<= 0)
925 postfix_blankline_requested
= 1;
928 case swstmt
: /* got keyword "switch" */
930 hd_type
= swstmt
; /* keep this for when we have
931 * seen the expression */
932 goto copy_id
; /* go move the token into buffer */
934 case sp_paren
: /* token is if, while, for */
935 sp_sw
= true; /* the interesting stuff is done after
936 * the expression is scanned */
937 hd_type
= (*token
== 'i' ? ifstmt
:
938 (*token
== 'w' ? whilestmt
: forstmt
));
941 * remember the type of header for later use by parser
943 goto copy_id
; /* copy the token into line */
945 case sp_nparen
:/* got else, do */
948 if (e_code
!= s_code
&& (!cuddle_else
|| e_code
[-1] != '}')) {
950 diag(0, "Line broken");
951 dump_line(); /* make sure this starts
953 ps
.want_blank
= false;
955 force_nl
= true; /* also, following stuff
956 * must go onto new line */
960 if (e_code
!= s_code
) { /* make sure this starts
963 diag(0, "Line broken");
965 ps
.want_blank
= false;
967 force_nl
= true; /* also, following stuff
968 * must go onto new line */
972 goto copy_id
; /* move the token into line */
974 case decl
: /* we have a declaration type (int, register,
976 parse(decl
); /* let parser worry about indentation */
977 if (ps
.last_token
== rparen
&& ps
.tos
<= 1) {
978 ps
.in_parameter_declaration
= 1;
979 if (s_code
!= e_code
) {
984 if (ps
.in_parameter_declaration
&& ps
.indent_parameters
&& ps
.dec_nest
== 0) {
985 ps
.ind_level
= ps
.i_l_follow
= 1;
988 ps
.in_or_st
= true; /* this might be a structure
991 ps
.in_decl
= ps
.decl_on_line
= true;
992 if ( /* !ps.in_or_st && */ ps
.dec_nest
<= 0)
993 ps
.just_saw_decl
= 2;
994 prefix_blankline_requested
= 0;
995 for (i
= 0; token
[i
++];); /* get length of token */
998 * dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent
1001 dec_ind
= ps
.decl_indent
> 0 ? ps
.decl_indent
: i
;
1002 tabs_to_var
= (use_tabs
? ps
.decl_indent
> 0 : 0);
1005 case ident
: /* got an identifier or constant */
1006 if (ps
.in_decl
) { /* if we are in a declaration,
1007 * we must indent identifier */
1010 ps
.want_blank
= false;
1011 if (is_procname
== 0 || !procnames_start_line
) {
1012 if (!ps
.block_init
) {
1013 if (troff
&& !ps
.dumped_decl_indent
) {
1014 sprintf(e_code
, "\n.De %dp+\200p\n", dec_ind
* 7);
1015 ps
.dumped_decl_indent
= 1;
1016 e_code
+= strlen(e_code
);
1023 * in order to get the tab math right for
1024 * indentations that are not multiples of 8 we
1025 * need to modify both startpos and dec_ind
1026 * (cur_dec_ind) here by eight minus the
1027 * remainder of the current starting column
1028 * divided by eight. This seems to be a
1029 * properly working fix
1031 startpos
= e_code
- s_code
;
1032 cur_dec_ind
= dec_ind
;
1034 if ((ps
.ind_level
* ps
.ind_size
) % 8 != 0) {
1035 pos
+= (ps
.ind_level
* ps
.ind_size
) % 8;
1036 cur_dec_ind
+= (ps
.ind_level
* ps
.ind_size
) % 8;
1040 while ((pos
& ~7) + 8 <= cur_dec_ind
) {
1043 pos
= (pos
& ~7) + 8;
1046 while (pos
< cur_dec_ind
) {
1051 if (ps
.want_blank
&& e_code
- s_code
== startpos
)
1053 ps
.want_blank
= false;
1057 if (dec_ind
&& s_code
!= e_code
)
1060 ps
.want_blank
= false;
1063 if (sp_sw
&& ps
.p_l_follow
== 0) {
1073 if (troff
&& ps
.its_a_keyword
) {
1074 e_code
= chfont(&bodyf
, &keywordf
, e_code
);
1075 for (t_ptr
= token
; *t_ptr
; ++t_ptr
) {
1077 *e_code
++ = keywordf
.allcaps
1078 ? toupper((unsigned char)*t_ptr
)
1081 e_code
= chfont(&keywordf
, &bodyf
, e_code
);
1083 for (t_ptr
= token
; *t_ptr
; ++t_ptr
) {
1087 ps
.want_blank
= true;
1090 case period
: /* treat a period kind of like a binary
1092 *e_code
++ = '.'; /* move the period into line */
1093 ps
.want_blank
= false; /* dont put a blank after a
1098 ps
.want_blank
= (s_code
!= e_code
); /* only put blank after
1099 * comma if comma does
1100 * not start the line */
1101 if (ps
.in_decl
&& is_procname
== 0 && !ps
.block_init
)
1102 while ((e_code
- s_code
) < (dec_ind
- 1)) {
1108 if (ps
.p_l_follow
== 0) {
1109 if (ps
.block_init_level
<= 0)
1111 if (break_comma
&& (!ps
.leave_comma
|| compute_code_target() + (e_code
- s_code
) > max_col
- 8))
1116 case preesc
: /* got the character '#' */
1117 if ((s_com
!= e_com
) ||
1121 *e_lab
++ = '#'; /* move whole line to 'label' buffer */
1128 while (*buf_ptr
== ' ' || *buf_ptr
== '\t') {
1130 if (buf_ptr
>= buf_end
)
1133 while (*buf_ptr
!= '\n' || in_comment
) {
1135 *e_lab
= *buf_ptr
++;
1136 if (buf_ptr
>= buf_end
)
1141 *e_lab
++ = BACKSLASH
;
1143 *e_lab
++ = *buf_ptr
++;
1144 if (buf_ptr
>= buf_end
)
1149 if (*buf_ptr
== '*' && !in_comment
&& !quote
) {
1151 *e_lab
++ = *buf_ptr
++;
1152 com_start
= e_lab
- s_lab
- 2;
1164 if (*buf_ptr
== '/' && in_comment
) {
1166 *e_lab
++ = *buf_ptr
++;
1167 com_end
= e_lab
- s_lab
;
1173 while (e_lab
> s_lab
&& (e_lab
[-1] == ' ' || e_lab
[-1] == '\t'))
1175 if (e_lab
- s_lab
== com_end
&& bp_save
== 0) { /* comment on
1176 * preprocessor line */
1177 if (sc_end
== 0) /* if this is the first
1178 * comment, we must set
1180 sc_end
= &(save_com
[0]);
1182 *sc_end
++ = '\n'; /* add newline between
1187 memmove(sc_end
, s_lab
+ com_start
, com_end
- com_start
);
1188 sc_end
+= com_end
- com_start
;
1189 if (sc_end
>= &save_com
[sc_size
])
1191 e_lab
= s_lab
+ com_start
;
1192 while (e_lab
> s_lab
&& (e_lab
[-1] == ' ' || e_lab
[-1] == '\t'))
1194 bp_save
= buf_ptr
; /* save current input
1197 buf_ptr
= save_com
; /* fix so that
1198 * subsequent calls to
1199 * lexi will take tokens
1200 * out of save_com */
1201 *sc_end
++ = ' '; /* add trailing blank,
1206 *e_lab
= '\0'; /* null terminate line */
1210 if (strncmp(s_lab
, "#if", 3) == 0) {
1211 if (blanklines_around_conditional_compilation
) {
1213 prefix_blankline_requested
++;
1214 while ((c
= getc(input
)) == '\n');
1217 if (ifdef_level
< (int)(sizeof state_stack
/ sizeof state_stack
[0])) {
1218 match_state
[ifdef_level
].tos
= -1;
1219 state_stack
[ifdef_level
++] = ps
;
1221 diag(1, "#if stack overflow");
1223 if (strncmp(s_lab
, "#else", 5) == 0) {
1224 if (ifdef_level
<= 0)
1225 diag(1, "Unmatched #else");
1227 match_state
[ifdef_level
- 1] = ps
;
1228 ps
= state_stack
[ifdef_level
- 1];
1231 if (strncmp(s_lab
, "#endif", 6) == 0) {
1232 if (ifdef_level
<= 0)
1233 diag(1, "Unmatched #endif");
1239 * This match needs to be more intelligent before the
1242 if (match_state
[ifdef_level
].tos
>= 0
1243 && memcmp(&ps
, &match_state
[ifdef_level
], sizeof ps
))
1244 diag(0, "Syntactically inconsistant #ifdef alternatives.");
1247 if (blanklines_around_conditional_compilation
) {
1248 postfix_blankline_requested
++;
1249 n_real_blanklines
= 0;
1252 break; /* subsequent processing of the newline
1253 * character will cause the line to be printed */
1255 case comment
: /* we have gotten a start comment */
1256 /* this is a biggie */
1257 if (flushed_nl
) { /* we should force a broken
1261 ps
.want_blank
= false; /* dont insert blank at
1267 } /* end of big switch stmt */
1269 *e_code
= '\0'; /* make sure code section is null terminated */
1270 if (type_code
!= comment
&& type_code
!= newline
&& type_code
!= preesc
)
1271 ps
.last_token
= type_code
;
1272 } /* end of main while (1) loop */
1275 * copy input file to backup file if in_name is /blah/blah/blah/file, then
1276 * backup file will be ".Bfile" then make the backup file the input and
1277 * original input file the output
1283 char buff
[8 * 1024];
1286 /* construct file name .Bfile */
1287 for (p
= in_name
; *p
; p
++); /* skip to end of string */
1288 while (p
> in_name
&& *p
!= '/') /* find last '/' */
1292 sprintf(bakfile
, "%s.BAK", p
);
1294 /* copy in_name to backup file */
1295 bakchn
= creat(bakfile
, 0600);
1297 err(1, "%s", bakfile
);
1298 while ((n
= read(fileno(input
), buff
, sizeof buff
)) > 0)
1299 if (write(bakchn
, buff
, n
) != n
)
1300 err(1, "%s", bakfile
);
1302 err(1, "%s", in_name
);
1306 /* re-open backup file as the input file */
1307 input
= fopen(bakfile
, "r");
1309 err(1, "%s", bakfile
);
1310 /* now the original input file will be the output */
1311 output
= fopen(in_name
, "w");
1314 err(1, "%s", in_name
);