xref: /csrg-svn/usr.bin/indent/indent.c (revision 34885)
121968Sdist /*
221968Sdist  * Copyright (c) 1980 Regents of the University of California.
333767Sbostic  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
433767Sbostic  * All rights reserved.
533767Sbostic  *
633767Sbostic  * Redistribution and use in source and binary forms are permitted
7*34885Sbostic  * provided that the above copyright notice and this paragraph are
8*34885Sbostic  * duplicated in all such forms and that any documentation,
9*34885Sbostic  * advertising materials, and other materials related to such
10*34885Sbostic  * distribution and use acknowledge that the software was developed
11*34885Sbostic  * by the University of California, Berkeley and the University
12*34885Sbostic  * of Illinois, Urbana.  The name of either
13*34885Sbostic  * University may not be used to endorse or promote products derived
14*34885Sbostic  * from this software without specific prior written permission.
15*34885Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16*34885Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17*34885Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1821968Sdist  */
198800Smckusick 
2021968Sdist #ifndef lint
2121968Sdist char copyright[] =
2221968Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
2333767Sbostic Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\
2421968Sdist  All rights reserved.\n";
2533767Sbostic #endif /* not lint */
2621968Sdist 
2721968Sdist #ifndef lint
28*34885Sbostic static char sccsid[] = "@(#)indent.c	5.8 (Berkeley) 06/29/88";
2933767Sbostic #endif /* not lint */
3021968Sdist 
3133767Sbostic /*
328800Smckusick NAME:
3324453Smckusick indent main program
3424453Smckusick 
358800Smckusick FUNCTION:
3624453Smckusick This is the main program of the indent program.  Indent will take a C
3724453Smckusick program source and reformat it into a semi-reasonable form.
3824453Smckusick 
398800Smckusick ALGORITHM:
4024453Smckusick The routine lexi scans tokens and passes them back one at a time to the
4124453Smckusick main routine.  The subroutine parse takes care of much of the work of
4224453Smckusick figuring indentation level.
4324453Smckusick 
4424453Smckusick 1) Call lexi
4524453Smckusick 2) Enter a monster switch statement on the code returned by lexi.  If
4624453Smckusick the indentation level for the line yet to be printed should be
4724453Smckusick changed, set the variable ps.ind_level.  If the indentation level for
4824453Smckusick the following line should be changed, set the variable ps.i_l_follow.
498800Smckusick 
5024453Smckusick */
5133228Sbostic #include "indent_globs.h"
5233228Sbostic #include "indent_codes.h"
538800Smckusick 
5424453Smckusick char       *in_name = "Standard Input";	/* will always point to name of
5524453Smckusick 					 * input file */
5624453Smckusick char       *out_name = "Standard Output";	/* will always point to
5724453Smckusick 						 * name of output file */
5824453Smckusick char        bakfile[32] = "";
598800Smckusick 
6024453Smckusick main(argc, argv)
6124453Smckusick     int         argc;
6224453Smckusick     char      **argv;
638800Smckusick {
6430984Sbostic     extern int	found_err;	/* if any error occurred */
658800Smckusick 
6624453Smckusick     int         dec_ind;	/* current indentation for declarations */
6724453Smckusick     int         di_stack[20];	/* a stack of structure indentation levels */
6824453Smckusick     int         flushed_nl;	/* used when buffering up comments to
6924453Smckusick 				 * remember that a newline was passed over */
7024453Smckusick     int         force_nl;	/* when true, code must be broken */
7124453Smckusick     int         hd_type;	/* used to store type of stmt for if
7224453Smckusick 				 * (...), for (...), etc */
7324453Smckusick     register int i;		/* local loop counter */
7424453Smckusick     register int j;		/* local loop counter */
7524453Smckusick     int         scase;		/* set to true when we see a case, so we
7624453Smckusick 				 * will know what to do with the following
7724453Smckusick 				 * colon */
7824453Smckusick     int         sp_sw;		/* when true, we are in the expressin of
7924453Smckusick 				 * if(...), while(...), etc. */
8024453Smckusick     int         squest;		/* when this is positive, we have seen a ?
8124453Smckusick 				 * without the matching : in a <c>?<s>:<s>
8224453Smckusick 				 * construct */
8324453Smckusick     register char *t_ptr;	/* used for copying tokens */
8424453Smckusick     int         type_code;	/* the type of token, returned by lexi */
858800Smckusick 
8624453Smckusick     int         last_else = 0;	/* true iff last keyword was an else */
878800Smckusick 
888800Smckusick 
8924453Smckusick     /*-----------------------------------------------*\
9024648Smckusick     |		      INITIALIZATION		      |
9124648Smckusick     \*-----------------------------------------------*/
928800Smckusick 
938800Smckusick 
9424453Smckusick     ps.p_stack[0] = stmt;	/* this is the parser's stack */
9524453Smckusick     ps.last_nl = true;		/* this is true if the last thing scanned
9624453Smckusick 				 * was a newline */
9724453Smckusick     ps.last_token = semicolon;
9824453Smckusick     combuf[0] = codebuf[0] = labbuf[0] = ' ';	/* set up code, label, and
9924453Smckusick 						 * comment buffers */
1008800Smckusick     combuf[1] = codebuf[1] = labbuf[1] = '\0';
1018800Smckusick     s_lab = e_lab = labbuf + 1;
1028800Smckusick     s_code = e_code = codebuf + 1;
1038800Smckusick     s_com = e_com = combuf + 1;
1048800Smckusick 
1058800Smckusick     buf_ptr = buf_end = in_buffer;
1068800Smckusick     line_no = 1;
10724453Smckusick     had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
1088800Smckusick     sp_sw = force_nl = false;
10924453Smckusick     ps.in_or_st = false;
11024453Smckusick     ps.bl_line = true;
1118800Smckusick     dec_ind = 0;
11224453Smckusick     di_stack[ps.dec_nest = 0] = 0;
11324453Smckusick     ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
1148800Smckusick 
1158800Smckusick 
11624453Smckusick     scase = ps.pcase = false;
1178800Smckusick     squest = 0;
1188800Smckusick     sc_end = 0;
1198800Smckusick     bp_save = 0;
1208800Smckusick     be_save = 0;
1218800Smckusick 
12224453Smckusick     output = 0;
1238800Smckusick 
1248800Smckusick 
1258800Smckusick 
12624453Smckusick     /*--------------------------------------------------*\
12724648Smckusick     |   COMMAND LINE SCAN
12824648Smckusick     \*--------------------------------------------------*/
1298800Smckusick 
13024648Smckusick     set_defaults();
1318800Smckusick 
13224648Smckusick     /*
13324648Smckusick      * Unfortunately, we must look for -npro here because the profiles
13424648Smckusick      * are read before the command line arguments.
13524648Smckusick      */
13624453Smckusick     for (i = 1; i < argc; ++i)
13724453Smckusick 	if (strcmp(argv[i], "-npro") == 0)
13824453Smckusick 	    break;
13924453Smckusick     if (i >= argc)
14024453Smckusick 	set_profile();
1418800Smckusick 
14224648Smckusick     input = 0;			/* cancel -st if it was in the profiles, */
14324648Smckusick     output = 0;			/* as it doesn't make any sense there. */
14424648Smckusick 
1458800Smckusick     for (i = 1; i < argc; ++i) {
14624453Smckusick 
14724453Smckusick 	/*
14824453Smckusick 	 * look thru args (if any) for changes to defaults
14924453Smckusick 	 */
1508800Smckusick 	if (argv[i][0] != '-') {/* no flag on parameter */
15124453Smckusick 	    if (input == 0) {	/* we must have the input file */
15224453Smckusick 		in_name = argv[i];	/* remember name of input file */
15324453Smckusick 		input = fopen(in_name, "r");
15424453Smckusick 		if (input == 0) {	/* check for open error */
15524648Smckusick 		    fprintf(stderr, "indent: can't open %s\n", argv[i]);
15624648Smckusick 		    exit(1);
1578800Smckusick 		}
1588800Smckusick 		continue;
15924453Smckusick 	    } else if (output == 0) {	/* we have the output file */
16024453Smckusick 		out_name = argv[i];	/* remember name of output file */
16124453Smckusick 		if (strcmp(in_name, out_name) == 0) {	/* attempt to overwrite
16224453Smckusick 							 * the file */
16324648Smckusick 		    fprintf(stderr, "indent: input and output files must be different\n");
16424648Smckusick 		    exit(1);
16524453Smckusick 		}
16624453Smckusick 		output = fopen(out_name, "w");
16724453Smckusick 		if (output == 0) {	/* check for create error */
16824648Smckusick 		    fprintf(stderr, "indent: can't create %s\n", argv[i]);
16924648Smckusick 		    exit(1);
17024453Smckusick 		}
17124453Smckusick 		continue;
1728800Smckusick 	    }
17324648Smckusick 	    fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]);
17424648Smckusick 	    exit(1);
17524453Smckusick 	} else
17624453Smckusick 	    set_option(argv[i]);
1778800Smckusick 
17824453Smckusick     }				/* end of for */
17924453Smckusick     if (input == 0) {
18024453Smckusick 	printf("Usage: indent file [ outfile ] [ options ]\n");
18124648Smckusick 	exit(1);
18224453Smckusick     }
18324453Smckusick     if (output == 0)
18424453Smckusick 	if (troff)
18524453Smckusick 	    output = stdout;
18624453Smckusick 	else {
18724453Smckusick 	    out_name = in_name;
18824453Smckusick 	    bakcopy();
1898800Smckusick 	}
19024648Smckusick 
19124648Smckusick     /*
19224648Smckusick      * Adjust parameters that are out of range, or set defaults if
19324648Smckusick      * no values were specified.
19424648Smckusick      */
19524453Smckusick     if (ps.com_ind <= 1)
19624453Smckusick 	ps.com_ind = 2;		/* dont put normal comments before column
19724453Smckusick 				 * 2 */
19824453Smckusick     if (block_comment_max_col <= 0)
19924453Smckusick 	block_comment_max_col = max_col;
20024453Smckusick     if (ps.decl_com_ind <= 0)	/* if not specified by user, set this */
20124648Smckusick 	ps.decl_com_ind = ps.ljust_decl ? ps.com_ind - 8 : ps.com_ind;
20224648Smckusick     if (ps.decl_com_ind <= 1)
20324648Smckusick 	ps.decl_com_ind = 2;
20424453Smckusick     if (continuation_indent == 0)
20524453Smckusick 	continuation_indent = ps.ind_size;
20624453Smckusick     fill_buffer();		/* get first batch of stuff into input
20724453Smckusick 				 * buffer */
2088800Smckusick 
20924453Smckusick     parse(semicolon);
21024453Smckusick     {
21124453Smckusick 	register char *p = buf_ptr;
21224453Smckusick 	register    col = 1;
2138800Smckusick 
21424453Smckusick 	while (1) {
21524453Smckusick 	    if (*p == ' ')
21624453Smckusick 		col++;
21724453Smckusick 	    else if (*p == '\t')
21824453Smckusick 		col = ((col - 1) & ~7) + 9;
21924453Smckusick 	    else
22024453Smckusick 		break;
22124453Smckusick 	    p++;
22224453Smckusick 	};
22324453Smckusick 	if (col > ps.ind_size)
22424453Smckusick 	    ps.ind_level = ps.i_l_follow = col / ps.ind_size;
2258800Smckusick     }
22624453Smckusick     if (troff) {
22724453Smckusick 	register char *p = in_name,
22824453Smckusick 	           *beg = in_name;
22924453Smckusick 
23024453Smckusick 	while (*p)
23124453Smckusick 	    if (*p++ == '/')
23224453Smckusick 		beg = p;
23324453Smckusick 	fprintf(output, ".Fn \"%s\"\n", beg);
2348800Smckusick     }
2358800Smckusick 
23624453Smckusick     /*
23724453Smckusick      * START OF MAIN LOOP
23824453Smckusick      */
2398800Smckusick 
24024453Smckusick     while (1) {			/* this is the main loop.  it will go
24124453Smckusick 				 * until we reach eof */
24224453Smckusick 	int         is_procname;
2438800Smckusick 
24424453Smckusick 	type_code = lexi();	/* lexi reads one token.  The actual
24524453Smckusick 				 * characters read are stored in "token".
24624453Smckusick 				 * lexi returns a code indicating the type
24724453Smckusick 				 * of token */
24824453Smckusick 	is_procname = ps.procname[0];
2498800Smckusick 
25024453Smckusick 	/*
25124453Smckusick 	 * The following code moves everything following an if (), while
25224453Smckusick 	 * (), else, etc. up to the start of the following stmt to a
25324453Smckusick 	 * buffer.  This allows proper handling of both kinds of brace
25424453Smckusick 	 * placement.
25524453Smckusick 	 */
2568800Smckusick 
2578800Smckusick 	flushed_nl = false;
25824453Smckusick 	while (ps.search_brace) {	/* if we scanned an if(), while(),
25924453Smckusick 					 * etc., we might need to copy
26024453Smckusick 					 * stuff into a buffer we must
26124453Smckusick 					 * loop, copying stuff into
26224453Smckusick 					 * save_com, until we find the
26324453Smckusick 					 * start of the stmt which follows
26424453Smckusick 					 * the if, or whatever */
2658800Smckusick 	    switch (type_code) {
26624453Smckusick 		case newline:
2678800Smckusick 		    ++line_no;
2688800Smckusick 		    flushed_nl = true;
26924453Smckusick 		case form_feed:
27024453Smckusick 		    break;	/* form feeds and newlines found here will
27124453Smckusick 				 * be ignored */
2728800Smckusick 
27324453Smckusick 		case lbrace:	/* this is a brace that starts the
27424453Smckusick 				 * compound stmt */
27524453Smckusick 		    if (sc_end == 0) {	/* ignore buffering if a comment
27624453Smckusick 					 * wasnt stored up */
27724453Smckusick 			ps.search_brace = false;
2788800Smckusick 			goto check_type;
2798800Smckusick 		    }
2808800Smckusick 		    if (btype_2) {
28124453Smckusick 			save_com[0] = '{';	/* we either want to put
28224453Smckusick 						 * the brace right after
28324453Smckusick 						 * the if */
28424453Smckusick 			goto sw_buffer;	/* go to common code to get out of
28524453Smckusick 					 * this loop */
2868800Smckusick 		    }
28724453Smckusick 		case comment:	/* we have a comment, so we must copy it
28824453Smckusick 				 * into the buffer */
28924453Smckusick 		    if (!flushed_nl) {
29024453Smckusick 			if (sc_end == 0) {	/* if this is the first
29124453Smckusick 						 * comment, we must set up
29224453Smckusick 						 * the buffer */
29324453Smckusick 			    save_com[0] = save_com[1] = ' ';
29424453Smckusick 			    sc_end = &(save_com[2]);
29524453Smckusick 			} else {
29624453Smckusick 			    *sc_end++ = '\n';	/* add newline between
29724453Smckusick 						 * comments */
29824453Smckusick 			    *sc_end++ = ' ';
29924453Smckusick 			    --line_no;
30024453Smckusick 			}
30124453Smckusick 			*sc_end++ = '/';	/* copy in start of
30224453Smckusick 						 * comment */
30324453Smckusick 			*sc_end++ = '*';
3048800Smckusick 
30524453Smckusick 			for (;;) {	/* loop until we get to the end of
30624453Smckusick 					 * the comment */
30724453Smckusick 			    *sc_end = *buf_ptr++;
30824453Smckusick 			    if (buf_ptr >= buf_end)
30924453Smckusick 				fill_buffer();
31024453Smckusick 
31124453Smckusick 			    if (*sc_end++ == '*' && *buf_ptr == '/')
31224453Smckusick 				break;	/* we are at end of comment */
31324453Smckusick 
31424453Smckusick 			    if (sc_end >= &(save_com[sc_size])) {	/* check for temp buffer
31524453Smckusick 									 * overflow */
31624453Smckusick 				diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
31724453Smckusick 				fflush(output);
31824648Smckusick 				exit(1);
31924453Smckusick 			    }
32024453Smckusick 			}
32124453Smckusick 			*sc_end++ = '/';	/* add ending slash */
32224453Smckusick 			if (++buf_ptr >= buf_end)	/* get past / in buffer */
32324453Smckusick 			    fill_buffer();
32424453Smckusick 			break;
32524453Smckusick 		    }
32624453Smckusick 		default:	/* it is the start of a normal statment */
32724453Smckusick 		    if (flushed_nl)	/* if we flushed a newline, make
32824453Smckusick 					 * sure it is put back */
3298800Smckusick 			force_nl = true;
33024453Smckusick 		    if (type_code == sp_paren && *token == 'i'
33124453Smckusick 			&& last_else && ps.else_if
33224453Smckusick 			|| type_code == sp_nparen && *token == 'e'
33324453Smckusick 			&& e_code != s_code && e_code[-1] == '}')
33424453Smckusick 			force_nl = false;
3358800Smckusick 
33624453Smckusick 		    if (sc_end == 0) {	/* ignore buffering if comment
33724453Smckusick 					 * wasnt saved up */
33824453Smckusick 			ps.search_brace = false;
3398800Smckusick 			goto check_type;
3408800Smckusick 		    }
34124453Smckusick 		    if (force_nl) {	/* if we should insert a nl here,
34224453Smckusick 					 * put it into the buffer */
3438800Smckusick 			force_nl = false;
34424453Smckusick 			--line_no;	/* this will be re-increased when
34524453Smckusick 					 * the nl is read from the buffer */
3468800Smckusick 			*sc_end++ = '\n';
3478800Smckusick 			*sc_end++ = ' ';
34824453Smckusick 			if (verbose && !flushed_nl)	/* print error msg if
34924453Smckusick 							 * the line was not
35024453Smckusick 							 * already broken */
35124453Smckusick 			    diag(0, "Line broken");
3528800Smckusick 			flushed_nl = false;
3538800Smckusick 		    }
3548800Smckusick 		    for (t_ptr = token; *t_ptr; ++t_ptr)
35524453Smckusick 			*sc_end++ = *t_ptr;	/* copy token into temp
35624453Smckusick 						 * buffer */
3578800Smckusick 
35824453Smckusick 	    sw_buffer:
35924453Smckusick 		    ps.search_brace = false;	/* stop looking for start
36024453Smckusick 						 * of stmt */
36124453Smckusick 		    bp_save = buf_ptr;	/* save current input buffer */
3628800Smckusick 		    be_save = buf_end;
36324453Smckusick 		    buf_ptr = save_com;	/* fix so that subsequent calls to
36424453Smckusick 					 * lexi will take tokens out of
36524453Smckusick 					 * save_com */
36624453Smckusick 		    *sc_end++ = ' ';	/* add trailing blank, just in
36724453Smckusick 					 * case */
3688800Smckusick 		    buf_end = sc_end;
3698800Smckusick 		    sc_end = 0;
3708800Smckusick 		    break;
37124453Smckusick 	    }			/* end of switch */
37224453Smckusick 	    if (type_code != 0)	/* we must make this check, just in case
37324453Smckusick 				 * there was an unexpected EOF */
37424453Smckusick 		type_code = lexi();	/* read another token */
37524453Smckusick 	    is_procname = ps.procname[0];
37624453Smckusick 	}			/* end of while (serach_brace) */
37724453Smckusick 	last_else = 0;
37824453Smckusick check_type:
37924453Smckusick 	if (type_code == 0) {	/* we got eof */
3808800Smckusick 	    if (s_lab != e_lab || s_code != e_code
38124453Smckusick 		|| s_com != e_com)	/* must dump end of line */
38224453Smckusick 		dump_line();
38324453Smckusick 	    if (ps.tos > 1)	/* check for balanced braces */
38424453Smckusick 		diag(1, "Stuff missing from end of file.");
3858800Smckusick 
3868800Smckusick 	    if (verbose) {
38724453Smckusick 		printf("There were %d output lines and %d comments\n",
38824453Smckusick 		       ps.out_lines, ps.out_coms);
38924453Smckusick 		printf("(Lines with comments)/(Lines with code): %6.3f\n",
39024453Smckusick 		       (1.0 * ps.com_lines) / code_lines);
3918800Smckusick 	    }
39224453Smckusick 	    fflush(output);
39330984Sbostic 	    exit(ps.tos > 1 || found_err);
3948800Smckusick 	}
3958800Smckusick 	if (
39624453Smckusick 	    (type_code != comment) &&
39724453Smckusick 	    (type_code != newline) &&
39824453Smckusick 	    (type_code != preesc) &&
39924453Smckusick 	    (type_code != form_feed)) {
4008800Smckusick 	    if (
40124453Smckusick 		force_nl
40224453Smckusick 		&&
40324453Smckusick 		(type_code != semicolon) &&
40424453Smckusick 		(
40524453Smckusick 		 type_code != lbrace
40624453Smckusick 		 ||
40724453Smckusick 		 !btype_2
40824453Smckusick 		 )) {		/* we should force a broken line here */
4098800Smckusick 		if (verbose && !flushed_nl)
41024453Smckusick 		    diag(0, "Line broken");
4118800Smckusick 		flushed_nl = false;
41224453Smckusick 		dump_line();
41324453Smckusick 		ps.want_blank = false;	/* dont insert blank at line start */
4148800Smckusick 		force_nl = false;
4158800Smckusick 	    }
41624453Smckusick 	    ps.in_stmt = true;	/* turn on flag which causes an extra
41724453Smckusick 				 * level of indentation. this is turned
41824453Smckusick 				 * off by a ; or '}' */
41924453Smckusick 	    if (s_com != e_com) {	/* the turkey has embedded a
42024453Smckusick 					 * comment in a line. fix it */
4218800Smckusick 		*e_code++ = ' ';
4228800Smckusick 		for (t_ptr = s_com; *t_ptr; ++t_ptr)
4238800Smckusick 		    *e_code++ = *t_ptr;
4248800Smckusick 		*e_code++ = ' ';
42524453Smckusick 		*e_code = '\0';	/* null terminate code sect */
42624453Smckusick 		ps.want_blank = false;
4278800Smckusick 		e_com = s_com;
4288800Smckusick 	    }
42924453Smckusick 	} else if (type_code != comment)	/* preserve force_nl thru
43024453Smckusick 						 * a comment */
43124453Smckusick 	    force_nl = false;
4328800Smckusick 
43324453Smckusick 	/*
43424453Smckusick 	 * cancel forced newline after newline, form feed, etc
43524453Smckusick 	 */
4368800Smckusick 
4378800Smckusick 
4388800Smckusick 
43924453Smckusick 	/*----------------------------------------------------*\
44024648Smckusick 	|   do switch on type of token scanned
44124648Smckusick 	\*----------------------------------------------------*/
44224453Smckusick 	switch (type_code) {	/* now, decide what to do with the token */
44324453Smckusick 
44424453Smckusick 	    case form_feed:	/* found a form feed in line */
44524453Smckusick 		ps.use_ff = true;	/* a form feed is treated much
44624453Smckusick 					 * like a newline */
44724453Smckusick 		dump_line();
44824453Smckusick 		ps.want_blank = false;
4498800Smckusick 		break;
4508800Smckusick 
45124453Smckusick 	    case newline:
45224453Smckusick 		if (ps.last_token != comma || ps.p_l_follow > 0
45324453Smckusick 		    || !ps.leave_comma || !break_comma || s_com != e_com) {
45424453Smckusick 		    dump_line();
45524453Smckusick 		    ps.want_blank = false;
45624453Smckusick 		}
45724453Smckusick 		++line_no;	/* keep track of input line number */
4588800Smckusick 		break;
4598800Smckusick 
46024453Smckusick 	    case lparen:	/* got a '(' or '[' */
46124453Smckusick 		++ps.p_l_follow;/* count parens to make Healy happy */
46224453Smckusick 		if (ps.want_blank && *token != '[' &&
46324453Smckusick 		    (ps.last_token != ident || proc_calls_space
46424453Smckusick 		     || (ps.its_a_keyword && !ps.sizeof_keyword)))
4658800Smckusick 		    *e_code++ = ' ';
46624453Smckusick 		if (ps.in_decl && !ps.block_init)
46724453Smckusick 		    if (troff && !ps.dumped_decl_indent) {
46824453Smckusick 			ps.dumped_decl_indent = 1;
46924453Smckusick 			sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
47024453Smckusick 			e_code += strlen(e_code);
47124453Smckusick 		    } else {
47224453Smckusick 			while ((e_code - s_code) < dec_ind)
47324453Smckusick 			    *e_code++ = ' ';
47424453Smckusick 			*e_code++ = token[0];
47524453Smckusick 		} else
47624453Smckusick 		    *e_code++ = token[0];
47724453Smckusick 		ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
47824453Smckusick 		ps.want_blank = false;
47924453Smckusick 		if (ps.in_or_st && *token == '(') {
4808800Smckusick 
48124453Smckusick 		    /*
48224453Smckusick 		     * this is a kluge to make sure that declarations will
48324453Smckusick 		     * be aligned right if proc decl has an explicit type
48424453Smckusick 		     * on it, i.e. "int a(x) {..."
48524453Smckusick 		     */
48624453Smckusick 		    parse(semicolon);	/* I said this was a kluge... */
48724453Smckusick 		    ps.in_or_st = false;	/* turn off flag for
48824453Smckusick 						 * structure decl or
48924453Smckusick 						 * initialization */
4908800Smckusick 		}
49124453Smckusick 		if (ps.sizeof_keyword) ps.sizeof_mask |= 1<<ps.p_l_follow;
4928800Smckusick 		break;
4938800Smckusick 
49424453Smckusick 	    case rparen:	/* got a ')' or ']' */
49524453Smckusick 		if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
49624453Smckusick 		    ps.last_u_d = true;
49724453Smckusick 		    ps.cast_mask &= (1 << ps.p_l_follow) - 1;
4988800Smckusick 		}
49924453Smckusick 		ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
50024453Smckusick 		if (--ps.p_l_follow < 0) {
50124453Smckusick 		    ps.p_l_follow = 0;
50224453Smckusick 		    diag(0, "Extra %c", *token);
50324453Smckusick 		}
50424453Smckusick 		if (e_code == s_code)	/* if the paren starts the line */
50524453Smckusick 		    ps.paren_level = ps.p_l_follow;	/* then indent it */
5068800Smckusick 
5078800Smckusick 		*e_code++ = token[0];
50824453Smckusick 		ps.want_blank = true;
5098800Smckusick 
51024453Smckusick 		if (sp_sw && (ps.p_l_follow == 0)) {	/* check for end of if
51124453Smckusick 							 * (...), or some such */
5128800Smckusick 		    sp_sw = false;
51324453Smckusick 		    force_nl = true;	/* must force newline after if */
51424453Smckusick 		    ps.last_u_d = true;	/* inform lexi that a following
51524453Smckusick 					 * operator is unary */
51624453Smckusick 		    ps.in_stmt = false;	/* dont use stmt continuation
51724453Smckusick 					 * indentation */
5188800Smckusick 
51924453Smckusick 		    parse(hd_type);	/* let parser worry about if, or
52024453Smckusick 					 * whatever */
5218800Smckusick 		}
52224453Smckusick 		ps.search_brace = btype_2;	/* this should insure that
52324453Smckusick 						 * constructs such as
52424453Smckusick 						 * main(){...} and
52524453Smckusick 						 * int[]{...} have their
52624453Smckusick 						 * braces put in the right
52724453Smckusick 						 * place */
5288800Smckusick 		break;
5298800Smckusick 
53024453Smckusick 	    case unary_op:	/* this could be any unary operation */
53124453Smckusick 		if (ps.want_blank)
5328800Smckusick 		    *e_code++ = ' ';
5338800Smckusick 
53424453Smckusick 		if (troff && !ps.dumped_decl_indent && ps.in_decl) {
53524453Smckusick 		    sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
53624453Smckusick 		    ps.dumped_decl_indent = 1;
53724453Smckusick 		    e_code += strlen(e_code);
53824453Smckusick 		} else {
53924453Smckusick 		    char       *res = token;
54024453Smckusick 
54124453Smckusick 		    if (ps.in_decl && !ps.block_init) {	/* if this is a unary op
54224453Smckusick 							 * in a declaration, we
54324453Smckusick 							 * should indent this
54424453Smckusick 							 * token */
54524453Smckusick 			for (i = 0; token[i]; ++i);	/* find length of token */
54624453Smckusick 			while ((e_code - s_code) < (dec_ind - i))
54724453Smckusick 			    *e_code++ = ' ';	/* pad it */
54824453Smckusick 		    }
54924453Smckusick 		    if (troff && token[0] == '-' && token[1] == '>')
55024453Smckusick 			res = "\\(->";
55124453Smckusick 		    for (t_ptr = res; *t_ptr; ++t_ptr)
55224453Smckusick 			*e_code++ = *t_ptr;
5538800Smckusick 		}
55424453Smckusick 		ps.want_blank = false;
5558800Smckusick 		break;
5568800Smckusick 
55724453Smckusick 	    case binary_op:	/* any binary operation */
55824453Smckusick 	do_binary:
55924453Smckusick 		if (ps.want_blank)
5608800Smckusick 		    *e_code++ = ' ';
56124453Smckusick 		{
56224453Smckusick 		    char       *res = token;
56324453Smckusick 
56424453Smckusick 		    if (troff)
56524453Smckusick 			switch (token[0]) {
56624453Smckusick 			    case '<':
56724453Smckusick 				if (token[1] == '=')
56824453Smckusick 				    res = "\\(<=";
56924453Smckusick 				break;
57024453Smckusick 			    case '>':
57124453Smckusick 				if (token[1] == '=')
57224453Smckusick 				    res = "\\(>=";
57324453Smckusick 				break;
57424453Smckusick 			    case '!':
57524453Smckusick 				if (token[1] == '=')
57624453Smckusick 				    res = "\\(!=";
57724453Smckusick 				break;
57824453Smckusick 			    case '|':
57924453Smckusick 				if (token[1] == '|')
58024453Smckusick 				    res = "\\(br\\(br";
58124453Smckusick 				else if (token[1] == 0)
58224453Smckusick 				    res = "\\(br";
58324453Smckusick 				break;
58424676Smckusick 			    case '-':
58524676Smckusick 				if (token[1] == '>')
58624676Smckusick 				    res = "\\(->";
58724453Smckusick 			}
58824453Smckusick 		    for (t_ptr = res; *t_ptr; ++t_ptr)
58924453Smckusick 			*e_code++ = *t_ptr;	/* move the operator */
59024453Smckusick 		}
59124453Smckusick 		ps.want_blank = true;
5928800Smckusick 		break;
5938800Smckusick 
59424453Smckusick 	    case postop:	/* got a trailing ++ or -- */
5958800Smckusick 		*e_code++ = token[0];
5968800Smckusick 		*e_code++ = token[1];
59724453Smckusick 		ps.want_blank = true;
5988800Smckusick 		break;
5998800Smckusick 
60024453Smckusick 	    case question:	/* got a ? */
60124453Smckusick 		squest++;	/* this will be used when a later colon
60224453Smckusick 				 * appears so we can distinguish the
60324453Smckusick 				 * <c>?<n>:<n> construct */
60424453Smckusick 		if (ps.want_blank)
6058800Smckusick 		    *e_code++ = ' ';
6068800Smckusick 		*e_code++ = '?';
60724453Smckusick 		ps.want_blank = true;
6088800Smckusick 		break;
6098800Smckusick 
61024453Smckusick 	    case casestmt:	/* got word 'case' or 'default' */
61124453Smckusick 		scase = true;	/* so we can process the later colon
61224453Smckusick 				 * properly */
61324453Smckusick 		goto copy_id;
6148800Smckusick 
61524453Smckusick 	    case colon:	/* got a ':' */
61624453Smckusick 		if (squest > 0) {	/* it is part of the <c>?<n>: <n>
61724453Smckusick 					 * construct */
6188800Smckusick 		    --squest;
61924453Smckusick 		    if (ps.want_blank)
6208800Smckusick 			*e_code++ = ' ';
6218800Smckusick 		    *e_code++ = ':';
62224453Smckusick 		    ps.want_blank = true;
6238800Smckusick 		    break;
6248800Smckusick 		}
62524453Smckusick 		if (ps.in_decl) {
62624453Smckusick 		    *e_code++ = ':';
62724453Smckusick 		    ps.want_blank = false;
62824453Smckusick 		    break;
62924453Smckusick 		}
63024453Smckusick 		ps.in_stmt = false;	/* seeing a label does not imply
63124453Smckusick 					 * we are in a stmt */
6328800Smckusick 		for (t_ptr = s_code; *t_ptr; ++t_ptr)
63324453Smckusick 		    *e_lab++ = *t_ptr;	/* turn everything so far into a
63424453Smckusick 					 * label */
6358800Smckusick 		e_code = s_code;
6368800Smckusick 		*e_lab++ = ':';
6378800Smckusick 		*e_lab++ = ' ';
6388800Smckusick 		*e_lab = '\0';
6398800Smckusick 
64024453Smckusick 		force_nl = ps.pcase = scase;	/* ps.pcase will be used
64124453Smckusick 						 * by dump_line to decide
64224453Smckusick 						 * how to indent the
64324453Smckusick 						 * label. force_nl will
64424453Smckusick 						 * force a case n: to be
64524453Smckusick 						 * on a line by itself */
6468800Smckusick 		scase = false;
64724453Smckusick 		ps.want_blank = false;
6488800Smckusick 		break;
6498800Smckusick 
65024453Smckusick 	    case semicolon:	/* got a ';' */
65124453Smckusick 		ps.in_or_st = false;	/* we are not in an initialization
65224453Smckusick 					 * or structure declaration */
65324453Smckusick 		scase = false;	/* these will only need resetting in a
65424453Smckusick 				 * error */
6558800Smckusick 		squest = 0;
65624453Smckusick 		if (ps.last_token == rparen)
65724453Smckusick 		    ps.in_parameter_declaration = 0;
65824453Smckusick 		ps.cast_mask = 0;
65924453Smckusick 		ps.sizeof_mask = 0;
66024453Smckusick 		ps.block_init = 0;
66124453Smckusick 		ps.just_saw_decl--;
6628800Smckusick 
66324453Smckusick 		if (ps.in_decl && s_code == e_code && !ps.block_init)
6648800Smckusick 		    while ((e_code - s_code) < (dec_ind - 1))
6658800Smckusick 			*e_code++ = ' ';
6668800Smckusick 
66724453Smckusick 		ps.in_decl = (ps.dec_nest > 0);	/* if we were in a first
66824453Smckusick 						 * level structure
66924453Smckusick 						 * declaration, we arent
67024453Smckusick 						 * any more */
6718800Smckusick 
67224453Smckusick 		if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
67324453Smckusick 
67424453Smckusick 		    /*
67524453Smckusick 		     * This should be true iff there were unbalanced
67624453Smckusick 		     * parens in the stmt.  It is a bit complicated,
67724453Smckusick 		     * because the semicolon might be in a for stmt
67824453Smckusick 		     */
67924453Smckusick 		    diag(1, "Unbalanced parens");
68024453Smckusick 		    ps.p_l_follow = 0;
68124453Smckusick 		    if (sp_sw) {/* this is a check for a if, while, etc.
68224453Smckusick 				 * with unbalanced parens */
6838800Smckusick 			sp_sw = false;
68424453Smckusick 			parse(hd_type);	/* dont lose the if, or whatever */
6858800Smckusick 		    }
6868800Smckusick 		}
6878800Smckusick 		*e_code++ = ';';
68824453Smckusick 		ps.want_blank = true;
68924453Smckusick 		ps.in_stmt = (ps.p_l_follow > 0);	/* we are no longer in
69024453Smckusick 							 * the middle of a stmt */
6918800Smckusick 
69224453Smckusick 		if (!sp_sw) {	/* if not if for (;;) */
69324453Smckusick 		    parse(semicolon);	/* let parser know about end of
69424453Smckusick 					 * stmt */
69524453Smckusick 		    force_nl = true;	/* force newline after a end of
69624453Smckusick 					 * stmt */
6978800Smckusick 		}
6988800Smckusick 		break;
6998800Smckusick 
70024453Smckusick 	    case lbrace:	/* got a '{' */
70124453Smckusick 		ps.in_stmt = false;	/* dont indent the {} */
70224453Smckusick 		if (!ps.block_init)
70324453Smckusick 		    force_nl = true;	/* force other stuff on same line
70424453Smckusick 					 * as '{' onto new line */
7058800Smckusick 
70624453Smckusick 		if (s_code != e_code && !ps.block_init) {
70724453Smckusick 		    if (!btype_2) {
70824453Smckusick 			dump_line();
70924453Smckusick 			ps.want_blank = false;
71024453Smckusick 		    } else if (ps.in_parameter_declaration && !ps.in_or_st) {
71124453Smckusick 			ps.i_l_follow = 0;
71224453Smckusick 			dump_line();
71324453Smckusick 			ps.want_blank = false;
71424453Smckusick 		    }
7158800Smckusick 		}
71624453Smckusick 		if (ps.in_parameter_declaration)
71724453Smckusick 		    prefix_blankline_requested = 0;
7188800Smckusick 
71924648Smckusick 		if (ps.p_l_follow > 0) {	/* check for preceding
72024453Smckusick 						 * unbalanced parens */
72124453Smckusick 		    diag(1, "Unbalanced parens");
72224453Smckusick 		    ps.p_l_follow = 0;
72324453Smckusick 		    if (sp_sw) {/* check for unclosed if, for, etc. */
7248800Smckusick 			sp_sw = false;
72524453Smckusick 			parse(hd_type);
72624453Smckusick 			ps.ind_level = ps.i_l_follow;
7278800Smckusick 		    }
7288800Smckusick 		}
7298800Smckusick 		if (s_code == e_code)
73024453Smckusick 		    ps.ind_stmt = false;	/* dont put extra
73124453Smckusick 						 * indentation on line
73224453Smckusick 						 * with '{' */
73324453Smckusick 		if (ps.in_decl && ps.in_or_st) {	/* this is either a
73424453Smckusick 							 * structure declaration
73524453Smckusick 							 * or an init */
73624453Smckusick 		    di_stack[ps.dec_nest++] = dec_ind;
7378800Smckusick 		    dec_ind = 0;
73824453Smckusick 		} else {
73924453Smckusick 		    ps.decl_on_line = false;	/* we cant be in the
74024453Smckusick 						 * middle of a
74124453Smckusick 						 * declaration, so dont do
74224453Smckusick 						 * special indentation of
74324453Smckusick 						 * comments */
74424453Smckusick 		    ps.in_parameter_declaration = 0;
7458800Smckusick 		}
74624453Smckusick 		parse(lbrace);	/* let parser know about this */
74724453Smckusick 		if (ps.want_blank)	/* put a blank before '{' if '{'
74824453Smckusick 					 * is not at start of line */
7498800Smckusick 		    *e_code++ = ' ';
75024453Smckusick 		ps.want_blank = false;
7518800Smckusick 		*e_code++ = '{';
75224453Smckusick 		ps.just_saw_decl = 0;
7538800Smckusick 		break;
7548800Smckusick 
75524453Smckusick 	    case rbrace:	/* got a '}' */
75624453Smckusick 		if (ps.p_l_follow) {	/* check for unclosed if, for,
75724453Smckusick 					 * else. */
75824453Smckusick 		    diag(1, "Unbalanced parens");
75924453Smckusick 		    ps.p_l_follow = 0;
7608800Smckusick 		    sp_sw = false;
7618800Smckusick 		}
76224453Smckusick 		ps.just_saw_decl = 0;
76324453Smckusick 		if (s_code != e_code && !ps.block_init) {	/* '}' must be first on
76424453Smckusick 								 * line */
7658800Smckusick 		    if (verbose)
76624453Smckusick 			diag(0, "Line broken");
76724453Smckusick 		    dump_line();
7688800Smckusick 		}
7698800Smckusick 		*e_code++ = '}';
77024453Smckusick 		ps.want_blank = true;
77124453Smckusick 		ps.in_stmt = ps.ind_stmt = false;
77224453Smckusick 		if (ps.dec_nest > 0) {	/* we are in multi-level structure
77324453Smckusick 					 * declaration */
77424453Smckusick 		    dec_ind = di_stack[--ps.dec_nest];
77524453Smckusick 		    if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
77624453Smckusick 			ps.just_saw_decl = 2;
77724453Smckusick 		    ps.in_decl = true;
7788800Smckusick 		}
77924453Smckusick 		prefix_blankline_requested = 0;
78024453Smckusick 		parse(rbrace);	/* let parser know about this */
78124453Smckusick 		ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead && ps.il[ps.tos] >= ps.ind_level;
78224453Smckusick 		if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
78324453Smckusick 		    postfix_blankline_requested = 1;
7848800Smckusick 		break;
7858800Smckusick 
78624453Smckusick 	    case swstmt:	/* got keyword "switch" */
7878800Smckusick 		sp_sw = true;
78824453Smckusick 		hd_type = swstmt;	/* keep this for when we have seen
78924453Smckusick 					 * the expression */
79024453Smckusick 		goto copy_id;	/* go move the token into buffer */
7918800Smckusick 
79224453Smckusick 	    case sp_paren:	/* token is if, while, for */
79324453Smckusick 		sp_sw = true;	/* the interesting stuff is done after the
79424453Smckusick 				 * expression is scanned */
7958800Smckusick 		hd_type = (*token == 'i' ? ifstmt :
79624453Smckusick 			   (*token == 'w' ? whilestmt : forstmt));
7978800Smckusick 
79824453Smckusick 		/*
79924453Smckusick 		 * remember the type of header for later use by parser
80024453Smckusick 		 */
80124453Smckusick 		goto copy_id;	/* copy the token into line */
80224453Smckusick 
80324453Smckusick 	    case sp_nparen:	/* got else, do */
80424453Smckusick 		ps.in_stmt = false;
80524453Smckusick 		if (*token == 'e') {
80624453Smckusick 		    if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
80724453Smckusick 			if (verbose)
80824453Smckusick 			    diag(0, "Line broken");
80924453Smckusick 			dump_line();	/* make sure this starts a line */
81024453Smckusick 			ps.want_blank = false;
81124453Smckusick 		    }
81224453Smckusick 		    force_nl = true;	/* also, following stuff must go
81324453Smckusick 					 * onto new line */
81424453Smckusick 		    last_else = 1;
81524453Smckusick 		    parse(elselit);
81624453Smckusick 		} else {
81724453Smckusick 		    if (e_code != s_code) {	/* make sure this starts a
81824453Smckusick 						 * line */
81924453Smckusick 			if (verbose)
82024453Smckusick 			    diag(0, "Line broken");
82124453Smckusick 			dump_line();
82224453Smckusick 			ps.want_blank = false;
82324453Smckusick 		    }
82424453Smckusick 		    force_nl = true;	/* also, following stuff must go
82524453Smckusick 					 * onto new line */
82624453Smckusick 		    last_else = 0;
82724453Smckusick 		    parse(dolit);
8288800Smckusick 		}
82924453Smckusick 		goto copy_id;	/* move the token into line */
8308800Smckusick 
83124453Smckusick 	    case decl:		/* we have a declaration type (int,
83224453Smckusick 				 * register, etc.) */
83324453Smckusick 		parse(decl);	/* let parser worry about indentation */
83424453Smckusick 		if (ps.last_token == rparen && ps.tos <= 1)
83524453Smckusick 		    ps.in_parameter_declaration = 1;
83624453Smckusick 		if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
83724453Smckusick 		    ps.ind_level = ps.i_l_follow = 1;
83824453Smckusick 		    ps.ind_stmt = 0;
83924453Smckusick 		}
84024453Smckusick 		ps.in_or_st = true;	/* this might be a structure or
84124453Smckusick 					 * initialization declaration */
84224453Smckusick 		ps.in_decl = ps.decl_on_line = true;
84324453Smckusick 		if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
84424453Smckusick 		    ps.just_saw_decl = 2;
84524453Smckusick 		prefix_blankline_requested = 0;
84624453Smckusick 		for (i = 0; token[i++];);	/* get length of token */
8478800Smckusick 
84824453Smckusick 		/*
84924453Smckusick 		 * dec_ind = e_code - s_code + (ps.decl_indent>i ?
85024453Smckusick 		 * ps.decl_indent : i);
85124453Smckusick 		 */
85224453Smckusick 		dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
8538800Smckusick 		goto copy_id;
8548800Smckusick 
85524453Smckusick 	    case ident:	/* got an identifier or constant */
85624453Smckusick 		if (ps.in_decl) {	/* if we are in a declaration, we
85724453Smckusick 					 * must indent identifier */
85824453Smckusick 		    if (ps.want_blank)
8598800Smckusick 			*e_code++ = ' ';
86024453Smckusick 		    ps.want_blank = false;
86124453Smckusick 		    if (is_procname == 0 || !procnames_start_line) {
86224453Smckusick 			if (!ps.block_init)
86324453Smckusick 			    if (troff && !ps.dumped_decl_indent) {
86424453Smckusick 				sprintf(e_code, "\\c\n.De %dp+\200p\n", dec_ind * 7);
86524453Smckusick 				ps.dumped_decl_indent = 1;
86624453Smckusick 				e_code += strlen(e_code);
86724453Smckusick 			    } else
86824453Smckusick 				while ((e_code - s_code) < dec_ind)
86924453Smckusick 				    *e_code++ = ' ';
87024453Smckusick 		    } else {
87124453Smckusick 			if (dec_ind && s_code != e_code)
87224453Smckusick 			    dump_line();
87324453Smckusick 			dec_ind = 0;
87424453Smckusick 			ps.want_blank = false;
87524453Smckusick 		    }
87624453Smckusick 		} else if (sp_sw && ps.p_l_follow == 0) {
87724453Smckusick 		    sp_sw = false;
87824453Smckusick 		    force_nl = true;
87924453Smckusick 		    ps.last_u_d = true;
88024453Smckusick 		    ps.in_stmt = false;
88124453Smckusick 		    parse(hd_type);
8828800Smckusick 		}
88324453Smckusick 	copy_id:
88424453Smckusick 		if (ps.want_blank)
8858800Smckusick 		    *e_code++ = ' ';
88624453Smckusick 		if (troff && ps.its_a_keyword) {
88724453Smckusick 		    *e_code++ = BACKSLASH;
88824453Smckusick 		    *e_code++ = 'f';
88924453Smckusick 		    *e_code++ = 'B';
89024453Smckusick 		}
8918800Smckusick 		for (t_ptr = token; *t_ptr; ++t_ptr)
8928800Smckusick 		    *e_code++ = *t_ptr;
89324453Smckusick 		if (troff && ps.its_a_keyword) {
89424453Smckusick 		    *e_code++ = BACKSLASH;
89524453Smckusick 		    *e_code++ = 'f';
89624453Smckusick 		    *e_code++ = 'R';
89724453Smckusick 		}
89824453Smckusick 		ps.want_blank = true;
8998800Smckusick 		break;
9008800Smckusick 
90124453Smckusick 	    case period:	/* treat a period kind of like a binary
90224453Smckusick 				 * operation */
90324453Smckusick 		*e_code++ = '.';/* move the period into line */
90424453Smckusick 		ps.want_blank = false;	/* dont put a blank after a period */
9058800Smckusick 		break;
9068800Smckusick 
90724453Smckusick 	    case comma:
90824453Smckusick 		ps.want_blank = (s_code != e_code);	/* only put blank after
90924453Smckusick 							 * comma if comma does
91024453Smckusick 							 * not start the line */
91124453Smckusick 		if (ps.in_decl && is_procname == 0 && !ps.block_init)
9128800Smckusick 		    while ((e_code - s_code) < (dec_ind - 1))
9138800Smckusick 			*e_code++ = ' ';
9148800Smckusick 
9158800Smckusick 		*e_code++ = ',';
91624453Smckusick 		if (ps.p_l_follow == 0) {
91724453Smckusick 		    ps.block_init = 0;
91824453Smckusick 		    if (break_comma && !ps.leave_comma)
91924453Smckusick 			force_nl = true;
92024453Smckusick 		}
9218800Smckusick 		break;
9228800Smckusick 
92324453Smckusick 	    case preesc:	/* got the character '#' */
92424453Smckusick 		if ((s_com != e_com) ||
92524453Smckusick 		    (s_lab != e_lab) ||
92624453Smckusick 		    (s_code != e_code))
92724453Smckusick 		    dump_line();
92824453Smckusick 		*e_lab++ = '#';	/* move whole line to 'label' buffer */
92924453Smckusick 		{
93024453Smckusick 		    int         in_comment = 0;
93124453Smckusick 		    char       *com_start = 0;
93224453Smckusick 		    char        quote = 0;
93324453Smckusick 		    char       *com_end = 0;
9348800Smckusick 
93524453Smckusick 		    while (*buf_ptr != '\n' || in_comment) {
93624453Smckusick 			*e_lab = *buf_ptr++;
93724453Smckusick 			if (buf_ptr >= buf_end)
93824453Smckusick 			    fill_buffer();
93924453Smckusick 			switch (*e_lab++) {
94024453Smckusick 			    case BACKSLASH:
94124453Smckusick 				if (troff)
94224453Smckusick 				    *e_lab++ = BACKSLASH;
94324453Smckusick 				if (!in_comment) {
94424453Smckusick 				    *e_lab++ = *buf_ptr++;
94524453Smckusick 				    if (buf_ptr >= buf_end)
94624453Smckusick 					fill_buffer();
94724453Smckusick 				}
94824453Smckusick 				break;
94924453Smckusick 			    case '/':
95024453Smckusick 				if (*buf_ptr == '*' && !in_comment && !quote) {
95124453Smckusick 				    in_comment = 1;
95224453Smckusick 				    *e_lab++ = *buf_ptr++;
95324453Smckusick 				    com_start = e_lab - 2;
95424453Smckusick 				}
95524453Smckusick 				break;
95624453Smckusick 			    case '"':
95724453Smckusick 				if (quote == '"')
95824453Smckusick 				    quote = 0;
95924453Smckusick 				break;
96024453Smckusick 			    case '\'':
96124453Smckusick 				if (quote == '\'')
96224453Smckusick 				    quote = 0;
96324453Smckusick 				break;
96424453Smckusick 			    case '*':
96524453Smckusick 				if (*buf_ptr == '/' && in_comment) {
96624453Smckusick 				    in_comment = 0;
96724453Smckusick 				    *e_lab++ = *buf_ptr++;
96824453Smckusick 				    com_end = e_lab;
96924453Smckusick 				}
97024453Smckusick 				break;
97124453Smckusick 			}
9728800Smckusick 		    }
97324453Smckusick 		    while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
97424453Smckusick 			e_lab--;
97524453Smckusick 		    if (e_lab == com_end && bp_save == 0) {	/* comment on
97624453Smckusick 								 * preprocessor line */
97724453Smckusick 			if (sc_end == 0)	/* if this is the first
97824453Smckusick 						 * comment, we must set up
97924453Smckusick 						 * the buffer */
98024453Smckusick 			    sc_end = &(save_com[0]);
98124453Smckusick 			else {
98224453Smckusick 			    *sc_end++ = '\n';	/* add newline between
98324453Smckusick 						 * comments */
98424453Smckusick 			    *sc_end++ = ' ';
98524453Smckusick 			    --line_no;
98624453Smckusick 			}
98724453Smckusick 			bcopy(com_start, sc_end, com_end - com_start);
98824453Smckusick 			sc_end += com_end - com_start;
98924453Smckusick 			e_lab = com_start;
99024453Smckusick 			while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
99124453Smckusick 			    e_lab--;
99224453Smckusick 			bp_save = buf_ptr;	/* save current input
99324453Smckusick 						 * buffer */
99424453Smckusick 			be_save = buf_end;
99524453Smckusick 			buf_ptr = save_com;	/* fix so that subsequent
99624453Smckusick 						 * calls to lexi will take
99724453Smckusick 						 * tokens out of save_com */
99824453Smckusick 			*sc_end++ = ' ';	/* add trailing blank,
99924453Smckusick 						 * just in case */
100024453Smckusick 			buf_end = sc_end;
100124453Smckusick 			sc_end = 0;
100224453Smckusick 		    }
100324453Smckusick 		    *e_lab = '\0';	/* null terminate line */
100424453Smckusick 		    ps.pcase = false;
10058800Smckusick 		}
100624453Smckusick 		if (strncmp(s_lab, "#if", 3) == 0)
100724453Smckusick 		    if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) {
100824453Smckusick 			match_state[ifdef_level].tos = -1;
100924453Smckusick 			state_stack[ifdef_level++] = ps;
101024453Smckusick 		    } else
101124453Smckusick 			diag(1, "#if stack overflow");
101224453Smckusick 		else if (strncmp(s_lab, "#else", 5) == 0)
101324453Smckusick 		    if (ifdef_level <= 0)
101424453Smckusick 			diag(1, "Unmatched #else");
101524453Smckusick 		    else {
101624453Smckusick 			match_state[ifdef_level - 1] = ps;
101724453Smckusick 			ps = state_stack[ifdef_level - 1];
101824453Smckusick 		} else if (strncmp(s_lab, "#endif", 6) == 0)
101924453Smckusick 		    if (ifdef_level <= 0)
102024453Smckusick 			diag(1, "Unmatched #endif");
102124453Smckusick 		    else {
102224453Smckusick 			ifdef_level--;
102324453Smckusick #ifdef undef
10248800Smckusick 
102524453Smckusick 			/*
102624453Smckusick 			 * This match needs to be more intelligent before
102724453Smckusick 			 * the message is useful
102824453Smckusick 			 */
102924453Smckusick 			if (match_state[ifdef_level].tos >= 0
103024453Smckusick 			    && bcmp(&ps, &match_state[ifdef_level], sizeof ps))
103124453Smckusick 			    diag(0, "Syntactically inconsistant #ifdef alternatives.");
103224453Smckusick #endif
103324453Smckusick 		    }
103424453Smckusick 		break;		/* subsequent processing of the newline
103524453Smckusick 				 * character will cause the line to be
103624453Smckusick 				 * printed */
10378800Smckusick 
103824453Smckusick 	    case comment:	/* we have gotten a /*  this is a biggie */
103924453Smckusick 	proc_comment:
104024453Smckusick 		if (flushed_nl) {	/* we should force a broken line
104124453Smckusick 					 * here */
104224453Smckusick 		    flushed_nl = false;
104324453Smckusick 		    dump_line();
104424453Smckusick 		    ps.want_blank = false;	/* dont insert blank at
104524453Smckusick 						 * line start */
104624453Smckusick 		    force_nl = false;
104724453Smckusick 		}
104824453Smckusick 		pr_comment();
10498800Smckusick 		break;
105024453Smckusick 	}			/* end of big switch stmt */
105124453Smckusick 	*e_code = '\0';		/* make sure code section is null
105224453Smckusick 				 * terminated */
105324453Smckusick 	if (type_code != comment && type_code != newline && type_code != preesc)
105424453Smckusick 	    ps.last_token = type_code;
105524453Smckusick     }				/* end of main while (1) loop */
10568800Smckusick };
10578800Smckusick 
10588800Smckusick /*
105924648Smckusick  * copy input file to backup file.  If in_name is /blah/blah/blah/file, then
106024648Smckusick  * backup file will be "file.BAK".  Then make the backup file the input and
106124648Smckusick  * original input file the output.
10628800Smckusick  */
106324453Smckusick bakcopy()
106424453Smckusick {
106524453Smckusick     int         n,
106624453Smckusick                 bakchn;
106724648Smckusick     char        buff[BUFSIZ];
106824453Smckusick     register char *p;
106924648Smckusick     char *rindex();
10708800Smckusick 
107124648Smckusick     if ((p = rindex(in_name, '/')) != NULL)
10728800Smckusick 	p++;
107324648Smckusick     else
107424648Smckusick 	p = in_name;
107524453Smckusick     sprintf(bakfile, "%s.BAK", p);
10768800Smckusick 
107724453Smckusick     /* copy in_name to backup file */
107824453Smckusick     bakchn = creat(bakfile, 0600);
10798800Smckusick     if (bakchn < 0) {
108024648Smckusick 	fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile);
108124648Smckusick 	exit(1);
10828800Smckusick     }
108324648Smckusick     while ((n = read(fileno(input), buff, sizeof buff)) > 0)
108424648Smckusick 	if (write(bakchn, buff, n) != n) {
108524648Smckusick 	    fprintf(stderr, "indent: error writing backup file \"%s\"\n",
108624648Smckusick 		bakfile);
108724648Smckusick 	    exit(1);
108824648Smckusick 	}
108924648Smckusick     if (n < 0) {
109024648Smckusick 	fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name);
109124648Smckusick 	exit(1);
109224648Smckusick     }
109324453Smckusick     close(bakchn);
109424453Smckusick     fclose(input);
10958800Smckusick 
109624453Smckusick     /* re-open backup file as the input file */
109724453Smckusick     input = fopen(bakfile, "r");
109824648Smckusick     if (input == NULL) {
109924648Smckusick 	fprintf(stderr, "indent: can't re-open backup file\n");
110024648Smckusick 	exit(1);
11018800Smckusick     }
110224453Smckusick     /* now the original input file will be the output */
110324453Smckusick     output = fopen(in_name, "w");
110424648Smckusick     if (output == NULL) {
110524648Smckusick 	fprintf(stderr, "indent: can't create %s\n", in_name);
110624453Smckusick 	unlink(bakfile);
110724648Smckusick 	exit(1);
11088800Smckusick     }
11098800Smckusick }
1110