Home | History | Annotate | Line # | Download | only in indent
indent.c revision 1.23
      1  1.23     sevan /*	$NetBSD: indent.c,v 1.23 2016/09/05 00:40:29 sevan Exp $	*/
      2   1.4       tls 
      3   1.1       cgd /*
      4   1.5       mrg  * Copyright (c) 1980, 1993
      5   1.5       mrg  *	The Regents of the University of California.  All rights reserved.
      6  1.15       agc  *
      7  1.15       agc  * Redistribution and use in source and binary forms, with or without
      8  1.15       agc  * modification, are permitted provided that the following conditions
      9  1.15       agc  * are met:
     10  1.15       agc  * 1. Redistributions of source code must retain the above copyright
     11  1.15       agc  *    notice, this list of conditions and the following disclaimer.
     12  1.15       agc  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.15       agc  *    notice, this list of conditions and the following disclaimer in the
     14  1.15       agc  *    documentation and/or other materials provided with the distribution.
     15  1.15       agc  * 3. Neither the name of the University nor the names of its contributors
     16  1.15       agc  *    may be used to endorse or promote products derived from this software
     17  1.15       agc  *    without specific prior written permission.
     18  1.15       agc  *
     19  1.15       agc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  1.15       agc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  1.15       agc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  1.15       agc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  1.15       agc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  1.15       agc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  1.15       agc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  1.15       agc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  1.15       agc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  1.15       agc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  1.15       agc  * SUCH DAMAGE.
     30  1.15       agc  */
     31  1.15       agc 
     32  1.15       agc /*
     33   1.5       mrg  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
     34   1.1       cgd  * Copyright (c) 1985 Sun Microsystems, Inc.
     35   1.1       cgd  * All rights reserved.
     36   1.1       cgd  *
     37   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     38   1.1       cgd  * modification, are permitted provided that the following conditions
     39   1.1       cgd  * are met:
     40   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     41   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     42   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     43   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     44   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     45   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     46   1.1       cgd  *    must display the following acknowledgement:
     47   1.1       cgd  *	This product includes software developed by the University of
     48   1.1       cgd  *	California, Berkeley and its contributors.
     49   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     50   1.1       cgd  *    may be used to endorse or promote products derived from this software
     51   1.1       cgd  *    without specific prior written permission.
     52   1.1       cgd  *
     53   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     54   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     55   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     56   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     57   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     58   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     59   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     60   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     61   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     62   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     63   1.1       cgd  * SUCH DAMAGE.
     64   1.1       cgd  */
     65   1.1       cgd 
     66   1.6     lukem #include <sys/cdefs.h>
     67   1.1       cgd #ifndef lint
     68  1.17     lukem __COPYRIGHT("@(#) Copyright (c) 1985 Sun Microsystems, Inc.\
     69  1.17     lukem   Copyright (c) 1976 Board of Trustees of the University of Illinois.\
     70  1.17     lukem   Copyright (c) 1980, 1993\
     71  1.17     lukem  The Regents of the University of California.  All rights reserved.");
     72   1.6     lukem #endif				/* not lint */
     73   1.1       cgd 
     74   1.1       cgd #ifndef lint
     75   1.5       mrg #if 0
     76   1.5       mrg static char sccsid[] = "@(#)indent.c	5.17 (Berkeley) 6/7/93";
     77   1.5       mrg #else
     78  1.23     sevan __RCSID("$NetBSD: indent.c,v 1.23 2016/09/05 00:40:29 sevan Exp $");
     79   1.5       mrg #endif
     80   1.6     lukem #endif				/* not lint */
     81   1.1       cgd 
     82   1.1       cgd #include <sys/param.h>
     83   1.6     lukem #include <ctype.h>
     84   1.6     lukem #include <err.h>
     85   1.6     lukem #include <errno.h>
     86   1.1       cgd #include <fcntl.h>
     87   1.1       cgd #include <stdio.h>
     88   1.1       cgd #include <stdlib.h>
     89   1.1       cgd #include <string.h>
     90   1.6     lukem #include <unistd.h>
     91  1.14  christos #include <locale.h>
     92   1.9  wsanchez #define EXTERN
     93   1.1       cgd #include "indent_globs.h"
     94   1.9  wsanchez #undef  EXTERN
     95   1.1       cgd #include "indent_codes.h"
     96   1.1       cgd 
     97  1.18     lukem const char *in_name = "Standard Input";		/* will always point to name of
     98  1.18     lukem 						 * input file */
     99  1.18     lukem const char *out_name = "Standard Output";	/* will always point to name of
    100  1.18     lukem 						 * output file */
    101   1.6     lukem char    bakfile[MAXPATHLEN] = "";
    102   1.1       cgd 
    103   1.6     lukem int
    104  1.13       wiz main(int argc, char **argv)
    105   1.1       cgd {
    106   1.1       cgd 
    107   1.6     lukem 	extern int found_err;	/* flag set in diag() on error */
    108   1.6     lukem 	int     dec_ind;	/* current indentation for declarations */
    109   1.6     lukem 	int     di_stack[20];	/* a stack of structure indentation levels */
    110   1.6     lukem 	int     flushed_nl;	/* used when buffering up comments to remember
    111   1.1       cgd 				 * that a newline was passed over */
    112   1.6     lukem 	int     force_nl;	/* when true, code must be broken */
    113   1.6     lukem 	int     hd_type;	/* used to store type of stmt for if (...),
    114   1.1       cgd 				 * for (...), etc */
    115   1.6     lukem 	int     i;		/* local loop counter */
    116   1.6     lukem 	int     scase;		/* set to true when we see a case, so we will
    117   1.1       cgd 				 * know what to do with the following colon */
    118   1.6     lukem 	int     sp_sw;		/* when true, we are in the expressin of
    119   1.1       cgd 				 * if(...), while(...), etc. */
    120   1.6     lukem 	int     squest;		/* when this is positive, we have seen a ?
    121   1.1       cgd 				 * without the matching : in a <c>?<s>:<s>
    122   1.1       cgd 				 * construct */
    123  1.18     lukem 	const char *t_ptr;	/* used for copying tokens */
    124  1.19       mrg 	int	tabs_to_var = 0; /* true if using tabs to indent to var name */
    125   1.6     lukem 	int     type_code;	/* the type of token, returned by lexi */
    126   1.1       cgd 
    127   1.6     lukem 	int     last_else = 0;	/* true iff last keyword was an else */
    128   1.1       cgd 
    129   1.1       cgd 
    130   1.6     lukem 	/*-----------------------------------------------*\
    131   1.6     lukem         |		      INITIALIZATION		      |
    132   1.6     lukem         \*-----------------------------------------------*/
    133   1.1       cgd 
    134  1.14  christos 	if (!setlocale(LC_ALL, ""))
    135  1.21  ginsbach 		warnx("can't set locale.");
    136   1.1       cgd 
    137   1.6     lukem 	hd_type = 0;
    138   1.6     lukem 	ps.p_stack[0] = stmt;	/* this is the parser's stack */
    139   1.6     lukem 	ps.last_nl = true;	/* this is true if the last thing scanned was
    140   1.1       cgd 				 * a newline */
    141   1.6     lukem 	ps.last_token = semicolon;
    142   1.6     lukem 	combuf = (char *) malloc(bufsize);
    143   1.6     lukem 	labbuf = (char *) malloc(bufsize);
    144   1.6     lukem 	codebuf = (char *) malloc(bufsize);
    145   1.6     lukem 	tokenbuf = (char *) malloc(bufsize);
    146   1.6     lukem 	l_com = combuf + bufsize - 5;
    147   1.6     lukem 	l_lab = labbuf + bufsize - 5;
    148   1.6     lukem 	l_code = codebuf + bufsize - 5;
    149   1.6     lukem 	l_token = tokenbuf + bufsize - 5;
    150   1.6     lukem 	combuf[0] = codebuf[0] = labbuf[0] = ' ';	/* set up code, label,
    151   1.6     lukem 							 * and comment buffers */
    152   1.6     lukem 	combuf[1] = codebuf[1] = labbuf[1] = '\0';
    153   1.6     lukem 	ps.else_if = 1;		/* Default else-if special processing to on */
    154   1.6     lukem 	s_lab = e_lab = labbuf + 1;
    155   1.6     lukem 	s_code = e_code = codebuf + 1;
    156   1.6     lukem 	s_com = e_com = combuf + 1;
    157   1.6     lukem 	s_token = e_token = tokenbuf + 1;
    158   1.6     lukem 
    159   1.6     lukem 	in_buffer = (char *) malloc(10);
    160   1.6     lukem 	in_buffer_limit = in_buffer + 8;
    161   1.6     lukem 	buf_ptr = buf_end = in_buffer;
    162   1.6     lukem 	line_no = 1;
    163   1.6     lukem 	had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
    164   1.6     lukem 	sp_sw = force_nl = false;
    165   1.6     lukem 	ps.in_or_st = false;
    166   1.6     lukem 	ps.bl_line = true;
    167   1.6     lukem 	dec_ind = 0;
    168   1.6     lukem 	di_stack[ps.dec_nest = 0] = 0;
    169   1.6     lukem 	ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
    170   1.6     lukem 
    171   1.6     lukem 
    172   1.6     lukem 	scase = ps.pcase = false;
    173   1.6     lukem 	squest = 0;
    174   1.6     lukem 	sc_end = 0;
    175   1.6     lukem 	bp_save = 0;
    176   1.6     lukem 	be_save = 0;
    177   1.6     lukem 
    178   1.6     lukem 	output = 0;
    179   1.1       cgd 
    180   1.1       cgd 
    181   1.1       cgd 
    182   1.6     lukem 	/*--------------------------------------------------*\
    183   1.6     lukem         |   		COMMAND LINE SCAN		 |
    184   1.6     lukem         \*--------------------------------------------------*/
    185   1.1       cgd 
    186   1.1       cgd #ifdef undef
    187   1.6     lukem 	max_col = 78;		/* -l78 */
    188   1.6     lukem 	lineup_to_parens = 1;	/* -lp */
    189   1.6     lukem 	ps.ljust_decl = 0;	/* -ndj */
    190   1.6     lukem 	ps.com_ind = 33;	/* -c33 */
    191   1.6     lukem 	star_comment_cont = 1;	/* -sc */
    192   1.6     lukem 	ps.ind_size = 8;	/* -i8 */
    193   1.6     lukem 	verbose = 0;
    194   1.6     lukem 	ps.decl_indent = 16;	/* -di16 */
    195   1.6     lukem 	ps.indent_parameters = 1;	/* -ip */
    196   1.6     lukem 	ps.decl_com_ind = 0;	/* if this is not set to some positive value
    197   1.1       cgd 				 * by an arg, we will set this equal to
    198   1.1       cgd 				 * ps.com_ind */
    199   1.6     lukem 	btype_2 = 1;		/* -br */
    200   1.6     lukem 	cuddle_else = 1;	/* -ce */
    201   1.6     lukem 	ps.unindent_displace = 0;	/* -d0 */
    202   1.6     lukem 	ps.case_indent = 0;	/* -cli0 */
    203   1.6     lukem 	format_col1_comments = 1;	/* -fc1 */
    204   1.6     lukem 	procnames_start_line = 1;	/* -psl */
    205   1.6     lukem 	proc_calls_space = 0;	/* -npcs */
    206   1.6     lukem 	comment_delimiter_on_blankline = 1;	/* -cdb */
    207   1.6     lukem 	ps.leave_comma = 1;	/* -nbc */
    208   1.1       cgd #endif
    209   1.1       cgd 
    210   1.6     lukem 	for (i = 1; i < argc; ++i)
    211   1.6     lukem 		if (strcmp(argv[i], "-npro") == 0)
    212   1.6     lukem 			break;
    213   1.6     lukem 	set_defaults();
    214   1.6     lukem 	if (i >= argc)
    215   1.6     lukem 		set_profile();
    216   1.1       cgd 
    217   1.6     lukem 	for (i = 1; i < argc; ++i) {
    218   1.1       cgd 
    219   1.6     lukem 		/*
    220   1.6     lukem 		 * look thru args (if any) for changes to defaults
    221   1.6     lukem 		 */
    222   1.6     lukem 		if (argv[i][0] != '-') {	/* no flag on parameter */
    223   1.6     lukem 			if (input == 0) {	/* we must have the input file */
    224   1.6     lukem 				in_name = argv[i];	/* remember name of
    225   1.6     lukem 							 * input file */
    226   1.6     lukem 				input = fopen(in_name, "r");
    227   1.6     lukem 				if (input == 0)	/* check for open error */
    228   1.6     lukem 					err(1, "%s", in_name);
    229   1.6     lukem 				continue;
    230   1.6     lukem 			} else
    231   1.6     lukem 				if (output == 0) {	/* we have the output
    232   1.6     lukem 							 * file */
    233   1.6     lukem 					out_name = argv[i];	/* remember name of
    234   1.6     lukem 								 * output file */
    235   1.6     lukem 					if (strcmp(in_name, out_name) == 0) {	/* attempt to overwrite
    236   1.6     lukem 										 * the file */
    237  1.20  ginsbach 						errx(1, "input and output files must be different");
    238   1.6     lukem 					}
    239   1.6     lukem 					output = fopen(out_name, "w");
    240   1.6     lukem 					if (output == 0)	/* check for create
    241   1.6     lukem 								 * error */
    242   1.6     lukem 						err(1, "%s", out_name);
    243   1.6     lukem 					continue;
    244   1.6     lukem 				}
    245  1.20  ginsbach 			errx(1, "unknown parameter: %s", argv[i]);
    246   1.6     lukem 		} else
    247   1.6     lukem 			set_option(argv[i]);
    248   1.6     lukem 	}			/* end of for */
    249   1.6     lukem 	if (input == 0) {
    250   1.8    mellon 		input = stdin;
    251   1.6     lukem 	}
    252   1.7      ross 	if (output == 0) {
    253   1.8    mellon 		if (troff || input == stdin)
    254   1.6     lukem 			output = stdout;
    255   1.6     lukem 		else {
    256   1.6     lukem 			out_name = in_name;
    257   1.6     lukem 			bakcopy();
    258   1.1       cgd 		}
    259   1.7      ross 	}
    260   1.6     lukem 	if (ps.com_ind <= 1)
    261  1.22  ginsbach 		ps.com_ind = 2;	/* don't put normal comments before column 2 */
    262   1.6     lukem 	if (troff) {
    263   1.6     lukem 		if (bodyf.font[0] == 0)
    264   1.6     lukem 			parsefont(&bodyf, "R");
    265   1.6     lukem 		if (scomf.font[0] == 0)
    266   1.6     lukem 			parsefont(&scomf, "I");
    267   1.6     lukem 		if (blkcomf.font[0] == 0)
    268   1.6     lukem 			blkcomf = scomf, blkcomf.size += 2;
    269   1.6     lukem 		if (boxcomf.font[0] == 0)
    270   1.6     lukem 			boxcomf = blkcomf;
    271   1.6     lukem 		if (stringf.font[0] == 0)
    272   1.6     lukem 			parsefont(&stringf, "L");
    273   1.6     lukem 		if (keywordf.font[0] == 0)
    274   1.6     lukem 			parsefont(&keywordf, "B");
    275   1.6     lukem 		writefdef(&bodyf, 'B');
    276   1.6     lukem 		writefdef(&scomf, 'C');
    277   1.6     lukem 		writefdef(&blkcomf, 'L');
    278   1.6     lukem 		writefdef(&boxcomf, 'X');
    279   1.6     lukem 		writefdef(&stringf, 'S');
    280   1.6     lukem 		writefdef(&keywordf, 'K');
    281   1.1       cgd 	}
    282   1.6     lukem 	if (block_comment_max_col <= 0)
    283   1.6     lukem 		block_comment_max_col = max_col;
    284   1.6     lukem 	if (ps.decl_com_ind <= 0)	/* if not specified by user, set this */
    285   1.6     lukem 		ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
    286   1.6     lukem 	if (continuation_indent == 0)
    287   1.6     lukem 		continuation_indent = ps.ind_size;
    288   1.6     lukem 	fill_buffer();		/* get first batch of stuff into input buffer */
    289   1.6     lukem 
    290   1.6     lukem 	parse(semicolon);
    291   1.6     lukem 	{
    292   1.6     lukem 		char   *p = buf_ptr;
    293   1.6     lukem 		int     col = 1;
    294   1.6     lukem 
    295   1.6     lukem 		while (1) {
    296   1.6     lukem 			if (*p == ' ')
    297   1.6     lukem 				col++;
    298   1.6     lukem 			else
    299   1.6     lukem 				if (*p == '\t')
    300   1.6     lukem 					col = ((col - 1) & ~7) + 9;
    301   1.6     lukem 				else
    302   1.6     lukem 					break;
    303   1.6     lukem 			p++;
    304   1.6     lukem 		}
    305   1.6     lukem 		if (col > ps.ind_size)
    306   1.6     lukem 			ps.ind_level = ps.i_l_follow = col / ps.ind_size;
    307   1.1       cgd 	}
    308   1.6     lukem 	if (troff) {
    309  1.18     lukem 		const char   *p = in_name, *beg = in_name;
    310   1.6     lukem 
    311   1.6     lukem 		while (*p)
    312   1.6     lukem 			if (*p++ == '/')
    313   1.6     lukem 				beg = p;
    314   1.6     lukem 		fprintf(output, ".Fn \"%s\"\n", beg);
    315   1.1       cgd 	}
    316   1.6     lukem 	/*
    317   1.6     lukem          * START OF MAIN LOOP
    318   1.6     lukem          */
    319   1.1       cgd 
    320   1.6     lukem 	while (1) {		/* this is the main loop.  it will go until we
    321   1.1       cgd 				 * reach eof */
    322   1.6     lukem 		int     is_procname;
    323   1.1       cgd 
    324   1.6     lukem 		type_code = lexi();	/* lexi reads one token.  The actual
    325   1.6     lukem 					 * characters read are stored in
    326   1.6     lukem 					 * "token". lexi returns a code
    327   1.6     lukem 					 * indicating the type of token */
    328   1.6     lukem 		is_procname = ps.procname[0];
    329   1.1       cgd 
    330   1.6     lukem 		/*
    331   1.6     lukem 		 * The following code moves everything following an if (), while (),
    332   1.6     lukem 		 * else, etc. up to the start of the following stmt to a buffer. This
    333   1.6     lukem 		 * allows proper handling of both kinds of brace placement.
    334   1.6     lukem 		 */
    335   1.6     lukem 
    336   1.6     lukem 		flushed_nl = false;
    337   1.6     lukem 		while (ps.search_brace) {	/* if we scanned an if(),
    338   1.6     lukem 						 * while(), etc., we might
    339   1.6     lukem 						 * need to copy stuff into a
    340   1.6     lukem 						 * buffer we must loop,
    341   1.6     lukem 						 * copying stuff into
    342   1.6     lukem 						 * save_com, until we find the
    343   1.6     lukem 						 * start of the stmt which
    344   1.6     lukem 						 * follows the if, or whatever */
    345   1.6     lukem 			switch (type_code) {
    346   1.6     lukem 			case newline:
    347   1.6     lukem 				++line_no;
    348   1.6     lukem 				flushed_nl = true;
    349   1.6     lukem 			case form_feed:
    350   1.6     lukem 				break;	/* form feeds and newlines found here
    351   1.6     lukem 					 * will be ignored */
    352   1.6     lukem 
    353   1.6     lukem 			case lbrace:	/* this is a brace that starts the
    354   1.6     lukem 					 * compound stmt */
    355   1.6     lukem 				if (sc_end == 0) {	/* ignore buffering if a
    356  1.22  ginsbach 							 * comment wasn't stored
    357   1.6     lukem 							 * up */
    358   1.6     lukem 					ps.search_brace = false;
    359   1.6     lukem 					goto check_type;
    360   1.6     lukem 				}
    361   1.6     lukem 				if (btype_2) {
    362   1.6     lukem 					save_com[0] = '{';	/* we either want to put
    363   1.6     lukem 								 * the brace right after
    364   1.6     lukem 								 * the if */
    365   1.6     lukem 					goto sw_buffer;	/* go to common code to
    366   1.6     lukem 							 * get out of this loop */
    367   1.6     lukem 				}
    368   1.6     lukem 			case comment:	/* we have a comment, so we must copy
    369   1.6     lukem 					 * it into the buffer */
    370   1.6     lukem 				if (!flushed_nl || sc_end != 0) {
    371   1.6     lukem 					if (sc_end == 0) {	/* if this is the first
    372   1.6     lukem 								 * comment, we must set
    373   1.6     lukem 								 * up the buffer */
    374   1.6     lukem 						save_com[0] = save_com[1] = ' ';
    375   1.6     lukem 						sc_end = &(save_com[2]);
    376   1.6     lukem 					} else {
    377   1.6     lukem 						*sc_end++ = '\n';	/* add newline between
    378   1.6     lukem 									 * comments */
    379   1.6     lukem 						*sc_end++ = ' ';
    380   1.6     lukem 						--line_no;
    381   1.6     lukem 					}
    382   1.6     lukem 					*sc_end++ = '/';	/* copy in start of
    383   1.6     lukem 								 * comment */
    384   1.6     lukem 					*sc_end++ = '*';
    385   1.6     lukem 
    386   1.6     lukem 					for (;;) {	/* loop until we get to
    387   1.6     lukem 							 * the end of the
    388   1.6     lukem 							 * comment */
    389   1.6     lukem 						*sc_end = *buf_ptr++;
    390   1.6     lukem 						if (buf_ptr >= buf_end)
    391   1.6     lukem 							fill_buffer();
    392   1.6     lukem 
    393   1.6     lukem 						if (*sc_end++ == '*' && *buf_ptr == '/')
    394   1.6     lukem 							break;	/* we are at end of
    395   1.6     lukem 								 * comment */
    396   1.6     lukem 
    397   1.6     lukem 						if (sc_end >= &(save_com[sc_size])) {	/* check for temp buffer
    398   1.6     lukem 											 * overflow */
    399   1.6     lukem 							diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
    400   1.6     lukem 							fflush(output);
    401   1.6     lukem 							exit(1);
    402   1.6     lukem 						}
    403   1.6     lukem 					}
    404   1.6     lukem 					*sc_end++ = '/';	/* add ending slash */
    405   1.6     lukem 					if (++buf_ptr >= buf_end)	/* get past / in buffer */
    406   1.6     lukem 						fill_buffer();
    407   1.6     lukem 					break;
    408   1.6     lukem 				}
    409   1.6     lukem 			default:	/* it is the start of a normal
    410   1.6     lukem 					 * statment */
    411   1.6     lukem 				if (flushed_nl)	/* if we flushed a newline,
    412   1.6     lukem 						 * make sure it is put back */
    413   1.6     lukem 					force_nl = true;
    414   1.6     lukem 				if ((type_code == sp_paren && *token == 'i'
    415   1.6     lukem 					&& last_else && ps.else_if) ||
    416   1.6     lukem 				    (type_code == sp_nparen && *token == 'e'
    417   1.6     lukem 					&& e_code != s_code && e_code[-1] == '}'))
    418   1.6     lukem 					force_nl = false;
    419   1.6     lukem 
    420   1.6     lukem 				if (sc_end == 0) {	/* ignore buffering if
    421  1.22  ginsbach 							 * comment wasn't saved
    422   1.6     lukem 							 * up */
    423   1.6     lukem 					ps.search_brace = false;
    424   1.6     lukem 					goto check_type;
    425   1.6     lukem 				}
    426   1.6     lukem 				if (force_nl) {	/* if we should insert a nl
    427   1.6     lukem 						 * here, put it into the
    428   1.6     lukem 						 * buffer */
    429   1.6     lukem 					force_nl = false;
    430   1.6     lukem 					--line_no;	/* this will be
    431   1.6     lukem 							 * re-increased when the
    432   1.6     lukem 							 * nl is read from the
    433   1.6     lukem 							 * buffer */
    434   1.6     lukem 					*sc_end++ = '\n';
    435   1.6     lukem 					*sc_end++ = ' ';
    436   1.6     lukem 					if (verbose && !flushed_nl)	/* print error msg if
    437   1.6     lukem 									 * the line was not
    438   1.6     lukem 									 * already broken */
    439   1.6     lukem 						diag(0, "Line broken");
    440   1.6     lukem 					flushed_nl = false;
    441   1.6     lukem 				}
    442   1.6     lukem 				for (t_ptr = token; *t_ptr; ++t_ptr)
    443   1.6     lukem 					*sc_end++ = *t_ptr;	/* copy token into temp
    444   1.6     lukem 								 * buffer */
    445   1.6     lukem 				ps.procname[0] = 0;
    446   1.6     lukem 
    447   1.6     lukem 		sw_buffer:
    448   1.6     lukem 				ps.search_brace = false;	/* stop looking for
    449   1.6     lukem 								 * start of stmt */
    450   1.6     lukem 				bp_save = buf_ptr;	/* save current input
    451   1.6     lukem 							 * buffer */
    452   1.6     lukem 				be_save = buf_end;
    453   1.6     lukem 				buf_ptr = save_com;	/* fix so that
    454   1.6     lukem 							 * subsequent calls to
    455   1.6     lukem 							 * lexi will take tokens
    456   1.6     lukem 							 * out of save_com */
    457   1.6     lukem 				*sc_end++ = ' ';	/* add trailing blank,
    458   1.6     lukem 							 * just in case */
    459   1.6     lukem 				buf_end = sc_end;
    460   1.6     lukem 				sc_end = 0;
    461   1.6     lukem 				break;
    462   1.6     lukem 			}	/* end of switch */
    463   1.6     lukem 			if (type_code != 0)	/* we must make this check,
    464   1.6     lukem 						 * just in case there was an
    465   1.6     lukem 						 * unexpected EOF */
    466   1.6     lukem 				type_code = lexi();	/* read another token */
    467   1.6     lukem 			/* if (ps.search_brace) ps.procname[0] = 0; */
    468   1.6     lukem 			if ((is_procname = ps.procname[0]) && flushed_nl
    469   1.6     lukem 			    && !procnames_start_line && ps.in_decl
    470   1.6     lukem 			    && type_code == ident)
    471   1.6     lukem 				flushed_nl = 0;
    472   1.6     lukem 		}		/* end of while (search_brace) */
    473   1.6     lukem 		last_else = 0;
    474   1.1       cgd check_type:
    475   1.6     lukem 		if (type_code == 0) {	/* we got eof */
    476   1.6     lukem 			if (s_lab != e_lab || s_code != e_code
    477   1.6     lukem 			    || s_com != e_com)	/* must dump end of line */
    478   1.6     lukem 				dump_line();
    479   1.6     lukem 			if (ps.tos > 1)	/* check for balanced braces */
    480   1.6     lukem 				diag(1, "Stuff missing from end of file.");
    481   1.6     lukem 
    482   1.6     lukem 			if (verbose) {
    483   1.6     lukem 				printf("There were %d output lines and %d comments\n",
    484   1.6     lukem 				    ps.out_lines, ps.out_coms);
    485   1.6     lukem 				printf("(Lines with comments)/(Lines with code): %6.3f\n",
    486   1.6     lukem 				    (1.0 * ps.com_lines) / code_lines);
    487   1.6     lukem 			}
    488   1.6     lukem 			fflush(output);
    489   1.6     lukem 			exit(found_err);
    490   1.1       cgd 		}
    491   1.6     lukem 		if (
    492   1.6     lukem 		    (type_code != comment) &&
    493   1.6     lukem 		    (type_code != newline) &&
    494   1.6     lukem 		    (type_code != preesc) &&
    495   1.6     lukem 		    (type_code != form_feed)) {
    496   1.6     lukem 			if (force_nl &&
    497   1.6     lukem 			    (type_code != semicolon) &&
    498   1.6     lukem 			    (type_code != lbrace || !btype_2)) {
    499   1.6     lukem 				/* we should force a broken line here */
    500   1.6     lukem 				if (verbose && !flushed_nl)
    501   1.6     lukem 					diag(0, "Line broken");
    502   1.6     lukem 				flushed_nl = false;
    503   1.6     lukem 				dump_line();
    504  1.22  ginsbach 				ps.want_blank = false;	/* don't insert blank at
    505   1.6     lukem 							 * line start */
    506   1.6     lukem 				force_nl = false;
    507   1.6     lukem 			}
    508   1.6     lukem 			ps.in_stmt = true;	/* turn on flag which causes
    509   1.6     lukem 						 * an extra level of
    510   1.6     lukem 						 * indentation. this is turned
    511   1.6     lukem 						 * off by a ; or '}' */
    512   1.6     lukem 			if (s_com != e_com) {	/* the turkey has embedded a
    513   1.6     lukem 						 * comment in a line. fix it */
    514   1.6     lukem 				*e_code++ = ' ';
    515   1.6     lukem 				for (t_ptr = s_com; *t_ptr; ++t_ptr) {
    516   1.6     lukem 					CHECK_SIZE_CODE;
    517   1.6     lukem 					*e_code++ = *t_ptr;
    518   1.6     lukem 				}
    519   1.6     lukem 				*e_code++ = ' ';
    520   1.6     lukem 				*e_code = '\0';	/* null terminate code sect */
    521   1.6     lukem 				ps.want_blank = false;
    522   1.6     lukem 				e_com = s_com;
    523   1.6     lukem 			}
    524   1.6     lukem 		} else
    525   1.6     lukem 			if (type_code != comment)	/* preserve force_nl
    526   1.6     lukem 							 * thru a comment */
    527   1.6     lukem 				force_nl = false;	/* cancel forced newline
    528   1.6     lukem 							 * after newline, form
    529   1.6     lukem 							 * feed, etc */
    530   1.1       cgd 
    531   1.1       cgd 
    532   1.1       cgd 
    533   1.6     lukem 		/*-----------------------------------------------------*\
    534   1.6     lukem 		|	   do switch on type of token scanned		|
    535   1.6     lukem 		\*-----------------------------------------------------*/
    536   1.6     lukem 		CHECK_SIZE_CODE;
    537   1.6     lukem 		switch (type_code) {	/* now, decide what to do with the
    538   1.6     lukem 					 * token */
    539   1.6     lukem 
    540   1.6     lukem 		case form_feed:/* found a form feed in line */
    541   1.6     lukem 			ps.use_ff = true;	/* a form feed is treated much
    542   1.6     lukem 						 * like a newline */
    543   1.6     lukem 			dump_line();
    544   1.6     lukem 			ps.want_blank = false;
    545   1.6     lukem 			break;
    546   1.6     lukem 
    547   1.6     lukem 		case newline:
    548   1.6     lukem 			if (ps.last_token != comma || ps.p_l_follow > 0
    549   1.6     lukem 			    || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
    550   1.6     lukem 				dump_line();
    551   1.6     lukem 				ps.want_blank = false;
    552   1.6     lukem 			}
    553   1.6     lukem 			++line_no;	/* keep track of input line number */
    554   1.6     lukem 			break;
    555   1.1       cgd 
    556   1.6     lukem 		case lparen:	/* got a '(' or '[' */
    557   1.6     lukem 			++ps.p_l_follow;	/* count parens to make Healy
    558   1.6     lukem 						 * happy */
    559   1.6     lukem 			if (ps.want_blank && *token != '[' &&
    560   1.6     lukem 			    (ps.last_token != ident || proc_calls_space
    561   1.6     lukem 				|| (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
    562   1.6     lukem 				*e_code++ = ' ';
    563  1.10  christos 			if (ps.in_decl && !ps.block_init) {
    564   1.6     lukem 				if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) {
    565   1.6     lukem 					ps.dumped_decl_indent = 1;
    566   1.6     lukem 					sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
    567   1.6     lukem 					e_code += strlen(e_code);
    568   1.6     lukem 				} else {
    569   1.6     lukem 					while ((e_code - s_code) < dec_ind) {
    570   1.6     lukem 						CHECK_SIZE_CODE;
    571   1.6     lukem 						*e_code++ = ' ';
    572   1.6     lukem 					}
    573   1.6     lukem 					*e_code++ = token[0];
    574   1.6     lukem 				}
    575  1.10  christos 			} else
    576   1.6     lukem 				*e_code++ = token[0];
    577   1.6     lukem 			ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
    578   1.6     lukem 			if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
    579   1.6     lukem 			    && ps.paren_indents[0] < 2 * ps.ind_size)
    580   1.6     lukem 				ps.paren_indents[0] = 2 * ps.ind_size;
    581   1.6     lukem 			ps.want_blank = false;
    582   1.6     lukem 			if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
    583   1.6     lukem 				/*
    584   1.6     lukem 				 * this is a kluge to make sure that declarations will be
    585   1.6     lukem 				 * aligned right if proc decl has an explicit type on it, i.e.
    586   1.6     lukem 				 * "int a(x) {..."
    587   1.6     lukem 				 */
    588   1.6     lukem 				parse(semicolon);	/* I said this was a
    589   1.6     lukem 							 * kluge... */
    590   1.6     lukem 				ps.in_or_st = false;	/* turn off flag for
    591   1.6     lukem 							 * structure decl or
    592   1.6     lukem 							 * initialization */
    593   1.6     lukem 			}
    594   1.6     lukem 			if (ps.sizeof_keyword)
    595   1.6     lukem 				ps.sizeof_mask |= 1 << ps.p_l_follow;
    596   1.1       cgd 			break;
    597   1.6     lukem 
    598   1.6     lukem 		case rparen:	/* got a ')' or ']' */
    599   1.6     lukem 			rparen_count--;
    600   1.6     lukem 			if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
    601   1.6     lukem 				ps.last_u_d = true;
    602   1.6     lukem 				ps.cast_mask &= (1 << ps.p_l_follow) - 1;
    603   1.6     lukem 			}
    604   1.6     lukem 			ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
    605   1.6     lukem 			if (--ps.p_l_follow < 0) {
    606   1.6     lukem 				ps.p_l_follow = 0;
    607   1.6     lukem 				diag(0, "Extra %c", *token);
    608   1.6     lukem 			}
    609   1.6     lukem 			if (e_code == s_code)	/* if the paren starts the
    610   1.6     lukem 						 * line */
    611   1.6     lukem 				ps.paren_level = ps.p_l_follow;	/* then indent it */
    612   1.6     lukem 
    613   1.6     lukem 			*e_code++ = token[0];
    614   1.6     lukem 			ps.want_blank = true;
    615   1.6     lukem 
    616   1.6     lukem 			if (sp_sw && (ps.p_l_follow == 0)) {	/* check for end of if
    617   1.6     lukem 								 * (...), or some such */
    618   1.6     lukem 				sp_sw = false;
    619   1.6     lukem 				force_nl = true;	/* must force newline
    620   1.6     lukem 							 * after if */
    621   1.6     lukem 				ps.last_u_d = true;	/* inform lexi that a
    622   1.6     lukem 							 * following operator is
    623   1.6     lukem 							 * unary */
    624  1.22  ginsbach 				ps.in_stmt = false;	/* don't use stmt
    625   1.6     lukem 							 * continuation
    626   1.6     lukem 							 * indentation */
    627   1.6     lukem 
    628   1.6     lukem 				parse(hd_type);	/* let parser worry about if,
    629   1.6     lukem 						 * or whatever */
    630   1.6     lukem 			}
    631   1.6     lukem 			ps.search_brace = btype_2;	/* this should insure
    632   1.6     lukem 							 * that constructs such
    633   1.6     lukem 							 * as main(){...} and
    634   1.6     lukem 							 * int[]{...} have their
    635   1.6     lukem 							 * braces put in the
    636   1.6     lukem 							 * right place */
    637   1.1       cgd 			break;
    638   1.6     lukem 
    639   1.6     lukem 		case unary_op:	/* this could be any unary operation */
    640   1.6     lukem 			if (ps.want_blank)
    641   1.6     lukem 				*e_code++ = ' ';
    642   1.6     lukem 
    643   1.6     lukem 			if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) {
    644   1.6     lukem 				sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
    645   1.6     lukem 				ps.dumped_decl_indent = 1;
    646   1.6     lukem 				e_code += strlen(e_code);
    647   1.6     lukem 			} else {
    648  1.18     lukem 				const char *res = token;
    649   1.6     lukem 
    650   1.6     lukem 				if (ps.in_decl && !ps.block_init) {	/* if this is a unary op
    651   1.6     lukem 									 * in a declaration, we
    652   1.6     lukem 									 * should indent this
    653   1.6     lukem 									 * token */
    654   1.6     lukem 					for (i = 0; token[i]; ++i);	/* find length of token */
    655   1.6     lukem 					while ((e_code - s_code) < (dec_ind - i)) {
    656   1.6     lukem 						CHECK_SIZE_CODE;
    657   1.6     lukem 						*e_code++ = ' ';	/* pad it */
    658   1.6     lukem 					}
    659   1.6     lukem 				}
    660   1.6     lukem 				if (troff && token[0] == '-' && token[1] == '>')
    661   1.6     lukem 					res = "\\(->";
    662   1.6     lukem 				for (t_ptr = res; *t_ptr; ++t_ptr) {
    663   1.6     lukem 					CHECK_SIZE_CODE;
    664   1.6     lukem 					*e_code++ = *t_ptr;
    665   1.6     lukem 				}
    666   1.6     lukem 			}
    667   1.6     lukem 			ps.want_blank = false;
    668   1.1       cgd 			break;
    669   1.6     lukem 
    670   1.6     lukem 		case binary_op:/* any binary operation */
    671   1.6     lukem 			if (ps.want_blank)
    672   1.6     lukem 				*e_code++ = ' ';
    673   1.6     lukem 			{
    674  1.18     lukem 				const char *res = token;
    675   1.6     lukem 
    676   1.6     lukem 				if (troff)
    677   1.6     lukem 					switch (token[0]) {
    678   1.6     lukem 					case '<':
    679   1.6     lukem 						if (token[1] == '=')
    680   1.6     lukem 							res = "\\(<=";
    681   1.6     lukem 						break;
    682   1.6     lukem 					case '>':
    683   1.6     lukem 						if (token[1] == '=')
    684   1.6     lukem 							res = "\\(>=";
    685   1.6     lukem 						break;
    686   1.6     lukem 					case '!':
    687   1.6     lukem 						if (token[1] == '=')
    688   1.6     lukem 							res = "\\(!=";
    689   1.6     lukem 						break;
    690   1.6     lukem 					case '|':
    691   1.6     lukem 						if (token[1] == '|')
    692   1.6     lukem 							res = "\\(br\\(br";
    693   1.6     lukem 						else
    694   1.6     lukem 							if (token[1] == 0)
    695   1.6     lukem 								res = "\\(br";
    696   1.6     lukem 						break;
    697   1.6     lukem 					}
    698   1.6     lukem 				for (t_ptr = res; *t_ptr; ++t_ptr) {
    699   1.6     lukem 					CHECK_SIZE_CODE;
    700   1.6     lukem 					*e_code++ = *t_ptr;	/* move the operator */
    701   1.6     lukem 				}
    702   1.6     lukem 			}
    703   1.6     lukem 			ps.want_blank = true;
    704   1.1       cgd 			break;
    705   1.1       cgd 
    706   1.6     lukem 		case postop:	/* got a trailing ++ or -- */
    707   1.6     lukem 			*e_code++ = token[0];
    708   1.6     lukem 			*e_code++ = token[1];
    709   1.6     lukem 			ps.want_blank = true;
    710   1.6     lukem 			break;
    711   1.1       cgd 
    712   1.6     lukem 		case question:	/* got a ? */
    713   1.6     lukem 			squest++;	/* this will be used when a later
    714   1.6     lukem 					 * colon appears so we can distinguish
    715   1.6     lukem 					 * the <c>?<n>:<n> construct */
    716   1.6     lukem 			if (ps.want_blank)
    717   1.6     lukem 				*e_code++ = ' ';
    718   1.6     lukem 			*e_code++ = '?';
    719   1.6     lukem 			ps.want_blank = true;
    720   1.6     lukem 			break;
    721   1.1       cgd 
    722   1.6     lukem 		case casestmt:	/* got word 'case' or 'default' */
    723   1.6     lukem 			scase = true;	/* so we can process the later colon
    724   1.6     lukem 					 * properly */
    725   1.6     lukem 			goto copy_id;
    726   1.6     lukem 
    727   1.6     lukem 		case colon:	/* got a ':' */
    728   1.6     lukem 			if (squest > 0) {	/* it is part of the <c>?<n>:
    729   1.6     lukem 						 * <n> construct */
    730   1.6     lukem 				--squest;
    731   1.6     lukem 				if (ps.want_blank)
    732   1.6     lukem 					*e_code++ = ' ';
    733   1.6     lukem 				*e_code++ = ':';
    734   1.6     lukem 				ps.want_blank = true;
    735   1.6     lukem 				break;
    736   1.6     lukem 			}
    737  1.11    kleink 			if (ps.in_or_st) {
    738   1.6     lukem 				*e_code++ = ':';
    739   1.6     lukem 				ps.want_blank = false;
    740   1.6     lukem 				break;
    741   1.6     lukem 			}
    742   1.6     lukem 			ps.in_stmt = false;	/* seeing a label does not
    743   1.6     lukem 						 * imply we are in a stmt */
    744   1.6     lukem 			for (t_ptr = s_code; *t_ptr; ++t_ptr)
    745   1.6     lukem 				*e_lab++ = *t_ptr;	/* turn everything so
    746   1.6     lukem 							 * far into a label */
    747   1.6     lukem 			e_code = s_code;
    748   1.6     lukem 			*e_lab++ = ':';
    749   1.6     lukem 			*e_lab++ = ' ';
    750   1.6     lukem 			*e_lab = '\0';
    751   1.6     lukem 
    752   1.6     lukem 			force_nl = ps.pcase = scase;	/* ps.pcase will be used
    753   1.6     lukem 							 * by dump_line to
    754   1.6     lukem 							 * decide how to indent
    755   1.6     lukem 							 * the label. force_nl
    756   1.6     lukem 							 * will force a case n:
    757   1.6     lukem 							 * to be on a line by
    758   1.6     lukem 							 * itself */
    759   1.6     lukem 			scase = false;
    760   1.6     lukem 			ps.want_blank = false;
    761   1.6     lukem 			break;
    762   1.1       cgd 
    763   1.6     lukem 		case semicolon:/* got a ';' */
    764   1.6     lukem 			ps.in_or_st = false;	/* we are not in an
    765   1.6     lukem 						 * initialization or structure
    766   1.6     lukem 						 * declaration */
    767   1.6     lukem 			scase = false;	/* these will only need resetting in a
    768   1.6     lukem 					 * error */
    769   1.6     lukem 			squest = 0;
    770   1.6     lukem 			if (ps.last_token == rparen && rparen_count == 0)
    771   1.6     lukem 				ps.in_parameter_declaration = 0;
    772   1.6     lukem 			ps.cast_mask = 0;
    773   1.6     lukem 			ps.sizeof_mask = 0;
    774   1.6     lukem 			ps.block_init = 0;
    775   1.6     lukem 			ps.block_init_level = 0;
    776   1.6     lukem 			ps.just_saw_decl--;
    777   1.6     lukem 
    778   1.6     lukem 			if (ps.in_decl && s_code == e_code && !ps.block_init)
    779   1.6     lukem 				while ((e_code - s_code) < (dec_ind - 1)) {
    780   1.6     lukem 					CHECK_SIZE_CODE;
    781   1.6     lukem 					*e_code++ = ' ';
    782   1.6     lukem 				}
    783   1.6     lukem 
    784   1.6     lukem 			ps.in_decl = (ps.dec_nest > 0);	/* if we were in a first
    785   1.6     lukem 							 * level structure
    786  1.22  ginsbach 							 * declaration, we
    787  1.22  ginsbach 							 * aren't any more */
    788   1.6     lukem 
    789   1.6     lukem 			if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
    790   1.6     lukem 
    791   1.6     lukem 				/*
    792   1.6     lukem 				 * This should be true iff there were unbalanced parens in the
    793   1.6     lukem 				 * stmt.  It is a bit complicated, because the semicolon might
    794   1.6     lukem 				 * be in a for stmt
    795   1.6     lukem 				 */
    796   1.6     lukem 				diag(1, "Unbalanced parens");
    797   1.6     lukem 				ps.p_l_follow = 0;
    798   1.6     lukem 				if (sp_sw) {	/* this is a check for a if,
    799   1.6     lukem 						 * while, etc. with unbalanced
    800   1.6     lukem 						 * parens */
    801   1.6     lukem 					sp_sw = false;
    802  1.22  ginsbach 					parse(hd_type);	/* don't lose the if,
    803  1.22  ginsbach 							 * or whatever */
    804   1.6     lukem 				}
    805   1.6     lukem 			}
    806   1.6     lukem 			*e_code++ = ';';
    807   1.6     lukem 			ps.want_blank = true;
    808   1.6     lukem 			ps.in_stmt = (ps.p_l_follow > 0);	/* we are no longer in
    809   1.6     lukem 								 * the middle of a stmt */
    810   1.6     lukem 
    811   1.6     lukem 			if (!sp_sw) {	/* if not if for (;;) */
    812   1.6     lukem 				parse(semicolon);	/* let parser know about
    813   1.6     lukem 							 * end of stmt */
    814   1.6     lukem 				force_nl = true;	/* force newline after a
    815   1.6     lukem 							 * end of stmt */
    816   1.1       cgd 			}
    817   1.6     lukem 			break;
    818   1.6     lukem 
    819   1.6     lukem 		case lbrace:	/* got a '{' */
    820  1.22  ginsbach 			ps.in_stmt = false;	/* don't indent the {} */
    821   1.6     lukem 			if (!ps.block_init)
    822   1.6     lukem 				force_nl = true;	/* force other stuff on
    823   1.6     lukem 							 * same line as '{' onto
    824   1.6     lukem 							 * new line */
    825   1.1       cgd 			else
    826   1.6     lukem 				if (ps.block_init_level <= 0)
    827   1.6     lukem 					ps.block_init_level = 1;
    828   1.6     lukem 				else
    829   1.6     lukem 					ps.block_init_level++;
    830   1.6     lukem 
    831   1.6     lukem 			if (s_code != e_code && !ps.block_init) {
    832   1.6     lukem 				if (!btype_2) {
    833   1.6     lukem 					dump_line();
    834   1.6     lukem 					ps.want_blank = false;
    835   1.6     lukem 				} else
    836   1.6     lukem 					if (ps.in_parameter_declaration && !ps.in_or_st) {
    837   1.6     lukem 						ps.i_l_follow = 0;
    838   1.6     lukem 						dump_line();
    839   1.6     lukem 						ps.want_blank = false;
    840   1.6     lukem 					}
    841   1.6     lukem 			}
    842   1.6     lukem 			if (ps.in_parameter_declaration)
    843   1.6     lukem 				prefix_blankline_requested = 0;
    844   1.6     lukem 
    845  1.12       wiz 			if (ps.p_l_follow > 0) {	/* check for preceding
    846   1.6     lukem 							 * unbalanced parens */
    847   1.6     lukem 				diag(1, "Unbalanced parens");
    848   1.6     lukem 				ps.p_l_follow = 0;
    849   1.6     lukem 				if (sp_sw) {	/* check for unclosed if, for,
    850   1.6     lukem 						 * etc. */
    851   1.6     lukem 					sp_sw = false;
    852   1.6     lukem 					parse(hd_type);
    853   1.6     lukem 					ps.ind_level = ps.i_l_follow;
    854   1.6     lukem 				}
    855   1.6     lukem 			}
    856   1.6     lukem 			if (s_code == e_code)
    857  1.22  ginsbach 				ps.ind_stmt = false;	/* don't put extra
    858   1.6     lukem 							 * indentation on line
    859   1.6     lukem 							 * with '{' */
    860   1.6     lukem 			if (ps.in_decl && ps.in_or_st) {	/* this is either a
    861   1.6     lukem 								 * structure declaration
    862   1.6     lukem 								 * or an init */
    863   1.6     lukem 				di_stack[ps.dec_nest++] = dec_ind;
    864   1.6     lukem 				/* ?		dec_ind = 0; */
    865   1.6     lukem 			} else {
    866  1.22  ginsbach 				ps.decl_on_line = false;	/* we can't be in the
    867   1.6     lukem 								 * middle of a
    868  1.22  ginsbach 								 * declaration, so don't
    869   1.6     lukem 								 * do special
    870   1.6     lukem 								 * indentation of
    871   1.6     lukem 								 * comments */
    872   1.6     lukem 				if (blanklines_after_declarations_at_proctop
    873   1.6     lukem 				    && ps.in_parameter_declaration)
    874   1.6     lukem 					postfix_blankline_requested = 1;
    875   1.6     lukem 				ps.in_parameter_declaration = 0;
    876   1.6     lukem 			}
    877   1.6     lukem 			dec_ind = 0;
    878   1.6     lukem 			parse(lbrace);	/* let parser know about this */
    879   1.6     lukem 			if (ps.want_blank)	/* put a blank before '{' if
    880   1.6     lukem 						 * '{' is not at start of line */
    881   1.1       cgd 				*e_code++ = ' ';
    882   1.6     lukem 			ps.want_blank = false;
    883   1.6     lukem 			*e_code++ = '{';
    884   1.6     lukem 			ps.just_saw_decl = 0;
    885   1.6     lukem 			break;
    886   1.6     lukem 
    887   1.6     lukem 		case rbrace:	/* got a '}' */
    888   1.6     lukem 			if (ps.p_stack[ps.tos] == decl && !ps.block_init)	/* semicolons can be
    889   1.6     lukem 										 * omitted in
    890   1.6     lukem 										 * declarations */
    891   1.6     lukem 				parse(semicolon);
    892   1.6     lukem 			if (ps.p_l_follow) {	/* check for unclosed if, for,
    893   1.6     lukem 						 * else. */
    894   1.6     lukem 				diag(1, "Unbalanced parens");
    895   1.6     lukem 				ps.p_l_follow = 0;
    896   1.6     lukem 				sp_sw = false;
    897   1.6     lukem 			}
    898   1.6     lukem 			ps.just_saw_decl = 0;
    899   1.6     lukem 			ps.block_init_level--;
    900   1.6     lukem 			if (s_code != e_code && !ps.block_init) {	/* '}' must be first on
    901   1.6     lukem 									 * line */
    902   1.6     lukem 				if (verbose)
    903   1.6     lukem 					diag(0, "Line broken");
    904   1.6     lukem 				dump_line();
    905   1.6     lukem 			}
    906   1.6     lukem 			*e_code++ = '}';
    907   1.6     lukem 			ps.want_blank = true;
    908   1.6     lukem 			ps.in_stmt = ps.ind_stmt = false;
    909   1.6     lukem 			if (ps.dec_nest > 0) {	/* we are in multi-level
    910   1.6     lukem 						 * structure declaration */
    911   1.6     lukem 				dec_ind = di_stack[--ps.dec_nest];
    912   1.6     lukem 				if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
    913   1.6     lukem 					ps.just_saw_decl = 2;
    914   1.6     lukem 				ps.in_decl = true;
    915   1.6     lukem 			}
    916   1.6     lukem 			prefix_blankline_requested = 0;
    917   1.6     lukem 			parse(rbrace);	/* let parser know about this */
    918   1.6     lukem 			ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
    919   1.6     lukem 			    && ps.il[ps.tos] >= ps.ind_level;
    920   1.6     lukem 			if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
    921   1.6     lukem 				postfix_blankline_requested = 1;
    922   1.6     lukem 			break;
    923   1.1       cgd 
    924   1.6     lukem 		case swstmt:	/* got keyword "switch" */
    925   1.6     lukem 			sp_sw = true;
    926   1.6     lukem 			hd_type = swstmt;	/* keep this for when we have
    927   1.6     lukem 						 * seen the expression */
    928   1.6     lukem 			goto copy_id;	/* go move the token into buffer */
    929   1.6     lukem 
    930   1.6     lukem 		case sp_paren:	/* token is if, while, for */
    931   1.6     lukem 			sp_sw = true;	/* the interesting stuff is done after
    932   1.6     lukem 					 * the expression is scanned */
    933   1.6     lukem 			hd_type = (*token == 'i' ? ifstmt :
    934   1.6     lukem 			    (*token == 'w' ? whilestmt : forstmt));
    935   1.6     lukem 
    936   1.6     lukem 			/*
    937   1.6     lukem 		         * remember the type of header for later use by parser
    938   1.6     lukem 		         */
    939   1.6     lukem 			goto copy_id;	/* copy the token into line */
    940   1.6     lukem 
    941   1.6     lukem 		case sp_nparen:/* got else, do */
    942   1.6     lukem 			ps.in_stmt = false;
    943   1.6     lukem 			if (*token == 'e') {
    944   1.6     lukem 				if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
    945   1.6     lukem 					if (verbose)
    946   1.6     lukem 						diag(0, "Line broken");
    947   1.6     lukem 					dump_line();	/* make sure this starts
    948   1.6     lukem 							 * a line */
    949   1.6     lukem 					ps.want_blank = false;
    950   1.6     lukem 				}
    951   1.6     lukem 				force_nl = true;	/* also, following stuff
    952   1.6     lukem 							 * must go onto new line */
    953   1.6     lukem 				last_else = 1;
    954   1.6     lukem 				parse(elselit);
    955   1.6     lukem 			} else {
    956   1.6     lukem 				if (e_code != s_code) {	/* make sure this starts
    957   1.6     lukem 							 * a line */
    958   1.6     lukem 					if (verbose)
    959   1.6     lukem 						diag(0, "Line broken");
    960   1.6     lukem 					dump_line();
    961   1.6     lukem 					ps.want_blank = false;
    962   1.6     lukem 				}
    963   1.6     lukem 				force_nl = true;	/* also, following stuff
    964   1.6     lukem 							 * must go onto new line */
    965   1.6     lukem 				last_else = 0;
    966   1.6     lukem 				parse(dolit);
    967   1.6     lukem 			}
    968   1.6     lukem 			goto copy_id;	/* move the token into line */
    969   1.1       cgd 
    970   1.6     lukem 		case decl:	/* we have a declaration type (int, register,
    971   1.6     lukem 				 * etc.) */
    972   1.6     lukem 			parse(decl);	/* let parser worry about indentation */
    973   1.6     lukem 			if (ps.last_token == rparen && ps.tos <= 1) {
    974   1.6     lukem 				ps.in_parameter_declaration = 1;
    975   1.6     lukem 				if (s_code != e_code) {
    976   1.6     lukem 					dump_line();
    977   1.6     lukem 					ps.want_blank = 0;
    978   1.6     lukem 				}
    979   1.1       cgd 			}
    980   1.6     lukem 			if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
    981   1.6     lukem 				ps.ind_level = ps.i_l_follow = 1;
    982   1.6     lukem 				ps.ind_stmt = 0;
    983   1.1       cgd 			}
    984   1.6     lukem 			ps.in_or_st = true;	/* this might be a structure
    985   1.6     lukem 						 * or initialization
    986   1.6     lukem 						 * declaration */
    987   1.6     lukem 			ps.in_decl = ps.decl_on_line = true;
    988   1.6     lukem 			if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
    989   1.6     lukem 				ps.just_saw_decl = 2;
    990   1.6     lukem 			prefix_blankline_requested = 0;
    991   1.6     lukem 			for (i = 0; token[i++];);	/* get length of token */
    992   1.6     lukem 
    993   1.6     lukem 			/*
    994   1.6     lukem 		         * dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent
    995   1.6     lukem 		         * : i);
    996   1.6     lukem 		         */
    997   1.6     lukem 			dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
    998  1.19       mrg 			tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0);
    999   1.6     lukem 			goto copy_id;
   1000   1.6     lukem 
   1001   1.6     lukem 		case ident:	/* got an identifier or constant */
   1002   1.6     lukem 			if (ps.in_decl) {	/* if we are in a declaration,
   1003   1.6     lukem 						 * we must indent identifier */
   1004   1.6     lukem 				if (ps.want_blank)
   1005   1.6     lukem 					*e_code++ = ' ';
   1006   1.6     lukem 				ps.want_blank = false;
   1007   1.6     lukem 				if (is_procname == 0 || !procnames_start_line) {
   1008   1.7      ross 					if (!ps.block_init) {
   1009   1.6     lukem 						if (troff && !ps.dumped_decl_indent) {
   1010   1.6     lukem 							sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7);
   1011   1.6     lukem 							ps.dumped_decl_indent = 1;
   1012   1.6     lukem 							e_code += strlen(e_code);
   1013  1.19       mrg 							CHECK_SIZE_CODE;
   1014  1.19       mrg 						} else {
   1015  1.19       mrg 							int cur_dec_ind;
   1016  1.19       mrg 							int pos, startpos;
   1017  1.19       mrg 
   1018  1.19       mrg 							/*
   1019  1.19       mrg 							 * in order to get the tab math right for
   1020  1.19       mrg 							 * indentations that are not multiples of 8 we
   1021  1.19       mrg 							 * need to modify both startpos and dec_ind
   1022  1.19       mrg 							 * (cur_dec_ind) here by eight minus the
   1023  1.19       mrg 							 * remainder of the current starting column
   1024  1.19       mrg 							 * divided by eight. This seems to be a
   1025  1.19       mrg 							 * properly working fix
   1026  1.19       mrg 							 */
   1027  1.19       mrg 							startpos = e_code - s_code;
   1028  1.19       mrg 							cur_dec_ind = dec_ind;
   1029  1.19       mrg 							pos = startpos;
   1030  1.19       mrg 							if ((ps.ind_level * ps.ind_size) % 8 != 0) {
   1031  1.19       mrg 								pos += (ps.ind_level * ps.ind_size) % 8;
   1032  1.19       mrg 								cur_dec_ind += (ps.ind_level * ps.ind_size) % 8;
   1033  1.19       mrg 							}
   1034  1.19       mrg 
   1035  1.19       mrg 							if (tabs_to_var) {
   1036  1.19       mrg 								while ((pos & ~7) + 8 <= cur_dec_ind) {
   1037  1.19       mrg 									CHECK_SIZE_CODE;
   1038  1.19       mrg 									*e_code++ = '\t';
   1039  1.19       mrg 									pos = (pos & ~7) + 8;
   1040  1.19       mrg 								}
   1041  1.19       mrg 							}
   1042  1.19       mrg 							while (pos < cur_dec_ind) {
   1043   1.6     lukem 								CHECK_SIZE_CODE;
   1044   1.6     lukem 								*e_code++ = ' ';
   1045  1.19       mrg 								pos++;
   1046   1.6     lukem 							}
   1047  1.19       mrg 							if (ps.want_blank && e_code - s_code == startpos)
   1048  1.19       mrg 								*e_code++ = ' ';
   1049  1.19       mrg 							ps.want_blank = false;
   1050  1.19       mrg 						}
   1051   1.7      ross 					}
   1052   1.6     lukem 				} else {
   1053   1.6     lukem 					if (dec_ind && s_code != e_code)
   1054   1.6     lukem 						dump_line();
   1055   1.6     lukem 					dec_ind = 0;
   1056   1.6     lukem 					ps.want_blank = false;
   1057   1.6     lukem 				}
   1058   1.6     lukem 			} else
   1059   1.6     lukem 				if (sp_sw && ps.p_l_follow == 0) {
   1060   1.6     lukem 					sp_sw = false;
   1061   1.6     lukem 					force_nl = true;
   1062   1.6     lukem 					ps.last_u_d = true;
   1063   1.6     lukem 					ps.in_stmt = false;
   1064   1.6     lukem 					parse(hd_type);
   1065   1.6     lukem 				}
   1066   1.6     lukem 	copy_id:
   1067   1.6     lukem 			if (ps.want_blank)
   1068   1.6     lukem 				*e_code++ = ' ';
   1069   1.6     lukem 			if (troff && ps.its_a_keyword) {
   1070   1.6     lukem 				e_code = chfont(&bodyf, &keywordf, e_code);
   1071   1.6     lukem 				for (t_ptr = token; *t_ptr; ++t_ptr) {
   1072   1.6     lukem 					CHECK_SIZE_CODE;
   1073  1.16       dsl 					*e_code++ = keywordf.allcaps
   1074  1.16       dsl 					    ? toupper((unsigned char)*t_ptr)
   1075  1.16       dsl 					    : *t_ptr;
   1076   1.6     lukem 				}
   1077   1.6     lukem 				e_code = chfont(&keywordf, &bodyf, e_code);
   1078   1.6     lukem 			} else
   1079   1.6     lukem 				for (t_ptr = token; *t_ptr; ++t_ptr) {
   1080   1.6     lukem 					CHECK_SIZE_CODE;
   1081   1.6     lukem 					*e_code++ = *t_ptr;
   1082   1.6     lukem 				}
   1083   1.6     lukem 			ps.want_blank = true;
   1084   1.1       cgd 			break;
   1085   1.6     lukem 
   1086   1.6     lukem 		case period:	/* treat a period kind of like a binary
   1087   1.6     lukem 				 * operation */
   1088   1.6     lukem 			*e_code++ = '.';	/* move the period into line */
   1089  1.22  ginsbach 			ps.want_blank = false;	/* don't put a blank after a
   1090   1.6     lukem 						 * period */
   1091   1.1       cgd 			break;
   1092   1.6     lukem 
   1093   1.6     lukem 		case comma:
   1094   1.6     lukem 			ps.want_blank = (s_code != e_code);	/* only put blank after
   1095   1.6     lukem 								 * comma if comma does
   1096   1.6     lukem 								 * not start the line */
   1097   1.6     lukem 			if (ps.in_decl && is_procname == 0 && !ps.block_init)
   1098   1.6     lukem 				while ((e_code - s_code) < (dec_ind - 1)) {
   1099   1.6     lukem 					CHECK_SIZE_CODE;
   1100   1.6     lukem 					*e_code++ = ' ';
   1101   1.6     lukem 				}
   1102   1.6     lukem 
   1103   1.6     lukem 			*e_code++ = ',';
   1104   1.6     lukem 			if (ps.p_l_follow == 0) {
   1105   1.6     lukem 				if (ps.block_init_level <= 0)
   1106   1.6     lukem 					ps.block_init = 0;
   1107   1.6     lukem 				if (break_comma && (!ps.leave_comma || compute_code_target() + (e_code - s_code) > max_col - 8))
   1108   1.6     lukem 					force_nl = true;
   1109   1.6     lukem 			}
   1110   1.1       cgd 			break;
   1111   1.6     lukem 
   1112   1.6     lukem 		case preesc:	/* got the character '#' */
   1113   1.6     lukem 			if ((s_com != e_com) ||
   1114   1.6     lukem 			    (s_lab != e_lab) ||
   1115   1.6     lukem 			    (s_code != e_code))
   1116   1.6     lukem 				dump_line();
   1117   1.6     lukem 			*e_lab++ = '#';	/* move whole line to 'label' buffer */
   1118   1.6     lukem 			{
   1119   1.6     lukem 				int     in_comment = 0;
   1120   1.6     lukem 				int     com_start = 0;
   1121   1.6     lukem 				char    quote = 0;
   1122   1.6     lukem 				int     com_end = 0;
   1123   1.6     lukem 
   1124   1.6     lukem 				while (*buf_ptr == ' ' || *buf_ptr == '\t') {
   1125   1.6     lukem 					buf_ptr++;
   1126   1.6     lukem 					if (buf_ptr >= buf_end)
   1127   1.6     lukem 						fill_buffer();
   1128   1.6     lukem 				}
   1129   1.6     lukem 				while (*buf_ptr != '\n' || in_comment) {
   1130   1.6     lukem 					CHECK_SIZE_LAB;
   1131   1.6     lukem 					*e_lab = *buf_ptr++;
   1132   1.6     lukem 					if (buf_ptr >= buf_end)
   1133   1.6     lukem 						fill_buffer();
   1134   1.6     lukem 					switch (*e_lab++) {
   1135   1.6     lukem 					case BACKSLASH:
   1136   1.6     lukem 						if (troff)
   1137   1.6     lukem 							*e_lab++ = BACKSLASH;
   1138   1.6     lukem 						if (!in_comment) {
   1139   1.6     lukem 							*e_lab++ = *buf_ptr++;
   1140   1.6     lukem 							if (buf_ptr >= buf_end)
   1141   1.6     lukem 								fill_buffer();
   1142   1.6     lukem 						}
   1143   1.6     lukem 						break;
   1144   1.6     lukem 					case '/':
   1145   1.6     lukem 						if (*buf_ptr == '*' && !in_comment && !quote) {
   1146   1.6     lukem 							in_comment = 1;
   1147   1.6     lukem 							*e_lab++ = *buf_ptr++;
   1148   1.6     lukem 							com_start = e_lab - s_lab - 2;
   1149   1.6     lukem 						}
   1150   1.6     lukem 						break;
   1151   1.6     lukem 					case '"':
   1152   1.6     lukem 						if (quote == '"')
   1153   1.6     lukem 							quote = 0;
   1154   1.6     lukem 						break;
   1155   1.6     lukem 					case '\'':
   1156   1.6     lukem 						if (quote == '\'')
   1157   1.6     lukem 							quote = 0;
   1158   1.6     lukem 						break;
   1159   1.6     lukem 					case '*':
   1160   1.6     lukem 						if (*buf_ptr == '/' && in_comment) {
   1161   1.6     lukem 							in_comment = 0;
   1162   1.6     lukem 							*e_lab++ = *buf_ptr++;
   1163   1.6     lukem 							com_end = e_lab - s_lab;
   1164   1.6     lukem 						}
   1165   1.6     lukem 						break;
   1166   1.6     lukem 					}
   1167   1.6     lukem 				}
   1168   1.6     lukem 
   1169   1.6     lukem 				while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
   1170   1.6     lukem 					e_lab--;
   1171   1.6     lukem 				if (e_lab - s_lab == com_end && bp_save == 0) {	/* comment on
   1172   1.6     lukem 										 * preprocessor line */
   1173   1.6     lukem 					if (sc_end == 0)	/* if this is the first
   1174   1.6     lukem 								 * comment, we must set
   1175   1.6     lukem 								 * up the buffer */
   1176   1.6     lukem 						sc_end = &(save_com[0]);
   1177   1.6     lukem 					else {
   1178   1.6     lukem 						*sc_end++ = '\n';	/* add newline between
   1179   1.6     lukem 									 * comments */
   1180   1.6     lukem 						*sc_end++ = ' ';
   1181   1.6     lukem 						--line_no;
   1182   1.6     lukem 					}
   1183   1.6     lukem 					memmove(sc_end, s_lab + com_start, com_end - com_start);
   1184   1.6     lukem 					sc_end += com_end - com_start;
   1185   1.6     lukem 					if (sc_end >= &save_com[sc_size])
   1186   1.6     lukem 						abort();
   1187   1.6     lukem 					e_lab = s_lab + com_start;
   1188   1.6     lukem 					while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
   1189   1.6     lukem 						e_lab--;
   1190   1.6     lukem 					bp_save = buf_ptr;	/* save current input
   1191   1.6     lukem 								 * buffer */
   1192   1.6     lukem 					be_save = buf_end;
   1193   1.6     lukem 					buf_ptr = save_com;	/* fix so that
   1194   1.6     lukem 								 * subsequent calls to
   1195   1.6     lukem 								 * lexi will take tokens
   1196   1.6     lukem 								 * out of save_com */
   1197   1.6     lukem 					*sc_end++ = ' ';	/* add trailing blank,
   1198   1.6     lukem 								 * just in case */
   1199   1.6     lukem 					buf_end = sc_end;
   1200   1.6     lukem 					sc_end = 0;
   1201   1.6     lukem 				}
   1202   1.6     lukem 				*e_lab = '\0';	/* null terminate line */
   1203   1.6     lukem 				ps.pcase = false;
   1204   1.1       cgd 			}
   1205   1.1       cgd 
   1206   1.6     lukem 			if (strncmp(s_lab, "#if", 3) == 0) {
   1207   1.6     lukem 				if (blanklines_around_conditional_compilation) {
   1208   1.6     lukem 					int     c;
   1209   1.6     lukem 					prefix_blankline_requested++;
   1210   1.6     lukem 					while ((c = getc(input)) == '\n');
   1211   1.6     lukem 					ungetc(c, input);
   1212   1.6     lukem 				}
   1213  1.18     lukem 				if (ifdef_level < (int)(sizeof state_stack / sizeof state_stack[0])) {
   1214   1.6     lukem 					match_state[ifdef_level].tos = -1;
   1215   1.6     lukem 					state_stack[ifdef_level++] = ps;
   1216   1.6     lukem 				} else
   1217   1.6     lukem 					diag(1, "#if stack overflow");
   1218   1.6     lukem 			} else
   1219  1.10  christos 				if (strncmp(s_lab, "#else", 5) == 0) {
   1220   1.6     lukem 					if (ifdef_level <= 0)
   1221   1.6     lukem 						diag(1, "Unmatched #else");
   1222   1.6     lukem 					else {
   1223   1.6     lukem 						match_state[ifdef_level - 1] = ps;
   1224   1.6     lukem 						ps = state_stack[ifdef_level - 1];
   1225   1.6     lukem 					}
   1226  1.10  christos 				} else
   1227   1.6     lukem 					if (strncmp(s_lab, "#endif", 6) == 0) {
   1228   1.6     lukem 						if (ifdef_level <= 0)
   1229   1.6     lukem 							diag(1, "Unmatched #endif");
   1230   1.6     lukem 						else {
   1231   1.6     lukem 							ifdef_level--;
   1232   1.1       cgd 
   1233   1.1       cgd #ifdef undef
   1234   1.6     lukem 							/*
   1235   1.6     lukem 						         * This match needs to be more intelligent before the
   1236   1.6     lukem 						         * message is useful
   1237   1.6     lukem 						         */
   1238   1.6     lukem 							if (match_state[ifdef_level].tos >= 0
   1239   1.6     lukem 							    && memcmp(&ps, &match_state[ifdef_level], sizeof ps))
   1240   1.6     lukem 								diag(0, "Syntactically inconsistant #ifdef alternatives.");
   1241   1.1       cgd #endif
   1242   1.6     lukem 						}
   1243   1.6     lukem 						if (blanklines_around_conditional_compilation) {
   1244   1.6     lukem 							postfix_blankline_requested++;
   1245   1.6     lukem 							n_real_blanklines = 0;
   1246   1.6     lukem 						}
   1247   1.6     lukem 					}
   1248   1.6     lukem 			break;	/* subsequent processing of the newline
   1249   1.1       cgd 				 * character will cause the line to be printed */
   1250   1.1       cgd 
   1251   1.6     lukem 		case comment:	/* we have gotten a start comment */
   1252   1.6     lukem 			/* this is a biggie */
   1253   1.6     lukem 			if (flushed_nl) {	/* we should force a broken
   1254   1.6     lukem 						 * line here */
   1255   1.6     lukem 				flushed_nl = false;
   1256   1.6     lukem 				dump_line();
   1257  1.22  ginsbach 				ps.want_blank = false;	/* don't insert blank at
   1258   1.6     lukem 							 * line start */
   1259   1.6     lukem 				force_nl = false;
   1260   1.6     lukem 			}
   1261   1.6     lukem 			pr_comment();
   1262   1.6     lukem 			break;
   1263   1.6     lukem 		}		/* end of big switch stmt */
   1264   1.6     lukem 
   1265   1.6     lukem 		*e_code = '\0';	/* make sure code section is null terminated */
   1266   1.6     lukem 		if (type_code != comment && type_code != newline && type_code != preesc)
   1267   1.6     lukem 			ps.last_token = type_code;
   1268   1.6     lukem 	}			/* end of main while (1) loop */
   1269   1.1       cgd }
   1270   1.1       cgd /*
   1271   1.1       cgd  * copy input file to backup file if in_name is /blah/blah/blah/file, then
   1272   1.1       cgd  * backup file will be ".Bfile" then make the backup file the input and
   1273   1.1       cgd  * original input file the output
   1274   1.1       cgd  */
   1275   1.6     lukem void
   1276  1.13       wiz bakcopy(void)
   1277   1.1       cgd {
   1278   1.6     lukem 	int     n, bakchn;
   1279   1.6     lukem 	char    buff[8 * 1024];
   1280  1.18     lukem 	const char *p;
   1281   1.6     lukem 
   1282   1.6     lukem 	/* construct file name .Bfile */
   1283   1.6     lukem 	for (p = in_name; *p; p++);	/* skip to end of string */
   1284   1.6     lukem 	while (p > in_name && *p != '/')	/* find last '/' */
   1285   1.6     lukem 		p--;
   1286   1.6     lukem 	if (*p == '/')
   1287   1.6     lukem 		p++;
   1288   1.6     lukem 	sprintf(bakfile, "%s.BAK", p);
   1289   1.6     lukem 
   1290   1.6     lukem 	/* copy in_name to backup file */
   1291   1.6     lukem 	bakchn = creat(bakfile, 0600);
   1292   1.6     lukem 	if (bakchn < 0)
   1293   1.6     lukem 		err(1, "%s", bakfile);
   1294   1.6     lukem 	while ((n = read(fileno(input), buff, sizeof buff)) > 0)
   1295   1.6     lukem 		if (write(bakchn, buff, n) != n)
   1296   1.6     lukem 			err(1, "%s", bakfile);
   1297   1.6     lukem 	if (n < 0)
   1298   1.6     lukem 		err(1, "%s", in_name);
   1299   1.6     lukem 	close(bakchn);
   1300   1.6     lukem 	fclose(input);
   1301   1.6     lukem 
   1302   1.6     lukem 	/* re-open backup file as the input file */
   1303   1.6     lukem 	input = fopen(bakfile, "r");
   1304   1.6     lukem 	if (input == 0)
   1305   1.6     lukem 		err(1, "%s", bakfile);
   1306   1.6     lukem 	/* now the original input file will be the output */
   1307   1.6     lukem 	output = fopen(in_name, "w");
   1308   1.6     lukem 	if (output == 0) {
   1309   1.6     lukem 		unlink(bakfile);
   1310   1.6     lukem 		err(1, "%s", in_name);
   1311   1.6     lukem 	}
   1312   1.1       cgd }
   1313