xref: /csrg-svn/usr.bin/indent/indent.c (revision 24648)
121968Sdist /*
221968Sdist  * Copyright (c) 1980 Regents of the University of California.
321968Sdist  * All rights reserved.  The Berkeley software License Agreement
421968Sdist  * specifies the terms and conditions for redistribution.
521968Sdist  */
68800Smckusick 
721968Sdist #ifndef lint
821968Sdist char copyright[] =
921968Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1021968Sdist  All rights reserved.\n";
1121968Sdist #endif not lint
1221968Sdist 
1321968Sdist #ifndef lint
14*24648Smckusick static char sccsid[] = "@(#)indent.c	5.3 (Berkeley) 09/08/85";
1521968Sdist #endif not lint
1621968Sdist 
1724453Smckusick /*-
1824453Smckusick 
1924453Smckusick 	Copyright (C) 1976
2024453Smckusick 		by the
2124453Smckusick 	Board of Trustees
2224453Smckusick 		of the
2324453Smckusick 	University of Illinois
2424453Smckusick 
2524453Smckusick 	All rights reserved
2624453Smckusick 
2724453Smckusick 
288800Smckusick NAME:
2924453Smckusick indent main program
3024453Smckusick 
318800Smckusick FUNCTION:
3224453Smckusick This is the main program of the indent program.  Indent will take a C
3324453Smckusick program source and reformat it into a semi-reasonable form.
3424453Smckusick 
358800Smckusick ALGORITHM:
3624453Smckusick The routine lexi scans tokens and passes them back one at a time to the
3724453Smckusick main routine.  The subroutine parse takes care of much of the work of
3824453Smckusick figuring indentation level.
3924453Smckusick 
4024453Smckusick 1) Call lexi
4124453Smckusick 2) Enter a monster switch statement on the code returned by lexi.  If
4224453Smckusick the indentation level for the line yet to be printed should be
4324453Smckusick changed, set the variable ps.ind_level.  If the indentation level for
4424453Smckusick the following line should be changed, set the variable ps.i_l_follow.
458800Smckusick 
4624453Smckusick */
478800Smckusick #include "indent_globs.h";
488800Smckusick #include "indent_codes.h";
498800Smckusick 
5024453Smckusick char       *in_name = "Standard Input";	/* will always point to name of
5124453Smckusick 					 * input file */
5224453Smckusick char       *out_name = "Standard Output";	/* will always point to
5324453Smckusick 						 * name of output file */
5424453Smckusick char        bakfile[32] = "";
558800Smckusick 
5624453Smckusick main(argc, argv)
5724453Smckusick     int         argc;
5824453Smckusick     char      **argv;
598800Smckusick {
608800Smckusick 
6124453Smckusick     int         dec_ind;	/* current indentation for declarations */
6224453Smckusick     int         di_stack[20];	/* a stack of structure indentation levels */
6324453Smckusick     int         flushed_nl;	/* used when buffering up comments to
6424453Smckusick 				 * remember that a newline was passed over */
6524453Smckusick     int         force_nl;	/* when true, code must be broken */
6624453Smckusick     int         hd_type;	/* used to store type of stmt for if
6724453Smckusick 				 * (...), for (...), etc */
6824453Smckusick     register int i;		/* local loop counter */
6924453Smckusick     register int j;		/* local loop counter */
7024453Smckusick     int         scase;		/* set to true when we see a case, so we
7124453Smckusick 				 * will know what to do with the following
7224453Smckusick 				 * colon */
7324453Smckusick     int         sp_sw;		/* when true, we are in the expressin of
7424453Smckusick 				 * if(...), while(...), etc. */
7524453Smckusick     int         squest;		/* when this is positive, we have seen a ?
7624453Smckusick 				 * without the matching : in a <c>?<s>:<s>
7724453Smckusick 				 * construct */
7824453Smckusick     register char *t_ptr;	/* used for copying tokens */
7924453Smckusick     int         type_code;	/* the type of token, returned by lexi */
808800Smckusick 
8124453Smckusick     int         last_else = 0;	/* true iff last keyword was an else */
828800Smckusick 
838800Smckusick 
8424453Smckusick     /*-----------------------------------------------*\
85*24648Smckusick     |		      INITIALIZATION		      |
86*24648Smckusick     \*-----------------------------------------------*/
878800Smckusick 
888800Smckusick 
8924453Smckusick     ps.p_stack[0] = stmt;	/* this is the parser's stack */
9024453Smckusick     ps.last_nl = true;		/* this is true if the last thing scanned
9124453Smckusick 				 * was a newline */
9224453Smckusick     ps.last_token = semicolon;
9324453Smckusick     combuf[0] = codebuf[0] = labbuf[0] = ' ';	/* set up code, label, and
9424453Smckusick 						 * comment buffers */
958800Smckusick     combuf[1] = codebuf[1] = labbuf[1] = '\0';
968800Smckusick     s_lab = e_lab = labbuf + 1;
978800Smckusick     s_code = e_code = codebuf + 1;
988800Smckusick     s_com = e_com = combuf + 1;
998800Smckusick 
1008800Smckusick     buf_ptr = buf_end = in_buffer;
1018800Smckusick     line_no = 1;
10224453Smckusick     had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
1038800Smckusick     sp_sw = force_nl = false;
10424453Smckusick     ps.in_or_st = false;
10524453Smckusick     ps.bl_line = true;
1068800Smckusick     dec_ind = 0;
10724453Smckusick     di_stack[ps.dec_nest = 0] = 0;
10824453Smckusick     ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
1098800Smckusick 
1108800Smckusick 
11124453Smckusick     scase = ps.pcase = false;
1128800Smckusick     squest = 0;
1138800Smckusick     sc_end = 0;
1148800Smckusick     bp_save = 0;
1158800Smckusick     be_save = 0;
1168800Smckusick 
11724453Smckusick     output = 0;
1188800Smckusick 
1198800Smckusick 
1208800Smckusick 
12124453Smckusick     /*--------------------------------------------------*\
122*24648Smckusick     |   COMMAND LINE SCAN
123*24648Smckusick     \*--------------------------------------------------*/
1248800Smckusick 
125*24648Smckusick     set_defaults();
1268800Smckusick 
127*24648Smckusick     /*
128*24648Smckusick      * Unfortunately, we must look for -npro here because the profiles
129*24648Smckusick      * are read before the command line arguments.
130*24648Smckusick      */
13124453Smckusick     for (i = 1; i < argc; ++i)
13224453Smckusick 	if (strcmp(argv[i], "-npro") == 0)
13324453Smckusick 	    break;
13424453Smckusick     if (i >= argc)
13524453Smckusick 	set_profile();
1368800Smckusick 
137*24648Smckusick     input = 0;			/* cancel -st if it was in the profiles, */
138*24648Smckusick     output = 0;			/* as it doesn't make any sense there. */
139*24648Smckusick 
1408800Smckusick     for (i = 1; i < argc; ++i) {
14124453Smckusick 
14224453Smckusick 	/*
14324453Smckusick 	 * look thru args (if any) for changes to defaults
14424453Smckusick 	 */
1458800Smckusick 	if (argv[i][0] != '-') {/* no flag on parameter */
14624453Smckusick 	    if (input == 0) {	/* we must have the input file */
14724453Smckusick 		in_name = argv[i];	/* remember name of input file */
14824453Smckusick 		input = fopen(in_name, "r");
14924453Smckusick 		if (input == 0) {	/* check for open error */
150*24648Smckusick 		    fprintf(stderr, "indent: can't open %s\n", argv[i]);
151*24648Smckusick 		    exit(1);
1528800Smckusick 		}
1538800Smckusick 		continue;
15424453Smckusick 	    } else if (output == 0) {	/* we have the output file */
15524453Smckusick 		out_name = argv[i];	/* remember name of output file */
15624453Smckusick 		if (strcmp(in_name, out_name) == 0) {	/* attempt to overwrite
15724453Smckusick 							 * the file */
158*24648Smckusick 		    fprintf(stderr, "indent: input and output files must be different\n");
159*24648Smckusick 		    exit(1);
16024453Smckusick 		}
16124453Smckusick 		output = fopen(out_name, "w");
16224453Smckusick 		if (output == 0) {	/* check for create error */
163*24648Smckusick 		    fprintf(stderr, "indent: can't create %s\n", argv[i]);
164*24648Smckusick 		    exit(1);
16524453Smckusick 		}
16624453Smckusick 		continue;
1678800Smckusick 	    }
168*24648Smckusick 	    fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]);
169*24648Smckusick 	    exit(1);
17024453Smckusick 	} else
17124453Smckusick 	    set_option(argv[i]);
1728800Smckusick 
17324453Smckusick     }				/* end of for */
17424453Smckusick     if (input == 0) {
17524453Smckusick 	printf("Usage: indent file [ outfile ] [ options ]\n");
176*24648Smckusick 	exit(1);
17724453Smckusick     }
17824453Smckusick     if (output == 0)
17924453Smckusick 	if (troff)
18024453Smckusick 	    output = stdout;
18124453Smckusick 	else {
18224453Smckusick 	    out_name = in_name;
18324453Smckusick 	    bakcopy();
1848800Smckusick 	}
185*24648Smckusick 
186*24648Smckusick     /*
187*24648Smckusick      * Adjust parameters that are out of range, or set defaults if
188*24648Smckusick      * no values were specified.
189*24648Smckusick      */
19024453Smckusick     if (ps.com_ind <= 1)
19124453Smckusick 	ps.com_ind = 2;		/* dont put normal comments before column
19224453Smckusick 				 * 2 */
19324453Smckusick     if (block_comment_max_col <= 0)
19424453Smckusick 	block_comment_max_col = max_col;
19524453Smckusick     if (ps.decl_com_ind <= 0)	/* if not specified by user, set this */
196*24648Smckusick 	ps.decl_com_ind = ps.ljust_decl ? ps.com_ind - 8 : ps.com_ind;
197*24648Smckusick     if (ps.decl_com_ind <= 1)
198*24648Smckusick 	ps.decl_com_ind = 2;
19924453Smckusick     if (continuation_indent == 0)
20024453Smckusick 	continuation_indent = ps.ind_size;
20124453Smckusick     fill_buffer();		/* get first batch of stuff into input
20224453Smckusick 				 * buffer */
2038800Smckusick 
20424453Smckusick     parse(semicolon);
20524453Smckusick     {
20624453Smckusick 	register char *p = buf_ptr;
20724453Smckusick 	register    col = 1;
2088800Smckusick 
20924453Smckusick 	while (1) {
21024453Smckusick 	    if (*p == ' ')
21124453Smckusick 		col++;
21224453Smckusick 	    else if (*p == '\t')
21324453Smckusick 		col = ((col - 1) & ~7) + 9;
21424453Smckusick 	    else
21524453Smckusick 		break;
21624453Smckusick 	    p++;
21724453Smckusick 	};
21824453Smckusick 	if (col > ps.ind_size)
21924453Smckusick 	    ps.ind_level = ps.i_l_follow = col / ps.ind_size;
2208800Smckusick     }
22124453Smckusick     if (troff) {
22224453Smckusick 	register char *p = in_name,
22324453Smckusick 	           *beg = in_name;
22424453Smckusick 
22524453Smckusick 	while (*p)
22624453Smckusick 	    if (*p++ == '/')
22724453Smckusick 		beg = p;
22824453Smckusick 	fprintf(output, ".Fn \"%s\"\n", beg);
2298800Smckusick     }
2308800Smckusick 
23124453Smckusick     /*
23224453Smckusick      * START OF MAIN LOOP
23324453Smckusick      */
2348800Smckusick 
23524453Smckusick     while (1) {			/* this is the main loop.  it will go
23624453Smckusick 				 * until we reach eof */
23724453Smckusick 	int         is_procname;
2388800Smckusick 
23924453Smckusick 	type_code = lexi();	/* lexi reads one token.  The actual
24024453Smckusick 				 * characters read are stored in "token".
24124453Smckusick 				 * lexi returns a code indicating the type
24224453Smckusick 				 * of token */
24324453Smckusick 	is_procname = ps.procname[0];
2448800Smckusick 
24524453Smckusick 	/*
24624453Smckusick 	 * The following code moves everything following an if (), while
24724453Smckusick 	 * (), else, etc. up to the start of the following stmt to a
24824453Smckusick 	 * buffer.  This allows proper handling of both kinds of brace
24924453Smckusick 	 * placement.
25024453Smckusick 	 */
2518800Smckusick 
2528800Smckusick 	flushed_nl = false;
25324453Smckusick 	while (ps.search_brace) {	/* if we scanned an if(), while(),
25424453Smckusick 					 * etc., we might need to copy
25524453Smckusick 					 * stuff into a buffer we must
25624453Smckusick 					 * loop, copying stuff into
25724453Smckusick 					 * save_com, until we find the
25824453Smckusick 					 * start of the stmt which follows
25924453Smckusick 					 * the if, or whatever */
2608800Smckusick 	    switch (type_code) {
26124453Smckusick 		case newline:
2628800Smckusick 		    ++line_no;
2638800Smckusick 		    flushed_nl = true;
26424453Smckusick 		case form_feed:
26524453Smckusick 		    break;	/* form feeds and newlines found here will
26624453Smckusick 				 * be ignored */
2678800Smckusick 
26824453Smckusick 		case lbrace:	/* this is a brace that starts the
26924453Smckusick 				 * compound stmt */
27024453Smckusick 		    if (sc_end == 0) {	/* ignore buffering if a comment
27124453Smckusick 					 * wasnt stored up */
27224453Smckusick 			ps.search_brace = false;
2738800Smckusick 			goto check_type;
2748800Smckusick 		    }
2758800Smckusick 		    if (btype_2) {
27624453Smckusick 			save_com[0] = '{';	/* we either want to put
27724453Smckusick 						 * the brace right after
27824453Smckusick 						 * the if */
27924453Smckusick 			goto sw_buffer;	/* go to common code to get out of
28024453Smckusick 					 * this loop */
2818800Smckusick 		    }
28224453Smckusick 		case comment:	/* we have a comment, so we must copy it
28324453Smckusick 				 * into the buffer */
28424453Smckusick 		    if (!flushed_nl) {
28524453Smckusick 			if (sc_end == 0) {	/* if this is the first
28624453Smckusick 						 * comment, we must set up
28724453Smckusick 						 * the buffer */
28824453Smckusick 			    save_com[0] = save_com[1] = ' ';
28924453Smckusick 			    sc_end = &(save_com[2]);
29024453Smckusick 			} else {
29124453Smckusick 			    *sc_end++ = '\n';	/* add newline between
29224453Smckusick 						 * comments */
29324453Smckusick 			    *sc_end++ = ' ';
29424453Smckusick 			    --line_no;
29524453Smckusick 			}
29624453Smckusick 			*sc_end++ = '/';	/* copy in start of
29724453Smckusick 						 * comment */
29824453Smckusick 			*sc_end++ = '*';
2998800Smckusick 
30024453Smckusick 			for (;;) {	/* loop until we get to the end of
30124453Smckusick 					 * the comment */
30224453Smckusick 			    *sc_end = *buf_ptr++;
30324453Smckusick 			    if (buf_ptr >= buf_end)
30424453Smckusick 				fill_buffer();
30524453Smckusick 
30624453Smckusick 			    if (*sc_end++ == '*' && *buf_ptr == '/')
30724453Smckusick 				break;	/* we are at end of comment */
30824453Smckusick 
30924453Smckusick 			    if (sc_end >= &(save_com[sc_size])) {	/* check for temp buffer
31024453Smckusick 									 * overflow */
31124453Smckusick 				diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
31224453Smckusick 				fflush(output);
313*24648Smckusick 				exit(1);
31424453Smckusick 			    }
31524453Smckusick 			}
31624453Smckusick 			*sc_end++ = '/';	/* add ending slash */
31724453Smckusick 			if (++buf_ptr >= buf_end)	/* get past / in buffer */
31824453Smckusick 			    fill_buffer();
31924453Smckusick 			break;
32024453Smckusick 		    }
32124453Smckusick 		default:	/* it is the start of a normal statment */
32224453Smckusick 		    if (flushed_nl)	/* if we flushed a newline, make
32324453Smckusick 					 * sure it is put back */
3248800Smckusick 			force_nl = true;
32524453Smckusick 		    if (type_code == sp_paren && *token == 'i'
32624453Smckusick 			&& last_else && ps.else_if
32724453Smckusick 			|| type_code == sp_nparen && *token == 'e'
32824453Smckusick 			&& e_code != s_code && e_code[-1] == '}')
32924453Smckusick 			force_nl = false;
3308800Smckusick 
33124453Smckusick 		    if (sc_end == 0) {	/* ignore buffering if comment
33224453Smckusick 					 * wasnt saved up */
33324453Smckusick 			ps.search_brace = false;
3348800Smckusick 			goto check_type;
3358800Smckusick 		    }
33624453Smckusick 		    if (force_nl) {	/* if we should insert a nl here,
33724453Smckusick 					 * put it into the buffer */
3388800Smckusick 			force_nl = false;
33924453Smckusick 			--line_no;	/* this will be re-increased when
34024453Smckusick 					 * the nl is read from the buffer */
3418800Smckusick 			*sc_end++ = '\n';
3428800Smckusick 			*sc_end++ = ' ';
34324453Smckusick 			if (verbose && !flushed_nl)	/* print error msg if
34424453Smckusick 							 * the line was not
34524453Smckusick 							 * already broken */
34624453Smckusick 			    diag(0, "Line broken");
3478800Smckusick 			flushed_nl = false;
3488800Smckusick 		    }
3498800Smckusick 		    for (t_ptr = token; *t_ptr; ++t_ptr)
35024453Smckusick 			*sc_end++ = *t_ptr;	/* copy token into temp
35124453Smckusick 						 * buffer */
3528800Smckusick 
35324453Smckusick 	    sw_buffer:
35424453Smckusick 		    ps.search_brace = false;	/* stop looking for start
35524453Smckusick 						 * of stmt */
35624453Smckusick 		    bp_save = buf_ptr;	/* save current input buffer */
3578800Smckusick 		    be_save = buf_end;
35824453Smckusick 		    buf_ptr = save_com;	/* fix so that subsequent calls to
35924453Smckusick 					 * lexi will take tokens out of
36024453Smckusick 					 * save_com */
36124453Smckusick 		    *sc_end++ = ' ';	/* add trailing blank, just in
36224453Smckusick 					 * case */
3638800Smckusick 		    buf_end = sc_end;
3648800Smckusick 		    sc_end = 0;
3658800Smckusick 		    break;
36624453Smckusick 	    }			/* end of switch */
36724453Smckusick 	    if (type_code != 0)	/* we must make this check, just in case
36824453Smckusick 				 * there was an unexpected EOF */
36924453Smckusick 		type_code = lexi();	/* read another token */
37024453Smckusick 	    is_procname = ps.procname[0];
37124453Smckusick 	}			/* end of while (serach_brace) */
37224453Smckusick 	last_else = 0;
37324453Smckusick check_type:
37424453Smckusick 	if (type_code == 0) {	/* we got eof */
3758800Smckusick 	    if (s_lab != e_lab || s_code != e_code
37624453Smckusick 		|| s_com != e_com)	/* must dump end of line */
37724453Smckusick 		dump_line();
37824453Smckusick 	    if (ps.tos > 1)	/* check for balanced braces */
37924453Smckusick 		diag(1, "Stuff missing from end of file.");
3808800Smckusick 
3818800Smckusick 	    if (verbose) {
38224453Smckusick 		printf("There were %d output lines and %d comments\n",
38324453Smckusick 		       ps.out_lines, ps.out_coms);
38424453Smckusick 		printf("(Lines with comments)/(Lines with code): %6.3f\n",
38524453Smckusick 		       (1.0 * ps.com_lines) / code_lines);
3868800Smckusick 	    }
38724453Smckusick 	    fflush(output);
388*24648Smckusick 	    exit(ps.tos <= 1);
3898800Smckusick 	}
3908800Smckusick 	if (
39124453Smckusick 	    (type_code != comment) &&
39224453Smckusick 	    (type_code != newline) &&
39324453Smckusick 	    (type_code != preesc) &&
39424453Smckusick 	    (type_code != form_feed)) {
3958800Smckusick 	    if (
39624453Smckusick 		force_nl
39724453Smckusick 		&&
39824453Smckusick 		(type_code != semicolon) &&
39924453Smckusick 		(
40024453Smckusick 		 type_code != lbrace
40124453Smckusick 		 ||
40224453Smckusick 		 !btype_2
40324453Smckusick 		 )) {		/* we should force a broken line here */
4048800Smckusick 		if (verbose && !flushed_nl)
40524453Smckusick 		    diag(0, "Line broken");
4068800Smckusick 		flushed_nl = false;
40724453Smckusick 		dump_line();
40824453Smckusick 		ps.want_blank = false;	/* dont insert blank at line start */
4098800Smckusick 		force_nl = false;
4108800Smckusick 	    }
41124453Smckusick 	    ps.in_stmt = true;	/* turn on flag which causes an extra
41224453Smckusick 				 * level of indentation. this is turned
41324453Smckusick 				 * off by a ; or '}' */
41424453Smckusick 	    if (s_com != e_com) {	/* the turkey has embedded a
41524453Smckusick 					 * comment in a line. fix it */
4168800Smckusick 		*e_code++ = ' ';
4178800Smckusick 		for (t_ptr = s_com; *t_ptr; ++t_ptr)
4188800Smckusick 		    *e_code++ = *t_ptr;
4198800Smckusick 		*e_code++ = ' ';
42024453Smckusick 		*e_code = '\0';	/* null terminate code sect */
42124453Smckusick 		ps.want_blank = false;
4228800Smckusick 		e_com = s_com;
4238800Smckusick 	    }
42424453Smckusick 	} else if (type_code != comment)	/* preserve force_nl thru
42524453Smckusick 						 * a comment */
42624453Smckusick 	    force_nl = false;
4278800Smckusick 
42824453Smckusick 	/*
42924453Smckusick 	 * cancel forced newline after newline, form feed, etc
43024453Smckusick 	 */
4318800Smckusick 
4328800Smckusick 
4338800Smckusick 
43424453Smckusick 	/*----------------------------------------------------*\
435*24648Smckusick 	|   do switch on type of token scanned
436*24648Smckusick 	\*----------------------------------------------------*/
43724453Smckusick 	switch (type_code) {	/* now, decide what to do with the token */
43824453Smckusick 
43924453Smckusick 	    case form_feed:	/* found a form feed in line */
44024453Smckusick 		ps.use_ff = true;	/* a form feed is treated much
44124453Smckusick 					 * like a newline */
44224453Smckusick 		dump_line();
44324453Smckusick 		ps.want_blank = false;
4448800Smckusick 		break;
4458800Smckusick 
44624453Smckusick 	    case newline:
44724453Smckusick 		if (ps.last_token != comma || ps.p_l_follow > 0
44824453Smckusick 		    || !ps.leave_comma || !break_comma || s_com != e_com) {
44924453Smckusick 		    dump_line();
45024453Smckusick 		    ps.want_blank = false;
45124453Smckusick 		}
45224453Smckusick 		++line_no;	/* keep track of input line number */
4538800Smckusick 		break;
4548800Smckusick 
45524453Smckusick 	    case lparen:	/* got a '(' or '[' */
45624453Smckusick 		++ps.p_l_follow;/* count parens to make Healy happy */
45724453Smckusick 		if (ps.want_blank && *token != '[' &&
45824453Smckusick 		    (ps.last_token != ident || proc_calls_space
45924453Smckusick 		     || (ps.its_a_keyword && !ps.sizeof_keyword)))
4608800Smckusick 		    *e_code++ = ' ';
46124453Smckusick 		if (ps.in_decl && !ps.block_init)
46224453Smckusick 		    if (troff && !ps.dumped_decl_indent) {
46324453Smckusick 			ps.dumped_decl_indent = 1;
46424453Smckusick 			sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
46524453Smckusick 			e_code += strlen(e_code);
46624453Smckusick 		    } else {
46724453Smckusick 			while ((e_code - s_code) < dec_ind)
46824453Smckusick 			    *e_code++ = ' ';
46924453Smckusick 			*e_code++ = token[0];
47024453Smckusick 		} else
47124453Smckusick 		    *e_code++ = token[0];
47224453Smckusick 		ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
47324453Smckusick 		ps.want_blank = false;
47424453Smckusick 		if (ps.in_or_st && *token == '(') {
4758800Smckusick 
47624453Smckusick 		    /*
47724453Smckusick 		     * this is a kluge to make sure that declarations will
47824453Smckusick 		     * be aligned right if proc decl has an explicit type
47924453Smckusick 		     * on it, i.e. "int a(x) {..."
48024453Smckusick 		     */
48124453Smckusick 		    parse(semicolon);	/* I said this was a kluge... */
48224453Smckusick 		    ps.in_or_st = false;	/* turn off flag for
48324453Smckusick 						 * structure decl or
48424453Smckusick 						 * initialization */
4858800Smckusick 		}
48624453Smckusick 		if (ps.sizeof_keyword) ps.sizeof_mask |= 1<<ps.p_l_follow;
4878800Smckusick 		break;
4888800Smckusick 
48924453Smckusick 	    case rparen:	/* got a ')' or ']' */
49024453Smckusick 		if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
49124453Smckusick 		    ps.last_u_d = true;
49224453Smckusick 		    ps.cast_mask &= (1 << ps.p_l_follow) - 1;
4938800Smckusick 		}
49424453Smckusick 		ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
49524453Smckusick 		if (--ps.p_l_follow < 0) {
49624453Smckusick 		    ps.p_l_follow = 0;
49724453Smckusick 		    diag(0, "Extra %c", *token);
49824453Smckusick 		}
49924453Smckusick 		if (e_code == s_code)	/* if the paren starts the line */
50024453Smckusick 		    ps.paren_level = ps.p_l_follow;	/* then indent it */
5018800Smckusick 
5028800Smckusick 		*e_code++ = token[0];
50324453Smckusick 		ps.want_blank = true;
5048800Smckusick 
50524453Smckusick 		if (sp_sw && (ps.p_l_follow == 0)) {	/* check for end of if
50624453Smckusick 							 * (...), or some such */
5078800Smckusick 		    sp_sw = false;
50824453Smckusick 		    force_nl = true;	/* must force newline after if */
50924453Smckusick 		    ps.last_u_d = true;	/* inform lexi that a following
51024453Smckusick 					 * operator is unary */
51124453Smckusick 		    ps.in_stmt = false;	/* dont use stmt continuation
51224453Smckusick 					 * indentation */
5138800Smckusick 
51424453Smckusick 		    parse(hd_type);	/* let parser worry about if, or
51524453Smckusick 					 * whatever */
5168800Smckusick 		}
51724453Smckusick 		ps.search_brace = btype_2;	/* this should insure that
51824453Smckusick 						 * constructs such as
51924453Smckusick 						 * main(){...} and
52024453Smckusick 						 * int[]{...} have their
52124453Smckusick 						 * braces put in the right
52224453Smckusick 						 * place */
5238800Smckusick 		break;
5248800Smckusick 
52524453Smckusick 	    case unary_op:	/* this could be any unary operation */
52624453Smckusick 		if (ps.want_blank)
5278800Smckusick 		    *e_code++ = ' ';
5288800Smckusick 
52924453Smckusick 		if (troff && !ps.dumped_decl_indent && ps.in_decl) {
53024453Smckusick 		    sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
53124453Smckusick 		    ps.dumped_decl_indent = 1;
53224453Smckusick 		    e_code += strlen(e_code);
53324453Smckusick 		} else {
53424453Smckusick 		    char       *res = token;
53524453Smckusick 
53624453Smckusick 		    if (ps.in_decl && !ps.block_init) {	/* if this is a unary op
53724453Smckusick 							 * in a declaration, we
53824453Smckusick 							 * should indent this
53924453Smckusick 							 * token */
54024453Smckusick 			for (i = 0; token[i]; ++i);	/* find length of token */
54124453Smckusick 			while ((e_code - s_code) < (dec_ind - i))
54224453Smckusick 			    *e_code++ = ' ';	/* pad it */
54324453Smckusick 		    }
54424453Smckusick 		    if (troff && token[0] == '-' && token[1] == '>')
54524453Smckusick 			res = "\\(->";
54624453Smckusick 		    for (t_ptr = res; *t_ptr; ++t_ptr)
54724453Smckusick 			*e_code++ = *t_ptr;
5488800Smckusick 		}
54924453Smckusick 		ps.want_blank = false;
5508800Smckusick 		break;
5518800Smckusick 
55224453Smckusick 	    case binary_op:	/* any binary operation */
55324453Smckusick 	do_binary:
55424453Smckusick 		if (ps.want_blank)
5558800Smckusick 		    *e_code++ = ' ';
55624453Smckusick 		{
55724453Smckusick 		    char       *res = token;
55824453Smckusick 
55924453Smckusick 		    if (troff)
56024453Smckusick 			switch (token[0]) {
56124453Smckusick 			    case '<':
56224453Smckusick 				if (token[1] == '=')
56324453Smckusick 				    res = "\\(<=";
56424453Smckusick 				break;
56524453Smckusick 			    case '>':
56624453Smckusick 				if (token[1] == '=')
56724453Smckusick 				    res = "\\(>=";
56824453Smckusick 				break;
56924453Smckusick 			    case '!':
57024453Smckusick 				if (token[1] == '=')
57124453Smckusick 				    res = "\\(!=";
57224453Smckusick 				break;
57324453Smckusick 			    case '|':
57424453Smckusick 				if (token[1] == '|')
57524453Smckusick 				    res = "\\(br\\(br";
57624453Smckusick 				else if (token[1] == 0)
57724453Smckusick 				    res = "\\(br";
57824453Smckusick 				break;
57924453Smckusick 			}
58024453Smckusick 		    for (t_ptr = res; *t_ptr; ++t_ptr)
58124453Smckusick 			*e_code++ = *t_ptr;	/* move the operator */
58224453Smckusick 		}
58324453Smckusick 		ps.want_blank = true;
5848800Smckusick 		break;
5858800Smckusick 
58624453Smckusick 	    case postop:	/* got a trailing ++ or -- */
5878800Smckusick 		*e_code++ = token[0];
5888800Smckusick 		*e_code++ = token[1];
58924453Smckusick 		ps.want_blank = true;
5908800Smckusick 		break;
5918800Smckusick 
59224453Smckusick 	    case question:	/* got a ? */
59324453Smckusick 		squest++;	/* this will be used when a later colon
59424453Smckusick 				 * appears so we can distinguish the
59524453Smckusick 				 * <c>?<n>:<n> construct */
59624453Smckusick 		if (ps.want_blank)
5978800Smckusick 		    *e_code++ = ' ';
5988800Smckusick 		*e_code++ = '?';
59924453Smckusick 		ps.want_blank = true;
6008800Smckusick 		break;
6018800Smckusick 
60224453Smckusick 	    case casestmt:	/* got word 'case' or 'default' */
60324453Smckusick 		scase = true;	/* so we can process the later colon
60424453Smckusick 				 * properly */
60524453Smckusick 		goto copy_id;
6068800Smckusick 
60724453Smckusick 	    case colon:	/* got a ':' */
60824453Smckusick 		if (squest > 0) {	/* it is part of the <c>?<n>: <n>
60924453Smckusick 					 * construct */
6108800Smckusick 		    --squest;
61124453Smckusick 		    if (ps.want_blank)
6128800Smckusick 			*e_code++ = ' ';
6138800Smckusick 		    *e_code++ = ':';
61424453Smckusick 		    ps.want_blank = true;
6158800Smckusick 		    break;
6168800Smckusick 		}
61724453Smckusick 		if (ps.in_decl) {
61824453Smckusick 		    *e_code++ = ':';
61924453Smckusick 		    ps.want_blank = false;
62024453Smckusick 		    break;
62124453Smckusick 		}
62224453Smckusick 		ps.in_stmt = false;	/* seeing a label does not imply
62324453Smckusick 					 * we are in a stmt */
6248800Smckusick 		for (t_ptr = s_code; *t_ptr; ++t_ptr)
62524453Smckusick 		    *e_lab++ = *t_ptr;	/* turn everything so far into a
62624453Smckusick 					 * label */
6278800Smckusick 		e_code = s_code;
6288800Smckusick 		*e_lab++ = ':';
6298800Smckusick 		*e_lab++ = ' ';
6308800Smckusick 		*e_lab = '\0';
6318800Smckusick 
63224453Smckusick 		force_nl = ps.pcase = scase;	/* ps.pcase will be used
63324453Smckusick 						 * by dump_line to decide
63424453Smckusick 						 * how to indent the
63524453Smckusick 						 * label. force_nl will
63624453Smckusick 						 * force a case n: to be
63724453Smckusick 						 * on a line by itself */
6388800Smckusick 		scase = false;
63924453Smckusick 		ps.want_blank = false;
6408800Smckusick 		break;
6418800Smckusick 
64224453Smckusick 	    case semicolon:	/* got a ';' */
64324453Smckusick 		ps.in_or_st = false;	/* we are not in an initialization
64424453Smckusick 					 * or structure declaration */
64524453Smckusick 		scase = false;	/* these will only need resetting in a
64624453Smckusick 				 * error */
6478800Smckusick 		squest = 0;
64824453Smckusick 		if (ps.last_token == rparen)
64924453Smckusick 		    ps.in_parameter_declaration = 0;
65024453Smckusick 		ps.cast_mask = 0;
65124453Smckusick 		ps.sizeof_mask = 0;
65224453Smckusick 		ps.block_init = 0;
65324453Smckusick 		ps.just_saw_decl--;
6548800Smckusick 
65524453Smckusick 		if (ps.in_decl && s_code == e_code && !ps.block_init)
6568800Smckusick 		    while ((e_code - s_code) < (dec_ind - 1))
6578800Smckusick 			*e_code++ = ' ';
6588800Smckusick 
65924453Smckusick 		ps.in_decl = (ps.dec_nest > 0);	/* if we were in a first
66024453Smckusick 						 * level structure
66124453Smckusick 						 * declaration, we arent
66224453Smckusick 						 * any more */
6638800Smckusick 
66424453Smckusick 		if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
66524453Smckusick 
66624453Smckusick 		    /*
66724453Smckusick 		     * This should be true iff there were unbalanced
66824453Smckusick 		     * parens in the stmt.  It is a bit complicated,
66924453Smckusick 		     * because the semicolon might be in a for stmt
67024453Smckusick 		     */
67124453Smckusick 		    diag(1, "Unbalanced parens");
67224453Smckusick 		    ps.p_l_follow = 0;
67324453Smckusick 		    if (sp_sw) {/* this is a check for a if, while, etc.
67424453Smckusick 				 * with unbalanced parens */
6758800Smckusick 			sp_sw = false;
67624453Smckusick 			parse(hd_type);	/* dont lose the if, or whatever */
6778800Smckusick 		    }
6788800Smckusick 		}
6798800Smckusick 		*e_code++ = ';';
68024453Smckusick 		ps.want_blank = true;
68124453Smckusick 		ps.in_stmt = (ps.p_l_follow > 0);	/* we are no longer in
68224453Smckusick 							 * the middle of a stmt */
6838800Smckusick 
68424453Smckusick 		if (!sp_sw) {	/* if not if for (;;) */
68524453Smckusick 		    parse(semicolon);	/* let parser know about end of
68624453Smckusick 					 * stmt */
68724453Smckusick 		    force_nl = true;	/* force newline after a end of
68824453Smckusick 					 * stmt */
6898800Smckusick 		}
6908800Smckusick 		break;
6918800Smckusick 
69224453Smckusick 	    case lbrace:	/* got a '{' */
69324453Smckusick 		ps.in_stmt = false;	/* dont indent the {} */
69424453Smckusick 		if (!ps.block_init)
69524453Smckusick 		    force_nl = true;	/* force other stuff on same line
69624453Smckusick 					 * as '{' onto new line */
6978800Smckusick 
69824453Smckusick 		if (s_code != e_code && !ps.block_init) {
69924453Smckusick 		    if (!btype_2) {
70024453Smckusick 			dump_line();
70124453Smckusick 			ps.want_blank = false;
70224453Smckusick 		    } else if (ps.in_parameter_declaration && !ps.in_or_st) {
70324453Smckusick 			ps.i_l_follow = 0;
70424453Smckusick 			dump_line();
70524453Smckusick 			ps.want_blank = false;
70624453Smckusick 		    }
7078800Smckusick 		}
70824453Smckusick 		if (ps.in_parameter_declaration)
70924453Smckusick 		    prefix_blankline_requested = 0;
7108800Smckusick 
711*24648Smckusick 		if (ps.p_l_follow > 0) {	/* check for preceding
71224453Smckusick 						 * unbalanced parens */
71324453Smckusick 		    diag(1, "Unbalanced parens");
71424453Smckusick 		    ps.p_l_follow = 0;
71524453Smckusick 		    if (sp_sw) {/* check for unclosed if, for, etc. */
7168800Smckusick 			sp_sw = false;
71724453Smckusick 			parse(hd_type);
71824453Smckusick 			ps.ind_level = ps.i_l_follow;
7198800Smckusick 		    }
7208800Smckusick 		}
7218800Smckusick 		if (s_code == e_code)
72224453Smckusick 		    ps.ind_stmt = false;	/* dont put extra
72324453Smckusick 						 * indentation on line
72424453Smckusick 						 * with '{' */
72524453Smckusick 		if (ps.in_decl && ps.in_or_st) {	/* this is either a
72624453Smckusick 							 * structure declaration
72724453Smckusick 							 * or an init */
72824453Smckusick 		    di_stack[ps.dec_nest++] = dec_ind;
7298800Smckusick 		    dec_ind = 0;
73024453Smckusick 		} else {
73124453Smckusick 		    ps.decl_on_line = false;	/* we cant be in the
73224453Smckusick 						 * middle of a
73324453Smckusick 						 * declaration, so dont do
73424453Smckusick 						 * special indentation of
73524453Smckusick 						 * comments */
73624453Smckusick 		    ps.in_parameter_declaration = 0;
7378800Smckusick 		}
73824453Smckusick 		parse(lbrace);	/* let parser know about this */
73924453Smckusick 		if (ps.want_blank)	/* put a blank before '{' if '{'
74024453Smckusick 					 * is not at start of line */
7418800Smckusick 		    *e_code++ = ' ';
74224453Smckusick 		ps.want_blank = false;
7438800Smckusick 		*e_code++ = '{';
74424453Smckusick 		ps.just_saw_decl = 0;
7458800Smckusick 		break;
7468800Smckusick 
74724453Smckusick 	    case rbrace:	/* got a '}' */
74824453Smckusick 		if (ps.p_l_follow) {	/* check for unclosed if, for,
74924453Smckusick 					 * else. */
75024453Smckusick 		    diag(1, "Unbalanced parens");
75124453Smckusick 		    ps.p_l_follow = 0;
7528800Smckusick 		    sp_sw = false;
7538800Smckusick 		}
75424453Smckusick 		ps.just_saw_decl = 0;
75524453Smckusick 		if (s_code != e_code && !ps.block_init) {	/* '}' must be first on
75624453Smckusick 								 * line */
7578800Smckusick 		    if (verbose)
75824453Smckusick 			diag(0, "Line broken");
75924453Smckusick 		    dump_line();
7608800Smckusick 		}
7618800Smckusick 		*e_code++ = '}';
76224453Smckusick 		ps.want_blank = true;
76324453Smckusick 		ps.in_stmt = ps.ind_stmt = false;
76424453Smckusick 		if (ps.dec_nest > 0) {	/* we are in multi-level structure
76524453Smckusick 					 * declaration */
76624453Smckusick 		    dec_ind = di_stack[--ps.dec_nest];
76724453Smckusick 		    if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
76824453Smckusick 			ps.just_saw_decl = 2;
76924453Smckusick 		    ps.in_decl = true;
7708800Smckusick 		}
77124453Smckusick 		prefix_blankline_requested = 0;
77224453Smckusick 		parse(rbrace);	/* let parser know about this */
77324453Smckusick 		ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead && ps.il[ps.tos] >= ps.ind_level;
77424453Smckusick 		if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
77524453Smckusick 		    postfix_blankline_requested = 1;
7768800Smckusick 		break;
7778800Smckusick 
77824453Smckusick 	    case swstmt:	/* got keyword "switch" */
7798800Smckusick 		sp_sw = true;
78024453Smckusick 		hd_type = swstmt;	/* keep this for when we have seen
78124453Smckusick 					 * the expression */
78224453Smckusick 		goto copy_id;	/* go move the token into buffer */
7838800Smckusick 
78424453Smckusick 	    case sp_paren:	/* token is if, while, for */
78524453Smckusick 		sp_sw = true;	/* the interesting stuff is done after the
78624453Smckusick 				 * expression is scanned */
7878800Smckusick 		hd_type = (*token == 'i' ? ifstmt :
78824453Smckusick 			   (*token == 'w' ? whilestmt : forstmt));
7898800Smckusick 
79024453Smckusick 		/*
79124453Smckusick 		 * remember the type of header for later use by parser
79224453Smckusick 		 */
79324453Smckusick 		goto copy_id;	/* copy the token into line */
79424453Smckusick 
79524453Smckusick 	    case sp_nparen:	/* got else, do */
79624453Smckusick 		ps.in_stmt = false;
79724453Smckusick 		if (*token == 'e') {
79824453Smckusick 		    if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
79924453Smckusick 			if (verbose)
80024453Smckusick 			    diag(0, "Line broken");
80124453Smckusick 			dump_line();	/* make sure this starts a line */
80224453Smckusick 			ps.want_blank = false;
80324453Smckusick 		    }
80424453Smckusick 		    force_nl = true;	/* also, following stuff must go
80524453Smckusick 					 * onto new line */
80624453Smckusick 		    last_else = 1;
80724453Smckusick 		    parse(elselit);
80824453Smckusick 		} else {
80924453Smckusick 		    if (e_code != s_code) {	/* make sure this starts a
81024453Smckusick 						 * line */
81124453Smckusick 			if (verbose)
81224453Smckusick 			    diag(0, "Line broken");
81324453Smckusick 			dump_line();
81424453Smckusick 			ps.want_blank = false;
81524453Smckusick 		    }
81624453Smckusick 		    force_nl = true;	/* also, following stuff must go
81724453Smckusick 					 * onto new line */
81824453Smckusick 		    last_else = 0;
81924453Smckusick 		    parse(dolit);
8208800Smckusick 		}
82124453Smckusick 		goto copy_id;	/* move the token into line */
8228800Smckusick 
82324453Smckusick 	    case decl:		/* we have a declaration type (int,
82424453Smckusick 				 * register, etc.) */
82524453Smckusick 		parse(decl);	/* let parser worry about indentation */
82624453Smckusick 		if (ps.last_token == rparen && ps.tos <= 1)
82724453Smckusick 		    ps.in_parameter_declaration = 1;
82824453Smckusick 		if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
82924453Smckusick 		    ps.ind_level = ps.i_l_follow = 1;
83024453Smckusick 		    ps.ind_stmt = 0;
83124453Smckusick 		}
83224453Smckusick 		ps.in_or_st = true;	/* this might be a structure or
83324453Smckusick 					 * initialization declaration */
83424453Smckusick 		ps.in_decl = ps.decl_on_line = true;
83524453Smckusick 		if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
83624453Smckusick 		    ps.just_saw_decl = 2;
83724453Smckusick 		prefix_blankline_requested = 0;
83824453Smckusick 		for (i = 0; token[i++];);	/* get length of token */
8398800Smckusick 
84024453Smckusick 		/*
84124453Smckusick 		 * dec_ind = e_code - s_code + (ps.decl_indent>i ?
84224453Smckusick 		 * ps.decl_indent : i);
84324453Smckusick 		 */
84424453Smckusick 		dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
8458800Smckusick 		goto copy_id;
8468800Smckusick 
84724453Smckusick 	    case ident:	/* got an identifier or constant */
84824453Smckusick 		if (ps.in_decl) {	/* if we are in a declaration, we
84924453Smckusick 					 * must indent identifier */
85024453Smckusick 		    if (ps.want_blank)
8518800Smckusick 			*e_code++ = ' ';
85224453Smckusick 		    ps.want_blank = false;
85324453Smckusick 		    if (is_procname == 0 || !procnames_start_line) {
85424453Smckusick 			if (!ps.block_init)
85524453Smckusick 			    if (troff && !ps.dumped_decl_indent) {
85624453Smckusick 				sprintf(e_code, "\\c\n.De %dp+\200p\n", dec_ind * 7);
85724453Smckusick 				ps.dumped_decl_indent = 1;
85824453Smckusick 				e_code += strlen(e_code);
85924453Smckusick 			    } else
86024453Smckusick 				while ((e_code - s_code) < dec_ind)
86124453Smckusick 				    *e_code++ = ' ';
86224453Smckusick 		    } else {
86324453Smckusick 			if (dec_ind && s_code != e_code)
86424453Smckusick 			    dump_line();
86524453Smckusick 			dec_ind = 0;
86624453Smckusick 			ps.want_blank = false;
86724453Smckusick 		    }
86824453Smckusick 		} else if (sp_sw && ps.p_l_follow == 0) {
86924453Smckusick 		    sp_sw = false;
87024453Smckusick 		    force_nl = true;
87124453Smckusick 		    ps.last_u_d = true;
87224453Smckusick 		    ps.in_stmt = false;
87324453Smckusick 		    parse(hd_type);
8748800Smckusick 		}
87524453Smckusick 	copy_id:
87624453Smckusick 		if (ps.want_blank)
8778800Smckusick 		    *e_code++ = ' ';
87824453Smckusick 		if (troff && ps.its_a_keyword) {
87924453Smckusick 		    *e_code++ = BACKSLASH;
88024453Smckusick 		    *e_code++ = 'f';
88124453Smckusick 		    *e_code++ = 'B';
88224453Smckusick 		}
8838800Smckusick 		for (t_ptr = token; *t_ptr; ++t_ptr)
8848800Smckusick 		    *e_code++ = *t_ptr;
88524453Smckusick 		if (troff && ps.its_a_keyword) {
88624453Smckusick 		    *e_code++ = BACKSLASH;
88724453Smckusick 		    *e_code++ = 'f';
88824453Smckusick 		    *e_code++ = 'R';
88924453Smckusick 		}
89024453Smckusick 		ps.want_blank = true;
8918800Smckusick 		break;
8928800Smckusick 
89324453Smckusick 	    case period:	/* treat a period kind of like a binary
89424453Smckusick 				 * operation */
89524453Smckusick 		*e_code++ = '.';/* move the period into line */
89624453Smckusick 		ps.want_blank = false;	/* dont put a blank after a period */
8978800Smckusick 		break;
8988800Smckusick 
89924453Smckusick 	    case comma:
90024453Smckusick 		ps.want_blank = (s_code != e_code);	/* only put blank after
90124453Smckusick 							 * comma if comma does
90224453Smckusick 							 * not start the line */
90324453Smckusick 		if (ps.in_decl && is_procname == 0 && !ps.block_init)
9048800Smckusick 		    while ((e_code - s_code) < (dec_ind - 1))
9058800Smckusick 			*e_code++ = ' ';
9068800Smckusick 
9078800Smckusick 		*e_code++ = ',';
90824453Smckusick 		if (ps.p_l_follow == 0) {
90924453Smckusick 		    ps.block_init = 0;
91024453Smckusick 		    if (break_comma && !ps.leave_comma)
91124453Smckusick 			force_nl = true;
91224453Smckusick 		}
9138800Smckusick 		break;
9148800Smckusick 
91524453Smckusick 	    case preesc:	/* got the character '#' */
91624453Smckusick 		if ((s_com != e_com) ||
91724453Smckusick 		    (s_lab != e_lab) ||
91824453Smckusick 		    (s_code != e_code))
91924453Smckusick 		    dump_line();
92024453Smckusick 		*e_lab++ = '#';	/* move whole line to 'label' buffer */
92124453Smckusick 		{
92224453Smckusick 		    int         in_comment = 0;
92324453Smckusick 		    char       *com_start = 0;
92424453Smckusick 		    char        quote = 0;
92524453Smckusick 		    char       *com_end = 0;
9268800Smckusick 
92724453Smckusick 		    while (*buf_ptr != '\n' || in_comment) {
92824453Smckusick 			*e_lab = *buf_ptr++;
92924453Smckusick 			if (buf_ptr >= buf_end)
93024453Smckusick 			    fill_buffer();
93124453Smckusick 			switch (*e_lab++) {
93224453Smckusick 			    case BACKSLASH:
93324453Smckusick 				if (troff)
93424453Smckusick 				    *e_lab++ = BACKSLASH;
93524453Smckusick 				if (!in_comment) {
93624453Smckusick 				    *e_lab++ = *buf_ptr++;
93724453Smckusick 				    if (buf_ptr >= buf_end)
93824453Smckusick 					fill_buffer();
93924453Smckusick 				}
94024453Smckusick 				break;
94124453Smckusick 			    case '/':
94224453Smckusick 				if (*buf_ptr == '*' && !in_comment && !quote) {
94324453Smckusick 				    in_comment = 1;
94424453Smckusick 				    *e_lab++ = *buf_ptr++;
94524453Smckusick 				    com_start = e_lab - 2;
94624453Smckusick 				}
94724453Smckusick 				break;
94824453Smckusick 			    case '"':
94924453Smckusick 				if (quote == '"')
95024453Smckusick 				    quote = 0;
95124453Smckusick 				break;
95224453Smckusick 			    case '\'':
95324453Smckusick 				if (quote == '\'')
95424453Smckusick 				    quote = 0;
95524453Smckusick 				break;
95624453Smckusick 			    case '*':
95724453Smckusick 				if (*buf_ptr == '/' && in_comment) {
95824453Smckusick 				    in_comment = 0;
95924453Smckusick 				    *e_lab++ = *buf_ptr++;
96024453Smckusick 				    com_end = e_lab;
96124453Smckusick 				}
96224453Smckusick 				break;
96324453Smckusick 			}
9648800Smckusick 		    }
96524453Smckusick 		    while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
96624453Smckusick 			e_lab--;
96724453Smckusick 		    if (e_lab == com_end && bp_save == 0) {	/* comment on
96824453Smckusick 								 * preprocessor line */
96924453Smckusick 			if (sc_end == 0)	/* if this is the first
97024453Smckusick 						 * comment, we must set up
97124453Smckusick 						 * the buffer */
97224453Smckusick 			    sc_end = &(save_com[0]);
97324453Smckusick 			else {
97424453Smckusick 			    *sc_end++ = '\n';	/* add newline between
97524453Smckusick 						 * comments */
97624453Smckusick 			    *sc_end++ = ' ';
97724453Smckusick 			    --line_no;
97824453Smckusick 			}
97924453Smckusick 			bcopy(com_start, sc_end, com_end - com_start);
98024453Smckusick 			sc_end += com_end - com_start;
98124453Smckusick 			e_lab = com_start;
98224453Smckusick 			while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
98324453Smckusick 			    e_lab--;
98424453Smckusick 			bp_save = buf_ptr;	/* save current input
98524453Smckusick 						 * buffer */
98624453Smckusick 			be_save = buf_end;
98724453Smckusick 			buf_ptr = save_com;	/* fix so that subsequent
98824453Smckusick 						 * calls to lexi will take
98924453Smckusick 						 * tokens out of save_com */
99024453Smckusick 			*sc_end++ = ' ';	/* add trailing blank,
99124453Smckusick 						 * just in case */
99224453Smckusick 			buf_end = sc_end;
99324453Smckusick 			sc_end = 0;
99424453Smckusick 		    }
99524453Smckusick 		    *e_lab = '\0';	/* null terminate line */
99624453Smckusick 		    ps.pcase = false;
9978800Smckusick 		}
99824453Smckusick 		if (strncmp(s_lab, "#if", 3) == 0)
99924453Smckusick 		    if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) {
100024453Smckusick 			match_state[ifdef_level].tos = -1;
100124453Smckusick 			state_stack[ifdef_level++] = ps;
100224453Smckusick 		    } else
100324453Smckusick 			diag(1, "#if stack overflow");
100424453Smckusick 		else if (strncmp(s_lab, "#else", 5) == 0)
100524453Smckusick 		    if (ifdef_level <= 0)
100624453Smckusick 			diag(1, "Unmatched #else");
100724453Smckusick 		    else {
100824453Smckusick 			match_state[ifdef_level - 1] = ps;
100924453Smckusick 			ps = state_stack[ifdef_level - 1];
101024453Smckusick 		} else if (strncmp(s_lab, "#endif", 6) == 0)
101124453Smckusick 		    if (ifdef_level <= 0)
101224453Smckusick 			diag(1, "Unmatched #endif");
101324453Smckusick 		    else {
101424453Smckusick 			ifdef_level--;
101524453Smckusick #ifdef undef
10168800Smckusick 
101724453Smckusick 			/*
101824453Smckusick 			 * This match needs to be more intelligent before
101924453Smckusick 			 * the message is useful
102024453Smckusick 			 */
102124453Smckusick 			if (match_state[ifdef_level].tos >= 0
102224453Smckusick 			    && bcmp(&ps, &match_state[ifdef_level], sizeof ps))
102324453Smckusick 			    diag(0, "Syntactically inconsistant #ifdef alternatives.");
102424453Smckusick #endif
102524453Smckusick 		    }
102624453Smckusick 		break;		/* subsequent processing of the newline
102724453Smckusick 				 * character will cause the line to be
102824453Smckusick 				 * printed */
10298800Smckusick 
103024453Smckusick 	    case comment:	/* we have gotten a /*  this is a biggie */
103124453Smckusick 	proc_comment:
103224453Smckusick 		if (flushed_nl) {	/* we should force a broken line
103324453Smckusick 					 * here */
103424453Smckusick 		    flushed_nl = false;
103524453Smckusick 		    dump_line();
103624453Smckusick 		    ps.want_blank = false;	/* dont insert blank at
103724453Smckusick 						 * line start */
103824453Smckusick 		    force_nl = false;
103924453Smckusick 		}
104024453Smckusick 		pr_comment();
10418800Smckusick 		break;
104224453Smckusick 	}			/* end of big switch stmt */
104324453Smckusick 	*e_code = '\0';		/* make sure code section is null
104424453Smckusick 				 * terminated */
104524453Smckusick 	if (type_code != comment && type_code != newline && type_code != preesc)
104624453Smckusick 	    ps.last_token = type_code;
104724453Smckusick     }				/* end of main while (1) loop */
10488800Smckusick };
10498800Smckusick 
10508800Smckusick /*
1051*24648Smckusick  * copy input file to backup file.  If in_name is /blah/blah/blah/file, then
1052*24648Smckusick  * backup file will be "file.BAK".  Then make the backup file the input and
1053*24648Smckusick  * original input file the output.
10548800Smckusick  */
105524453Smckusick bakcopy()
105624453Smckusick {
105724453Smckusick     int         n,
105824453Smckusick                 bakchn;
1059*24648Smckusick     char        buff[BUFSIZ];
106024453Smckusick     register char *p;
1061*24648Smckusick     char *rindex();
10628800Smckusick 
1063*24648Smckusick     if ((p = rindex(in_name, '/')) != NULL)
10648800Smckusick 	p++;
1065*24648Smckusick     else
1066*24648Smckusick 	p = in_name;
106724453Smckusick     sprintf(bakfile, "%s.BAK", p);
10688800Smckusick 
106924453Smckusick     /* copy in_name to backup file */
107024453Smckusick     bakchn = creat(bakfile, 0600);
10718800Smckusick     if (bakchn < 0) {
1072*24648Smckusick 	fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile);
1073*24648Smckusick 	exit(1);
10748800Smckusick     }
1075*24648Smckusick     while ((n = read(fileno(input), buff, sizeof buff)) > 0)
1076*24648Smckusick 	if (write(bakchn, buff, n) != n) {
1077*24648Smckusick 	    fprintf(stderr, "indent: error writing backup file \"%s\"\n",
1078*24648Smckusick 		bakfile);
1079*24648Smckusick 	    exit(1);
1080*24648Smckusick 	}
1081*24648Smckusick     if (n < 0) {
1082*24648Smckusick 	fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name);
1083*24648Smckusick 	exit(1);
1084*24648Smckusick     }
108524453Smckusick     close(bakchn);
108624453Smckusick     fclose(input);
10878800Smckusick 
108824453Smckusick     /* re-open backup file as the input file */
108924453Smckusick     input = fopen(bakfile, "r");
1090*24648Smckusick     if (input == NULL) {
1091*24648Smckusick 	fprintf(stderr, "indent: can't re-open backup file\n");
1092*24648Smckusick 	exit(1);
10938800Smckusick     }
109424453Smckusick     /* now the original input file will be the output */
109524453Smckusick     output = fopen(in_name, "w");
1096*24648Smckusick     if (output == NULL) {
1097*24648Smckusick 	fprintf(stderr, "indent: can't create %s\n", in_name);
109824453Smckusick 	unlink(bakfile);
1099*24648Smckusick 	exit(1);
11008800Smckusick     }
11018800Smckusick }
1102