indent.c revision 99112
1233294Sstas/*
2102644Snectar * Copyright (c) 1985 Sun Microsystems, Inc.
355682Smarkm * Copyright (c) 1976 Board of Trustees of the University of Illinois.
4142403Snectar * Copyright (c) 1980, 1993
5233294Sstas *	The Regents of the University of California.  All rights reserved.
6233294Sstas *
755682Smarkm * Redistribution and use in source and binary forms, with or without
855682Smarkm * modification, are permitted provided that the following conditions
955682Smarkm * are met:
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1355682Smarkm *    notice, this list of conditions and the following disclaimer in the
1455682Smarkm *    documentation and/or other materials provided with the distribution.
1555682Smarkm * 3. All advertising materials mentioning features or use of this software
1690926Snectar *    must display the following acknowledgement:
1790926Snectar *	This product includes software developed by the University of
18233294Sstas *	California, Berkeley and its contributors.
1990926Snectar * 4. Neither the name of the University nor the names of its contributors
20233294Sstas *    may be used to endorse or promote products derived from this software
2190926Snectar *    without specific prior written permission.
22233294Sstas *
2355682Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2455682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2555682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2755682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29102644Snectar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30102644Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31102644Snectar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32127808Snectar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3390926Snectar * SUCH DAMAGE.
34127808Snectar */
3555682Smarkm
3655682Smarkm#ifndef lint
3755682Smarkmstatic const char copyright[] =
3855682Smarkm"@(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\
3955682Smarkm@(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\
4055682Smarkm@(#) Copyright (c) 1980, 1993\n\
41178825Sdfr	The Regents of the University of California.  All rights reserved.\n";
4255682Smarkm#endif /* not lint */
43142403Snectar
44142403Snectar#ifndef lint
45142403Snectar#if 0
46233294Sstasstatic char sccsid[] = "@(#)indent.c	5.17 (Berkeley) 6/7/93";
47233294Sstas#endif
48178825Sdfr#endif /* not lint */
49142403Snectar#include <sys/cdefs.h>
50233294Sstas__FBSDID("$FreeBSD: head/usr.bin/indent/indent.c 99112 2002-06-30 05:25:07Z obrien $");
51142403Snectar
52142403Snectar#include <sys/param.h>
53142403Snectar#include <err.h>
54233294Sstas#include <fcntl.h>
55142403Snectar#include <unistd.h>
56142403Snectar#include <stdio.h>
57142403Snectar#include <stdlib.h>
58142403Snectar#include <string.h>
59142403Snectar#include <ctype.h>
60142403Snectar#include "indent_globs.h"
61142403Snectar#include "indent_codes.h"
62142403Snectar#include "indent.h"
63142403Snectar
64142403Snectarstatic void bakcopy(void);
65142403Snectar
66142403Snectarconst char *in_name = "Standard Input";	/* will always point to name of input
67142403Snectar					 * file */
68142403Snectarconst char *out_name = "Standard Output";	/* will always point to name
69233294Sstas						 * of output file */
70142403Snectarchar        bakfile[MAXPATHLEN] = "";
71142403Snectar
72142403Snectarint
73142403Snectarmain(int argc, char **argv)
74178825Sdfr{
75142403Snectar
76142403Snectar    extern int  found_err;	/* flag set in diagN() on error */
77142403Snectar    int         dec_ind;	/* current indentation for declarations */
78142403Snectar    int         di_stack[20];	/* a stack of structure indentation levels */
79142403Snectar    int         flushed_nl;	/* used when buffering up comments to remember
80142403Snectar				 * that a newline was passed over */
81142403Snectar    int         force_nl;	/* when true, code must be broken */
82142403Snectar    int         hd_type = 0;	/* used to store type of stmt for if (...),
83233294Sstas				 * for (...), etc */
84233294Sstas    int i;		/* local loop counter */
85233294Sstas    int         scase;		/* set to true when we see a case, so we will
86233294Sstas				 * know what to do with the following colon */
87233294Sstas    int         sp_sw;		/* when true, we are in the expressin of
88233294Sstas				 * if(...), while(...), etc. */
89178825Sdfr    int         squest;		/* when this is positive, we have seen a ?
90178825Sdfr				 * without the matching : in a <c>?<s>:<s>
91178825Sdfr				 * construct */
92178825Sdfr    const char *t_ptr;		/* used for copying tokens */
93178825Sdfr    int         type_code;	/* the type of token, returned by lexi */
94178825Sdfr
95178825Sdfr    int         last_else = 0;	/* true iff last keyword was an else */
96233294Sstas
97142403Snectar
98142403Snectar    /*-----------------------------------------------*\
99178825Sdfr    |		      INITIALIZATION		      |
100142403Snectar    \*-----------------------------------------------*/
101142403Snectar
102233294Sstas
103178825Sdfr    ps.p_stack[0] = stmt;	/* this is the parser's stack */
104233294Sstas    ps.last_nl = true;		/* this is true if the last thing scanned was
105178825Sdfr				 * a newline */
106142403Snectar    ps.last_token = semicolon;
107142403Snectar    combuf = (char *) malloc(bufsize);
108142403Snectar    labbuf = (char *) malloc(bufsize);
109233294Sstas    codebuf = (char *) malloc(bufsize);
110142403Snectar    tokenbuf = (char *) malloc(bufsize);
111142403Snectar    l_com = combuf + bufsize - 5;
112142403Snectar    l_lab = labbuf + bufsize - 5;
113233294Sstas    l_code = codebuf + bufsize - 5;
114233294Sstas    l_token = tokenbuf + bufsize - 5;
115233294Sstas    combuf[0] = codebuf[0] = labbuf[0] = ' ';	/* set up code, label, and
116233294Sstas						 * comment buffers */
117233294Sstas    combuf[1] = codebuf[1] = labbuf[1] = '\0';
118233294Sstas    ps.else_if = 1;		/* Default else-if special processing to on */
119233294Sstas    s_lab = e_lab = labbuf + 1;
120233294Sstas    s_code = e_code = codebuf + 1;
121233294Sstas    s_com = e_com = combuf + 1;
122233294Sstas    s_token = e_token = tokenbuf + 1;
123233294Sstas
124233294Sstas    in_buffer = (char *) malloc(10);
125233294Sstas    in_buffer_limit = in_buffer + 8;
126142403Snectar    buf_ptr = buf_end = in_buffer;
127142403Snectar    line_no = 1;
128142403Snectar    had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
129142403Snectar    sp_sw = force_nl = false;
130142403Snectar    ps.in_or_st = false;
131142403Snectar    ps.bl_line = true;
132142403Snectar    dec_ind = 0;
133142403Snectar    di_stack[ps.dec_nest = 0] = 0;
134178825Sdfr    ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
135178825Sdfr
136178825Sdfr
137178825Sdfr    scase = ps.pcase = false;
138178825Sdfr    squest = 0;
139142403Snectar    sc_end = 0;
140178825Sdfr    bp_save = 0;
141178825Sdfr    be_save = 0;
142142403Snectar
143142403Snectar    output = 0;
144142403Snectar
145142403Snectar
146142403Snectar
147142403Snectar    /*--------------------------------------------------*\
148178825Sdfr    |   		COMMAND LINE SCAN		 |
149178825Sdfr    \*--------------------------------------------------*/
150178825Sdfr
151142403Snectar#ifdef undef
152142403Snectar    max_col = 78;		/* -l78 */
153142403Snectar    lineup_to_parens = 1;	/* -lp */
154178825Sdfr    ps.ljust_decl = 0;		/* -ndj */
155178825Sdfr    ps.com_ind = 33;		/* -c33 */
156233294Sstas    star_comment_cont = 1;	/* -sc */
157233294Sstas    ps.ind_size = 8;		/* -i8 */
158142403Snectar    verbose = 0;
159142403Snectar    ps.decl_indent = 16;	/* -di16 */
160142403Snectar    ps.indent_parameters = 1;	/* -ip */
161142403Snectar    ps.decl_com_ind = 0;	/* if this is not set to some positive value
162142403Snectar				 * by an arg, we will set this equal to
163142403Snectar				 * ps.com_ind */
164233294Sstas    btype_2 = 1;		/* -br */
165233294Sstas    cuddle_else = 1;		/* -ce */
166233294Sstas    ps.unindent_displace = 0;	/* -d0 */
167142403Snectar    ps.case_indent = 0;		/* -cli0 */
168142403Snectar    format_block_comments = 1;	/* -fcb */
169178825Sdfr    format_col1_comments = 1;	/* -fc1 */
170178825Sdfr    procnames_start_line = 1;	/* -psl */
171178825Sdfr    proc_calls_space = 0;	/* -npcs */
172142403Snectar    comment_delimiter_on_blankline = 1;	/* -cdb */
173178825Sdfr    ps.leave_comma = 1;		/* -nbc */
174178825Sdfr#endif
175178825Sdfr
176233294Sstas    for (i = 1; i < argc; ++i)
177233294Sstas	if (strcmp(argv[i], "-npro") == 0)
178233294Sstas	    break;
179233294Sstas    set_defaults();
180233294Sstas    if (i >= argc)
181233294Sstas	set_profile();
182233294Sstas
183233294Sstas    for (i = 1; i < argc; ++i) {
184233294Sstas
185233294Sstas	/*
186233294Sstas	 * look thru args (if any) for changes to defaults
187233294Sstas	 */
188233294Sstas	if (argv[i][0] != '-') {/* no flag on parameter */
189233294Sstas	    if (input == 0) {	/* we must have the input file */
190233294Sstas		in_name = argv[i];	/* remember name of input file */
191233294Sstas		input = fopen(in_name, "r");
192233294Sstas		if (input == 0)		/* check for open error */
193233294Sstas			err(1, "%s", in_name);
194233294Sstas		continue;
195233294Sstas	    }
196233294Sstas	    else if (output == 0) {	/* we have the output file */
197233294Sstas		out_name = argv[i];	/* remember name of output file */
198233294Sstas		if (strcmp(in_name, out_name) == 0) {	/* attempt to overwrite
199233294Sstas							 * the file */
200233294Sstas		    errx(1, "input and output files must be different");
201233294Sstas		}
202233294Sstas		output = fopen(out_name, "w");
203233294Sstas		if (output == 0)	/* check for create error */
204142403Snectar			err(1, "%s", out_name);
205233294Sstas		continue;
206142403Snectar	    }
207142403Snectar	    errx(1, "unknown parameter: %s", argv[i]);
208142403Snectar	}
209142403Snectar	else
210127808Snectar	    set_option(argv[i]);
21155682Smarkm    }				/* end of for */
21272445Sassar    if (input == 0)
213127808Snectar	input = stdin;
214233294Sstas    if (output == 0) {
215233294Sstas	if (troff || input == stdin)
216127808Snectar	    output = stdout;
217127808Snectar	else {
218127808Snectar	    out_name = in_name;
21955682Smarkm	    bakcopy();
22055682Smarkm	}
221233294Sstas    }
222233294Sstas    if (ps.com_ind <= 1)
22355682Smarkm	ps.com_ind = 2;		/* dont put normal comments before column 2 */
22455682Smarkm    if (troff) {
22555682Smarkm	if (bodyf.font[0] == 0)
226233294Sstas	    parsefont(&bodyf, "R");
227127808Snectar	if (scomf.font[0] == 0)
22890926Snectar	    parsefont(&scomf, "I");
22972445Sassar	if (blkcomf.font[0] == 0)
230127808Snectar	    blkcomf = scomf, blkcomf.size += 2;
231127808Snectar	if (boxcomf.font[0] == 0)
232233294Sstas	    boxcomf = blkcomf;
23355682Smarkm	if (stringf.font[0] == 0)
234127808Snectar	    parsefont(&stringf, "L");
235233294Sstas	if (keywordf.font[0] == 0)
23690926Snectar	    parsefont(&keywordf, "B");
237178825Sdfr	writefdef(&bodyf, 'B');
238178825Sdfr	writefdef(&scomf, 'C');
23972445Sassar	writefdef(&blkcomf, 'L');
240233294Sstas	writefdef(&boxcomf, 'X');
241233294Sstas	writefdef(&stringf, 'S');
242233294Sstas	writefdef(&keywordf, 'K');
243127808Snectar    }
244127808Snectar    if (block_comment_max_col <= 0)
245127808Snectar	block_comment_max_col = max_col;
246127808Snectar    if (ps.decl_com_ind <= 0)	/* if not specified by user, set this */
247127808Snectar	ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
248233294Sstas    if (continuation_indent == 0)
249178825Sdfr	continuation_indent = ps.ind_size;
25055682Smarkm    fill_buffer();		/* get first batch of stuff into input buffer */
25172445Sassar
252178825Sdfr    parse(semicolon);
253127808Snectar    {
254127808Snectar	char *p = buf_ptr;
255233294Sstas	int col = 1;
256233294Sstas
257127808Snectar	while (1) {
258127808Snectar	    if (*p == ' ')
259233294Sstas		col++;
260178825Sdfr	    else if (*p == '\t')
261127808Snectar		col = ((col - 1) & ~7) + 9;
262127808Snectar	    else
263127808Snectar		break;
26490926Snectar	    p++;
265233294Sstas	}
266127808Snectar	if (col > ps.ind_size)
267178825Sdfr	    ps.ind_level = ps.i_l_follow = col / ps.ind_size;
26855682Smarkm    }
269102644Snectar    if (troff) {
270102644Snectar	const char *p = in_name,
271178825Sdfr	           *beg = in_name;
272127808Snectar
273127808Snectar	while (*p)
27455682Smarkm	    if (*p++ == '/')
27555682Smarkm		beg = p;
27690926Snectar	fprintf(output, ".Fn \"%s\"\n", beg);
277127808Snectar    }
278127808Snectar    /*
279127808Snectar     * START OF MAIN LOOP
280127808Snectar     */
281127808Snectar
28290926Snectar    while (1) {			/* this is the main loop.  it will go until we
28390926Snectar				 * reach eof */
28490926Snectar	int         is_procname;
285127808Snectar
286127808Snectar	type_code = lexi();	/* lexi reads one token.  The actual
287127808Snectar				 * characters read are stored in "token". lexi
288127808Snectar				 * returns a code indicating the type of token */
289233294Sstas	is_procname = ps.procname[0];
290127808Snectar
291127808Snectar	/*
292233294Sstas	 * The following code moves everything following an if (), while (),
293178825Sdfr	 * else, etc. up to the start of the following stmt to a buffer. This
294127808Snectar	 * allows proper handling of both kinds of brace placement.
295127808Snectar	 */
296127808Snectar
297127808Snectar	flushed_nl = false;
298127808Snectar	while (ps.search_brace) {	/* if we scanned an if(), while(),
299127808Snectar					 * etc., we might need to copy stuff
300127808Snectar					 * into a buffer we must loop, copying
301127808Snectar					 * stuff into save_com, until we find
302178825Sdfr					 * the start of the stmt which follows
303178825Sdfr					 * the if, or whatever */
304178825Sdfr	    switch (type_code) {
305178825Sdfr	    case newline:
306127808Snectar		++line_no;
307127808Snectar		flushed_nl = true;
30855682Smarkm	    case form_feed:
309127808Snectar		break;		/* form feeds and newlines found here will be
310233294Sstas				 * ignored */
311233294Sstas
312127808Snectar	    case lbrace:	/* this is a brace that starts the compound
313127808Snectar				 * stmt */
314127808Snectar		if (sc_end == 0) {	/* ignore buffering if a comment wasnt
315127808Snectar					 * stored up */
316127808Snectar		    ps.search_brace = false;
31755682Smarkm		    goto check_type;
318127808Snectar		}
319127808Snectar		if (btype_2) {
320178825Sdfr		    save_com[0] = '{';	/* we either want to put the brace
321127808Snectar					 * right after the if */
322127808Snectar		    goto sw_buffer;	/* go to common code to get out of
32355682Smarkm					 * this loop */
32455682Smarkm		}
325127808Snectar	    case comment:	/* we have a comment, so we must copy it into
326127808Snectar				 * the buffer */
327233294Sstas		if (!flushed_nl || sc_end != 0) {
328127808Snectar		    if (sc_end == 0) {	/* if this is the first comment, we
329127808Snectar					 * must set up the buffer */
330233294Sstas			save_com[0] = save_com[1] = ' ';
33155682Smarkm			sc_end = &(save_com[2]);
33255682Smarkm		    }
333120945Snectar		    else {
334127808Snectar			*sc_end++ = '\n';	/* add newline between
335233294Sstas						 * comments */
336178825Sdfr			*sc_end++ = ' ';
337233294Sstas			--line_no;
338233294Sstas		    }
339233294Sstas		    *sc_end++ = '/';	/* copy in start of comment */
34055682Smarkm		    *sc_end++ = '*';
341233294Sstas
342127808Snectar		    for (;;) {	/* loop until we get to the end of the comment */
343233294Sstas			*sc_end = *buf_ptr++;
344233294Sstas			if (buf_ptr >= buf_end)
34555682Smarkm			    fill_buffer();
346127808Snectar
347127808Snectar			if (*sc_end++ == '*' && *buf_ptr == '/')
348127808Snectar			    break;	/* we are at end of comment */
349127808Snectar
350233294Sstas			if (sc_end >= &(save_com[sc_size])) {	/* check for temp buffer
351127808Snectar								 * overflow */
352127808Snectar			    diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
353233294Sstas			    fflush(output);
354233294Sstas			    exit(1);
355233294Sstas			}
356233294Sstas		    }
35755682Smarkm		    *sc_end++ = '/';	/* add ending slash */
358233294Sstas		    if (++buf_ptr >= buf_end)	/* get past / in buffer */
359127808Snectar			fill_buffer();
360127808Snectar		    break;
361233294Sstas		}
362233294Sstas	    default:		/* it is the start of a normal statment */
363102644Snectar		if (flushed_nl)	/* if we flushed a newline, make sure it is
36455682Smarkm				 * put back */
365178825Sdfr		    force_nl = true;
36655682Smarkm		if ((type_code == sp_paren && *token == 'i'
36755682Smarkm			&& last_else && ps.else_if)
36855682Smarkm			|| (type_code == sp_nparen && *token == 'e'
369178825Sdfr			&& e_code != s_code && e_code[-1] == '}'))
37090926Snectar		    force_nl = false;
37190926Snectar
37290926Snectar		if (sc_end == 0) {	/* ignore buffering if comment wasnt
37390926Snectar					 * saved up */
37455682Smarkm		    ps.search_brace = false;
375178825Sdfr		    goto check_type;
376178825Sdfr		}
377178825Sdfr		if (force_nl) {	/* if we should insert a nl here, put it into
378178825Sdfr				 * the buffer */
379178825Sdfr		    force_nl = false;
380233294Sstas		    --line_no;	/* this will be re-increased when the nl is
381127808Snectar				 * read from the buffer */
382233294Sstas		    *sc_end++ = '\n';
383233294Sstas		    *sc_end++ = ' ';
384127808Snectar		    if (verbose && !flushed_nl)	/* print error msg if the line
385233294Sstas						 * was not already broken */
386178825Sdfr			diag2(0, "Line broken");
387178825Sdfr		    flushed_nl = false;
388127808Snectar		}
389127808Snectar		for (t_ptr = token; *t_ptr; ++t_ptr)
390127808Snectar		    *sc_end++ = *t_ptr;	/* copy token into temp buffer */
391127808Snectar		ps.procname[0] = 0;
392127808Snectar
393127808Snectar	sw_buffer:
394178825Sdfr		ps.search_brace = false;	/* stop looking for start of
395127808Snectar						 * stmt */
396178825Sdfr		bp_save = buf_ptr;	/* save current input buffer */
397178825Sdfr		be_save = buf_end;
398102644Snectar		buf_ptr = save_com;	/* fix so that subsequent calls to
399102644Snectar					 * lexi will take tokens out of
400102644Snectar					 * save_com */
401178825Sdfr		*sc_end++ = ' ';/* add trailing blank, just in case */
402127808Snectar		buf_end = sc_end;
403127808Snectar		sc_end = 0;
404127808Snectar		break;
405127808Snectar	    }			/* end of switch */
406127808Snectar	    if (type_code != 0)	/* we must make this check, just in case there
407127808Snectar				 * was an unexpected EOF */
408178825Sdfr		type_code = lexi();	/* read another token */
409127808Snectar	    /* if (ps.search_brace) ps.procname[0] = 0; */
410127808Snectar	    if ((is_procname = ps.procname[0]) && flushed_nl
41172445Sassar		    && !procnames_start_line && ps.in_decl
412127808Snectar		    && type_code == ident)
413127808Snectar		flushed_nl = 0;
414178825Sdfr	}			/* end of while (search_brace) */
415127808Snectar	last_else = 0;
416127808Snectarcheck_type:
417142403Snectar	if (type_code == 0) {	/* we got eof */
418127808Snectar	    if (s_lab != e_lab || s_code != e_code
419178825Sdfr		    || s_com != e_com)	/* must dump end of line */
420127808Snectar		dump_line();
421127808Snectar	    if (ps.tos > 1)	/* check for balanced braces */
422178825Sdfr		diag2(1, "Stuff missing from end of file.");
423127808Snectar
424127808Snectar	    if (verbose) {
425178825Sdfr		printf("There were %d output lines and %d comments\n",
426233294Sstas		       ps.out_lines, ps.out_coms);
427127808Snectar		printf("(Lines with comments)/(Lines with code): %6.3f\n",
428127808Snectar		       (1.0 * ps.com_lines) / code_lines);
429233294Sstas	    }
430178825Sdfr	    fflush(output);
431178825Sdfr	    exit(found_err);
432233294Sstas	}
433233294Sstas	if (
434233294Sstas		(type_code != comment) &&
435233294Sstas		(type_code != newline) &&
436233294Sstas		(type_code != preesc) &&
437102644Snectar		(type_code != form_feed)) {
43890926Snectar	    if (force_nl &&
43972445Sassar		    (type_code != semicolon) &&
44055682Smarkm		    (type_code != lbrace || !btype_2)) {
441233294Sstas		/* we should force a broken line here */
44255682Smarkm		if (verbose && !flushed_nl)
44355682Smarkm		    diag2(0, "Line broken");
44455682Smarkm		flushed_nl = false;
44555682Smarkm		dump_line();
44655682Smarkm		ps.want_blank = false;	/* dont insert blank at line start */
44755682Smarkm		force_nl = false;
448233294Sstas	    }
44955682Smarkm	    ps.in_stmt = true;	/* turn on flag which causes an extra level of
450120945Snectar				 * indentation. this is turned off by a ; or
45190926Snectar				 * '}' */
45272445Sassar	    if (s_com != e_com) {	/* the turkey has embedded a comment
45355682Smarkm					 * in a line. fix it */
45490926Snectar		*e_code++ = ' ';
455233294Sstas		for (t_ptr = s_com; *t_ptr; ++t_ptr) {
45690926Snectar		    CHECK_SIZE_CODE;
457178825Sdfr		    *e_code++ = *t_ptr;
458178825Sdfr		}
459178825Sdfr		*e_code++ = ' ';
460178825Sdfr		*e_code = '\0';	/* null terminate code sect */
461233294Sstas		ps.want_blank = false;
462233294Sstas		e_com = s_com;
463178825Sdfr	    }
464233294Sstas	}
465178825Sdfr	else if (type_code != comment)	/* preserve force_nl thru a comment */
46690926Snectar	    force_nl = false;	/* cancel forced newline after newline, form
46772445Sassar				 * feed, etc */
46872445Sassar
469178825Sdfr
470178825Sdfr
47172445Sassar	/*-----------------------------------------------------*\
472233294Sstas	|	   do switch on type of token scanned		|
47372445Sassar	\*-----------------------------------------------------*/
47455682Smarkm	CHECK_SIZE_CODE;
47590926Snectar	switch (type_code) {	/* now, decide what to do with the token */
476178825Sdfr
477233294Sstas	case form_feed:	/* found a form feed in line */
478233294Sstas	    ps.use_ff = true;	/* a form feed is treated much like a newline */
479233294Sstas	    dump_line();
480233294Sstas	    ps.want_blank = false;
481233294Sstas	    break;
482233294Sstas
483233294Sstas	case newline:
484178825Sdfr	    if (ps.last_token != comma || ps.p_l_follow > 0
485178825Sdfr		    || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
486178825Sdfr		dump_line();
487178825Sdfr		ps.want_blank = false;
488178825Sdfr	    }
489178825Sdfr	    ++line_no;		/* keep track of input line number */
490178825Sdfr	    break;
491178825Sdfr
492178825Sdfr	case lparen:		/* got a '(' or '[' */
493178825Sdfr	    ++ps.p_l_follow;	/* count parens to make Healy happy */
494233294Sstas	    if (ps.want_blank && *token != '[' &&
495233294Sstas		    (ps.last_token != ident || proc_calls_space
496233294Sstas	      || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
497233294Sstas		*e_code++ = ' ';
49872445Sassar	    if (ps.in_decl && !ps.block_init)
49972445Sassar		if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) {
500178825Sdfr		    ps.dumped_decl_indent = 1;
50172445Sassar		    sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
50272445Sassar		    e_code += strlen(e_code);
50355682Smarkm		}
504233294Sstas		else {
505233294Sstas		    while ((e_code - s_code) < dec_ind) {
506233294Sstas			CHECK_SIZE_CODE;
507233294Sstas			*e_code++ = ' ';
508233294Sstas		    }
509233294Sstas		    *e_code++ = token[0];
510233294Sstas		}
511233294Sstas	    else
512233294Sstas		*e_code++ = token[0];
51390926Snectar	    ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
51455682Smarkm	    if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
51555682Smarkm		    && ps.paren_indents[0] < 2 * ps.ind_size)
516233294Sstas		ps.paren_indents[0] = 2 * ps.ind_size;
517142403Snectar	    ps.want_blank = false;
518142403Snectar	    if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
519142403Snectar		/*
520142403Snectar		 * this is a kluge to make sure that declarations will be
521233294Sstas		 * aligned right if proc decl has an explicit type on it, i.e.
522233294Sstas		 * "int a(x) {..."
523142403Snectar		 */
524142403Snectar		parse(semicolon);	/* I said this was a kluge... */
525142403Snectar		ps.in_or_st = false;	/* turn off flag for structure decl or
526233294Sstas					 * initialization */
527233294Sstas	    }
528233294Sstas	    if (ps.sizeof_keyword)
529142403Snectar		ps.sizeof_mask |= 1 << ps.p_l_follow;
530142403Snectar	    break;
531142403Snectar
532142403Snectar	case rparen:		/* got a ')' or ']' */
533142403Snectar	    rparen_count--;
534142403Snectar	    if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
535142403Snectar		ps.last_u_d = true;
536142403Snectar		ps.cast_mask &= (1 << ps.p_l_follow) - 1;
537142403Snectar		ps.want_blank = false;
538142403Snectar	    } else
539142403Snectar		ps.want_blank = true;
540142403Snectar	    ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
541142403Snectar	    if (--ps.p_l_follow < 0) {
542142403Snectar		ps.p_l_follow = 0;
543142403Snectar		diag3(0, "Extra %c", *token);
544142403Snectar	    }
545142403Snectar	    if (e_code == s_code)	/* if the paren starts the line */
546233294Sstas		ps.paren_level = ps.p_l_follow;	/* then indent it */
54755682Smarkm
54855682Smarkm	    *e_code++ = token[0];
549178825Sdfr
550233294Sstas	    if (sp_sw && (ps.p_l_follow == 0)) {	/* check for end of if
551233294Sstas							 * (...), or some such */
552233294Sstas		sp_sw = false;
553233294Sstas		force_nl = true;/* must force newline after if */
554233294Sstas		ps.last_u_d = true;	/* inform lexi that a following
555233294Sstas					 * operator is unary */
556233294Sstas		ps.in_stmt = false;	/* dont use stmt continuation
557233294Sstas					 * indentation */
558233294Sstas
559233294Sstas		parse(hd_type);	/* let parser worry about if, or whatever */
560233294Sstas	    }
561233294Sstas	    ps.search_brace = btype_2;	/* this should insure that constructs
562233294Sstas					 * such as main(){...} and int[]{...}
563233294Sstas					 * have their braces put in the right
564233294Sstas					 * place */
565233294Sstas	    break;
566233294Sstas
567233294Sstas	case unary_op:		/* this could be any unary operation */
568233294Sstas	    if (ps.want_blank)
569233294Sstas		*e_code++ = ' ';
570233294Sstas
57155682Smarkm	    if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) {
57255682Smarkm		sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
57355682Smarkm		ps.dumped_decl_indent = 1;
574233294Sstas		e_code += strlen(e_code);
575233294Sstas	    }
576233294Sstas	    else {
577233294Sstas		const char *res = token;
578233294Sstas
579233294Sstas		if (ps.in_decl && !ps.block_init) {	/* if this is a unary op
580233294Sstas							 * in a declaration, we
58155682Smarkm							 * should indent this
58290926Snectar							 * token */
583233294Sstas		    for (i = 0; token[i]; ++i);	/* find length of token */
584233294Sstas		    while ((e_code - s_code) < (dec_ind - i)) {
585233294Sstas			CHECK_SIZE_CODE;
586233294Sstas			*e_code++ = ' ';	/* pad it */
587233294Sstas		    }
588233294Sstas		}
589233294Sstas		if (troff && token[0] == '-' && token[1] == '>')
590178825Sdfr		    res = "\\(->";
591178825Sdfr		for (t_ptr = res; *t_ptr; ++t_ptr) {
592178825Sdfr		    CHECK_SIZE_CODE;
593233294Sstas		    *e_code++ = *t_ptr;
594233294Sstas		}
595233294Sstas	    }
596233294Sstas	    ps.want_blank = false;
597233294Sstas	    break;
598233294Sstas
599233294Sstas	case binary_op:	/* any binary operation */
600233294Sstas	    if (ps.want_blank)
601233294Sstas		*e_code++ = ' ';
602233294Sstas	    {
603233294Sstas		const char *res = token;
604233294Sstas
605233294Sstas		if (troff)
606233294Sstas		    switch (token[0]) {
607233294Sstas		    case '<':
608233294Sstas			if (token[1] == '=')
609233294Sstas			    res = "\\(<=";
610233294Sstas			break;
611233294Sstas		    case '>':
612233294Sstas			if (token[1] == '=')
613233294Sstas			    res = "\\(>=";
61455682Smarkm			break;
615178825Sdfr		    case '!':
616178825Sdfr			if (token[1] == '=')
617233294Sstas			    res = "\\(!=";
618233294Sstas			break;
619233294Sstas		    case '|':
620233294Sstas			if (token[1] == '|')
621233294Sstas			    res = "\\(br\\(br";
622233294Sstas			else if (token[1] == 0)
623233294Sstas			    res = "\\(br";
624178825Sdfr			break;
625178825Sdfr		    }
626233294Sstas		for (t_ptr = res; *t_ptr; ++t_ptr) {
627233294Sstas		    CHECK_SIZE_CODE;
628233294Sstas		    *e_code++ = *t_ptr;	/* move the operator */
629233294Sstas		}
630233294Sstas	    }
631233294Sstas	    ps.want_blank = true;
632233294Sstas	    break;
633178825Sdfr
63455682Smarkm	case postop:		/* got a trailing ++ or -- */
635233294Sstas	    *e_code++ = token[0];
636233294Sstas	    *e_code++ = token[1];
637233294Sstas	    ps.want_blank = true;
638233294Sstas	    break;
639233294Sstas
640233294Sstas	case question:		/* got a ? */
641233294Sstas	    squest++;		/* this will be used when a later colon
64290926Snectar				 * appears so we can distinguish the
64372445Sassar				 * <c>?<n>:<n> construct */
644178825Sdfr	    if (ps.want_blank)
645233294Sstas		*e_code++ = ' ';
646233294Sstas	    *e_code++ = '?';
647233294Sstas	    ps.want_blank = true;
64890926Snectar	    break;
64972445Sassar
650178825Sdfr	case casestmt:		/* got word 'case' or 'default' */
65190926Snectar	    scase = true;	/* so we can process the later colon properly */
65255682Smarkm	    goto copy_id;
653178825Sdfr
654178825Sdfr	case colon:		/* got a ':' */
655178825Sdfr	    if (squest > 0) {	/* it is part of the <c>?<n>: <n> construct */
656178825Sdfr		--squest;
65790926Snectar		if (ps.want_blank)
65855682Smarkm		    *e_code++ = ' ';
659178825Sdfr		*e_code++ = ':';
660178825Sdfr		ps.want_blank = true;
661178825Sdfr		break;
662178825Sdfr	    }
66390926Snectar	    if (ps.in_decl) {
66472445Sassar		*e_code++ = ':';
665178825Sdfr		ps.want_blank = false;
66690926Snectar		break;
66755682Smarkm	    }
668178825Sdfr	    ps.in_stmt = false;	/* seeing a label does not imply we are in a
66990926Snectar				 * stmt */
67090926Snectar	    for (t_ptr = s_code; *t_ptr; ++t_ptr)
671142403Snectar		*e_lab++ = *t_ptr;	/* turn everything so far into a label */
67290926Snectar	    e_code = s_code;
67390926Snectar	    *e_lab++ = ':';
67490926Snectar	    *e_lab++ = ' ';
67590926Snectar	    *e_lab = '\0';
676233294Sstas
677233294Sstas	    force_nl = ps.pcase = scase;	/* ps.pcase will be used by
678233294Sstas						 * dump_line to decide how to
679233294Sstas						 * indent the label. force_nl
680233294Sstas						 * will force a case n: to be
681233294Sstas						 * on a line by itself */
682233294Sstas	    scase = false;
683233294Sstas	    ps.want_blank = false;
684233294Sstas	    break;
685233294Sstas
686233294Sstas	case semicolon:	/* got a ';' */
687233294Sstas	    ps.in_or_st = false;/* we are not in an initialization or
688233294Sstas				 * structure declaration */
689233294Sstas	    scase = false;	/* these will only need resetting in a error */
690233294Sstas	    squest = 0;
69172445Sassar	    if (ps.last_token == rparen && rparen_count == 0)
692233294Sstas		ps.in_parameter_declaration = 0;
693233294Sstas	    ps.cast_mask = 0;
694233294Sstas	    ps.sizeof_mask = 0;
695233294Sstas	    ps.block_init = 0;
696233294Sstas	    ps.block_init_level = 0;
69790926Snectar	    ps.just_saw_decl--;
69872445Sassar
699233294Sstas	    if (ps.in_decl && s_code == e_code && !ps.block_init)
700233294Sstas		while ((e_code - s_code) < (dec_ind - 1)) {
701233294Sstas		    CHECK_SIZE_CODE;
702233294Sstas		    *e_code++ = ' ';
703233294Sstas		}
70490926Snectar
70572445Sassar	    ps.in_decl = (ps.dec_nest > 0);	/* if we were in a first level
706233294Sstas						 * structure declaration, we
707233294Sstas						 * arent any more */
708233294Sstas
709233294Sstas	    if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
710233294Sstas
711102644Snectar		/*
712102644Snectar		 * This should be true iff there were unbalanced parens in the
713102644Snectar		 * stmt.  It is a bit complicated, because the semicolon might
714102644Snectar		 * be in a for stmt
715102644Snectar		 */
716102644Snectar		diag2(1, "Unbalanced parens");
717233294Sstas		ps.p_l_follow = 0;
71890926Snectar		if (sp_sw) {	/* this is a check for a if, while, etc. with
719178825Sdfr				 * unbalanced parens */
720233294Sstas		    sp_sw = false;
721233294Sstas		    parse(hd_type);	/* dont lose the if, or whatever */
722233294Sstas		}
723233294Sstas	    }
724233294Sstas	    *e_code++ = ';';
725233294Sstas	    ps.want_blank = true;
726233294Sstas	    ps.in_stmt = (ps.p_l_follow > 0);	/* we are no longer in the
727233294Sstas						 * middle of a stmt */
728233294Sstas
729233294Sstas	    if (!sp_sw) {	/* if not if for (;;) */
730233294Sstas		parse(semicolon);	/* let parser know about end of stmt */
731233294Sstas		force_nl = true;/* force newline after a end of stmt */
732233294Sstas	    }
733233294Sstas	    break;
734233294Sstas
735233294Sstas	case lbrace:		/* got a '{' */
73655682Smarkm	    ps.in_stmt = false;	/* dont indent the {} */
737233294Sstas	    if (!ps.block_init)
738233294Sstas		force_nl = true;/* force other stuff on same line as '{' onto
739233294Sstas				 * new line */
740233294Sstas	    else if (ps.block_init_level <= 0)
741233294Sstas		ps.block_init_level = 1;
742233294Sstas	    else
743233294Sstas		ps.block_init_level++;
74455682Smarkm
74590926Snectar	    if (s_code != e_code && !ps.block_init) {
746233294Sstas		if (!btype_2) {
747233294Sstas		    dump_line();
748233294Sstas		    ps.want_blank = false;
749233294Sstas		}
750233294Sstas		else if (ps.in_parameter_declaration && !ps.in_or_st) {
751233294Sstas		    ps.i_l_follow = 0;
752233294Sstas		    dump_line();
753233294Sstas		    ps.want_blank = false;
754233294Sstas		}
755233294Sstas	    }
756233294Sstas	    if (ps.in_parameter_declaration)
757233294Sstas		prefix_blankline_requested = 0;
758233294Sstas
759233294Sstas	    if (ps.p_l_follow > 0) {	/* check for preceding unbalanced
760233294Sstas					 * parens */
761233294Sstas		diag2(1, "Unbalanced parens");
762233294Sstas		ps.p_l_follow = 0;
763233294Sstas		if (sp_sw) {	/* check for unclosed if, for, etc. */
764233294Sstas		    sp_sw = false;
765233294Sstas		    parse(hd_type);
766233294Sstas		    ps.ind_level = ps.i_l_follow;
767233294Sstas		}
768233294Sstas	    }
769233294Sstas	    if (s_code == e_code)
770233294Sstas		ps.ind_stmt = false;	/* dont put extra indentation on line
771233294Sstas					 * with '{' */
772233294Sstas	    if (ps.in_decl && ps.in_or_st) {	/* this is either a structure
773233294Sstas						 * declaration or an init */
77455682Smarkm		di_stack[ps.dec_nest++] = dec_ind;
775233294Sstas		/* ?		dec_ind = 0; */
776233294Sstas	    }
777233294Sstas	    else {
778233294Sstas		ps.decl_on_line = false;	/* we cant be in the middle of
779233294Sstas						 * a declaration, so dont do
780233294Sstas						 * special indentation of
78155682Smarkm						 * comments */
782233294Sstas		if (blanklines_after_declarations_at_proctop
783233294Sstas			&& ps.in_parameter_declaration)
784233294Sstas		    postfix_blankline_requested = 1;
785233294Sstas		ps.in_parameter_declaration = 0;
786233294Sstas	    }
787233294Sstas	    dec_ind = 0;
788233294Sstas	    parse(lbrace);	/* let parser know about this */
789233294Sstas	    if (ps.want_blank)	/* put a blank before '{' if '{' is not at
790233294Sstas				 * start of line */
791233294Sstas		*e_code++ = ' ';
792233294Sstas	    ps.want_blank = false;
793233294Sstas	    *e_code++ = '{';
79472445Sassar	    ps.just_saw_decl = 0;
795102644Snectar	    break;
79672445Sassar
79772445Sassar	case rbrace:		/* got a '}' */
79872445Sassar	    if (ps.p_stack[ps.tos] == decl && !ps.block_init)	/* semicolons can be
799233294Sstas								 * omitted in
800233294Sstas								 * declarations */
801102644Snectar		parse(semicolon);
802142403Snectar	    if (ps.p_l_follow) {/* check for unclosed if, for, else. */
80355682Smarkm		diag2(1, "Unbalanced parens");
80472445Sassar		ps.p_l_follow = 0;
80572445Sassar		sp_sw = false;
806233294Sstas	    }
80755682Smarkm	    ps.just_saw_decl = 0;
808102644Snectar	    ps.block_init_level--;
80972445Sassar	    if (s_code != e_code && !ps.block_init) {	/* '}' must be first on
81072445Sassar							 * line */
81172445Sassar		if (verbose)
812233294Sstas		    diag2(0, "Line broken");
813233294Sstas		dump_line();
814233294Sstas	    }
815233294Sstas	    *e_code++ = '}';
816178825Sdfr	    ps.want_blank = true;
817233294Sstas	    ps.in_stmt = ps.ind_stmt = false;
818233294Sstas	    if (ps.dec_nest > 0) {	/* we are in multi-level structure
819233294Sstas					 * declaration */
820233294Sstas		dec_ind = di_stack[--ps.dec_nest];
821233294Sstas		if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
822233294Sstas		    ps.just_saw_decl = 2;
823233294Sstas		ps.in_decl = true;
824178825Sdfr	    }
825127808Snectar	    prefix_blankline_requested = 0;
826127808Snectar	    parse(rbrace);	/* let parser know about this */
827127808Snectar	    ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
828127808Snectar		&& ps.il[ps.tos] >= ps.ind_level;
829127808Snectar	    if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
830127808Snectar		postfix_blankline_requested = 1;
831127808Snectar	    break;
832233294Sstas
833233294Sstas	case swstmt:		/* got keyword "switch" */
834233294Sstas	    sp_sw = true;
835127808Snectar	    hd_type = swstmt;	/* keep this for when we have seen the
836233294Sstas				 * expression */
837127808Snectar	    goto copy_id;	/* go move the token into buffer */
83878527Sassar
839102644Snectar	case sp_paren:		/* token is if, while, for */
840233294Sstas	    sp_sw = true;	/* the interesting stuff is done after the
841233294Sstas				 * expression is scanned */
84278527Sassar	    hd_type = (*token == 'i' ? ifstmt :
84355682Smarkm		       (*token == 'w' ? whilestmt : forstmt));
844127808Snectar
84555682Smarkm	    /*
84655682Smarkm	     * remember the type of header for later use by parser
847233294Sstas	     */
848233294Sstas	    goto copy_id;	/* copy the token into line */
849233294Sstas
850233294Sstas	case sp_nparen:	/* got else, do */
851233294Sstas	    ps.in_stmt = false;
852233294Sstas	    if (*token == 'e') {
853233294Sstas		if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
854233294Sstas		    if (verbose)
855233294Sstas			diag2(0, "Line broken");
856233294Sstas		    dump_line();/* make sure this starts a line */
857233294Sstas		    ps.want_blank = false;
858233294Sstas		}
859233294Sstas		force_nl = true;/* also, following stuff must go onto new line */
860178825Sdfr		last_else = 1;
861178825Sdfr		parse(elselit);
862178825Sdfr	    }
863178825Sdfr	    else {
864178825Sdfr		if (e_code != s_code) {	/* make sure this starts a line */
865178825Sdfr		    if (verbose)
866178825Sdfr			diag2(0, "Line broken");
867178825Sdfr		    dump_line();
868178825Sdfr		    ps.want_blank = false;
869178825Sdfr		}
870178825Sdfr		force_nl = true;/* also, following stuff must go onto new line */
871178825Sdfr		last_else = 0;
872102644Snectar		parse(dolit);
87355682Smarkm	    }
874178825Sdfr	    goto copy_id;	/* move the token into line */
875233294Sstas
876233294Sstas	case decl:		/* we have a declaration type (int, register,
877233294Sstas				 * etc.) */
878102644Snectar	    parse(decl);	/* let parser worry about indentation */
879233294Sstas	    if (ps.last_token == rparen && ps.tos <= 1) {
880233294Sstas		ps.in_parameter_declaration = 1;
881102644Snectar		if (s_code != e_code) {
882233294Sstas		    dump_line();
88355682Smarkm		    ps.want_blank = 0;
884233294Sstas		}
885233294Sstas	    }
88672445Sassar	    if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
88755682Smarkm		ps.ind_level = ps.i_l_follow = 1;
88855682Smarkm		ps.ind_stmt = 0;
88990926Snectar	    }
890127808Snectar	    ps.in_or_st = true;	/* this might be a structure or initialization
89190926Snectar				 * declaration */
89255682Smarkm	    ps.in_decl = ps.decl_on_line = true;
89355682Smarkm	    if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
89455682Smarkm		ps.just_saw_decl = 2;
89590926Snectar	    prefix_blankline_requested = 0;
89690926Snectar	    for (i = 0; token[i++];);	/* get length of token */
897233294Sstas
898178825Sdfr	    /*
899142403Snectar	     * dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent
90090926Snectar	     * : i);
90155682Smarkm	     */
90255682Smarkm	    dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
90390926Snectar	    goto copy_id;
90455682Smarkm
90555682Smarkm	case ident:		/* got an identifier or constant */
90655682Smarkm	    if (ps.in_decl) {	/* if we are in a declaration, we must indent
90790926Snectar				 * identifier */
90890926Snectar		if (ps.want_blank)
90955682Smarkm		    *e_code++ = ' ';
91090926Snectar		ps.want_blank = false;
911127808Snectar		if (is_procname == 0 || !procnames_start_line) {
91290926Snectar		    if (!ps.block_init) {
91390926Snectar			if (troff && !ps.dumped_decl_indent) {
91455682Smarkm			    sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7);
91555682Smarkm			    ps.dumped_decl_indent = 1;
91655682Smarkm			    e_code += strlen(e_code);
917178825Sdfr			} else {
91855682Smarkm			    while ((e_code - s_code) < dec_ind) {
91955682Smarkm				CHECK_SIZE_CODE;
920178825Sdfr				*e_code++ = ' ';
921233294Sstas			    }
92255682Smarkm			}
92355682Smarkm		    }
92490926Snectar		} else {
92590926Snectar		    if (dec_ind && s_code != e_code)
92690926Snectar			dump_line();
92755682Smarkm		    dec_ind = 0;
928178825Sdfr		    ps.want_blank = false;
929178825Sdfr		}
93055682Smarkm	    }
93190926Snectar	    else if (sp_sw && ps.p_l_follow == 0) {
932233294Sstas		sp_sw = false;
933127808Snectar		force_nl = true;
93490926Snectar		ps.last_u_d = true;
935178825Sdfr		ps.in_stmt = false;
93655682Smarkm		parse(hd_type);
93790926Snectar	    }
93855682Smarkm    copy_id:
93990926Snectar	    if (ps.want_blank)
94055682Smarkm		*e_code++ = ' ';
941142403Snectar	    if (troff && ps.its_a_keyword) {
942142403Snectar		e_code = chfont(&bodyf, &keywordf, e_code);
943233294Sstas		for (t_ptr = token; *t_ptr; ++t_ptr) {
944233294Sstas		    CHECK_SIZE_CODE;
94590926Snectar		    *e_code++ = keywordf.allcaps && islower(*t_ptr)
94655682Smarkm			? toupper(*t_ptr) : *t_ptr;
94790926Snectar		}
94890926Snectar		e_code = chfont(&keywordf, &bodyf, e_code);
949120945Snectar	    }
950120945Snectar	    else
951120945Snectar		for (t_ptr = token; *t_ptr; ++t_ptr) {
952178825Sdfr		    CHECK_SIZE_CODE;
953178825Sdfr		    *e_code++ = *t_ptr;
954233294Sstas		}
955233294Sstas	    ps.want_blank = true;
956178825Sdfr	    break;
95790926Snectar
95890926Snectar	case period:		/* treat a period kind of like a binary
959178825Sdfr				 * operation */
960178825Sdfr	    *e_code++ = '.';	/* move the period into line */
961233294Sstas	    ps.want_blank = false;	/* dont put a blank after a period */
962233294Sstas	    break;
96390926Snectar
96490926Snectar	case comma:
965233294Sstas	    ps.want_blank = (s_code != e_code);	/* only put blank after comma
96690926Snectar						 * if comma does not start the
967233294Sstas						 * line */
968233294Sstas	    if (ps.in_decl && is_procname == 0 && !ps.block_init)
969178825Sdfr		while ((e_code - s_code) < (dec_ind - 1)) {
970178825Sdfr		    CHECK_SIZE_CODE;
971233294Sstas		    *e_code++ = ' ';
972233294Sstas		}
973178825Sdfr
974178825Sdfr	    *e_code++ = ',';
975233294Sstas	    if (ps.p_l_follow == 0) {
976233294Sstas		if (ps.block_init_level <= 0)
97790926Snectar		    ps.block_init = 0;
97890926Snectar		if (break_comma && (!ps.leave_comma || compute_code_target() + (e_code - s_code) > max_col - 8))
97955682Smarkm		    force_nl = true;
980233294Sstas	    }
981127808Snectar	    break;
98290926Snectar
98355682Smarkm	case preesc:		/* got the character '#' */
98490926Snectar	    if ((s_com != e_com) ||
98555682Smarkm		    (s_lab != e_lab) ||
98690926Snectar		    (s_code != e_code))
98790926Snectar		dump_line();
98890926Snectar	    *e_lab++ = '#';	/* move whole line to 'label' buffer */
989127808Snectar	    {
990127808Snectar		int         in_comment = 0;
991127808Snectar		int         com_start = 0;
992127808Snectar		char        quote = 0;
993127808Snectar		int         com_end = 0;
994127808Snectar
995127808Snectar		while (*buf_ptr == ' ' || *buf_ptr == '\t') {
996127808Snectar		    buf_ptr++;
997178825Sdfr		    if (buf_ptr >= buf_end)
998178825Sdfr			fill_buffer();
999178825Sdfr		}
1000178825Sdfr		while (*buf_ptr != '\n' || (in_comment && !had_eof)) {
1001233294Sstas		    CHECK_SIZE_LAB;
100290926Snectar		    *e_lab = *buf_ptr++;
1003233294Sstas		    if (buf_ptr >= buf_end)
1004233294Sstas			fill_buffer();
100590926Snectar		    switch (*e_lab++) {
1006127808Snectar		    case BACKSLASH:
1007178825Sdfr			if (troff)
1008178825Sdfr			    *e_lab++ = BACKSLASH;
1009178825Sdfr			if (!in_comment) {
1010178825Sdfr			    *e_lab++ = *buf_ptr++;
1011178825Sdfr			    if (buf_ptr >= buf_end)
1012178825Sdfr				fill_buffer();
1013178825Sdfr			}
1014178825Sdfr			break;
1015233294Sstas		    case '/':
1016233294Sstas			if (*buf_ptr == '*' && !in_comment && !quote) {
1017233294Sstas			    in_comment = 1;
1018233294Sstas			    *e_lab++ = *buf_ptr++;
1019233294Sstas			    com_start = e_lab - s_lab - 2;
1020233294Sstas			}
1021233294Sstas			break;
1022233294Sstas		    case '"':
102390926Snectar			if (quote == '"')
102490926Snectar			    quote = 0;
102555682Smarkm			break;
102655682Smarkm		    case '\'':
102755682Smarkm			if (quote == '\'')
102855682Smarkm			    quote = 0;
102955682Smarkm			break;
103072445Sassar		    case '*':
103172445Sassar			if (*buf_ptr == '/' && in_comment) {
103272445Sassar			    in_comment = 0;
103372445Sassar			    *e_lab++ = *buf_ptr++;
103455682Smarkm			    com_end = e_lab - s_lab;
103555682Smarkm			}
103655682Smarkm			break;
1037178825Sdfr		    }
1038178825Sdfr		}
103955682Smarkm
104055682Smarkm		while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
104155682Smarkm		    e_lab--;
104255682Smarkm		if (e_lab - s_lab == com_end && bp_save == 0) {	/* comment on
104355682Smarkm								 * preprocessor line */
104455682Smarkm		    if (sc_end == 0)	/* if this is the first comment, we
104572445Sassar					 * must set up the buffer */
104672445Sassar			sc_end = &(save_com[0]);
104755682Smarkm		    else {
1048178825Sdfr			*sc_end++ = '\n';	/* add newline between
1049178825Sdfr						 * comments */
1050178825Sdfr			*sc_end++ = ' ';
1051178825Sdfr			--line_no;
1052178825Sdfr		    }
1053178825Sdfr		    bcopy(s_lab + com_start, sc_end, com_end - com_start);
1054178825Sdfr		    sc_end += com_end - com_start;
1055178825Sdfr		    if (sc_end >= &save_com[sc_size])
1056178825Sdfr			abort();
1057178825Sdfr		    e_lab = s_lab + com_start;
1058178825Sdfr		    while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
105955682Smarkm			e_lab--;
106055682Smarkm		    bp_save = buf_ptr;	/* save current input buffer */
106155682Smarkm		    be_save = buf_end;
1062102644Snectar		    buf_ptr = save_com;	/* fix so that subsequent calls to
1063102644Snectar					 * lexi will take tokens out of
1064178825Sdfr					 * save_com */
1065178825Sdfr		    *sc_end++ = ' ';	/* add trailing blank, just in case */
1066102644Snectar		    buf_end = sc_end;
1067102644Snectar		    sc_end = 0;
1068102644Snectar		}
1069102644Snectar		*e_lab = '\0';	/* null terminate line */
1070102644Snectar		ps.pcase = false;
1071102644Snectar	    }
1072178825Sdfr
1073102644Snectar	    if (strncmp(s_lab, "#if", 3) == 0) {
1074102644Snectar		if (blanklines_around_conditional_compilation) {
1075102644Snectar		    int c;
1076102644Snectar		    prefix_blankline_requested++;
1077102644Snectar		    while ((c = getc(input)) == '\n');
1078102644Snectar		    ungetc(c, input);
1079102644Snectar		}
1080102644Snectar		if ((size_t)ifdef_level < sizeof(state_stack)/sizeof(state_stack[0])) {
1081102644Snectar		    match_state[ifdef_level].tos = -1;
1082102644Snectar		    state_stack[ifdef_level++] = ps;
1083102644Snectar		}
1084102644Snectar		else
1085102644Snectar		    diag2(1, "#if stack overflow");
1086102644Snectar	    }
1087102644Snectar	    else if (strncmp(s_lab, "#else", 5) == 0)
1088178825Sdfr		if (ifdef_level <= 0)
1089102644Snectar		    diag2(1, "Unmatched #else");
1090102644Snectar		else {
1091102644Snectar		    match_state[ifdef_level - 1] = ps;
1092102644Snectar		    ps = state_stack[ifdef_level - 1];
1093233294Sstas		}
1094233294Sstas	    else if (strncmp(s_lab, "#endif", 6) == 0) {
1095233294Sstas		if (ifdef_level <= 0)
109655682Smarkm		    diag2(1, "Unmatched #endif");
109755682Smarkm		else {
109855682Smarkm		    ifdef_level--;
109955682Smarkm
110055682Smarkm#ifdef undef
110155682Smarkm		    /*
110255682Smarkm		     * This match needs to be more intelligent before the
110355682Smarkm		     * message is useful
110455682Smarkm		     */
110555682Smarkm		    if (match_state[ifdef_level].tos >= 0
110655682Smarkm			  && bcmp(&ps, &match_state[ifdef_level], sizeof ps))
110755682Smarkm			diag2(0, "Syntactically inconsistant #ifdef alternatives.");
110855682Smarkm#endif
110955682Smarkm		}
111055682Smarkm		if (blanklines_around_conditional_compilation) {
111155682Smarkm		    postfix_blankline_requested++;
111255682Smarkm		    n_real_blanklines = 0;
111355682Smarkm		}
111455682Smarkm	    }
111555682Smarkm	    break;		/* subsequent processing of the newline
111655682Smarkm				 * character will cause the line to be printed */
111755682Smarkm
111855682Smarkm	case comment:		/* we have gotten a / followed by * this is a biggie */
111955682Smarkm	    if (flushed_nl) {	/* we should force a broken line here */
112055682Smarkm		flushed_nl = false;
112155682Smarkm		dump_line();
112255682Smarkm		ps.want_blank = false;	/* dont insert blank at line start */
112355682Smarkm		force_nl = false;
112455682Smarkm	    }
112555682Smarkm	    pr_comment();
112655682Smarkm	    break;
112755682Smarkm	}			/* end of big switch stmt */
112855682Smarkm
112955682Smarkm	*e_code = '\0';		/* make sure code section is null terminated */
113055682Smarkm	if (type_code != comment && type_code != newline && type_code != preesc)
113155682Smarkm	    ps.last_token = type_code;
113255682Smarkm    }				/* end of main while (1) loop */
113355682Smarkm}
113455682Smarkm
113555682Smarkm/*
113655682Smarkm * copy input file to backup file if in_name is /blah/blah/blah/file, then
113755682Smarkm * backup file will be ".Bfile" then make the backup file the input and
113855682Smarkm * original input file the output
113955682Smarkm */
114055682Smarkmstatic void
114155682Smarkmbakcopy(void)
114255682Smarkm{
114355682Smarkm    int         n,
114455682Smarkm                bakchn;
114555682Smarkm    char        buff[8 * 1024];
114655682Smarkm    const char *p;
114755682Smarkm
114855682Smarkm    /* construct file name .Bfile */
114955682Smarkm    for (p = in_name; *p; p++);	/* skip to end of string */
115055682Smarkm    while (p > in_name && *p != '/')	/* find last '/' */
115155682Smarkm	p--;
115255682Smarkm    if (*p == '/')
115355682Smarkm	p++;
115455682Smarkm    sprintf(bakfile, "%s.BAK", p);
115555682Smarkm
115655682Smarkm    /* copy in_name to backup file */
115755682Smarkm    bakchn = creat(bakfile, 0600);
115855682Smarkm    if (bakchn < 0)
115955682Smarkm	err(1, "%s", bakfile);
116072445Sassar    while ((n = read(fileno(input), buff, sizeof buff)) != 0)
1161178825Sdfr	if (write(bakchn, buff, n) != n)
116255682Smarkm	    err(1, "%s", bakfile);
1163178825Sdfr    if (n < 0)
1164178825Sdfr	err(1, "%s", in_name);
1165178825Sdfr    close(bakchn);
1166120945Snectar    fclose(input);
1167178825Sdfr
116855682Smarkm    /* re-open backup file as the input file */
116955682Smarkm    input = fopen(bakfile, "r");
117055682Smarkm    if (input == 0)
117155682Smarkm	err(1, "%s", bakfile);
117255682Smarkm    /* now the original input file will be the output */
117355682Smarkm    output = fopen(in_name, "w");
1174178825Sdfr    if (output == 0) {
1175178825Sdfr	unlink(bakfile);
1176178825Sdfr	err(1, "%s", in_name);
1177178825Sdfr    }
1178178825Sdfr}
1179178825Sdfr