Path: utzoo!attcan!uunet!lll-winken!ames!ucsd!nosc!cod!hall From: hall@cod.NOSC.MIL (Robert R. Hall) Newsgroups: comp.os.minix Subject: Indent (part 1 of 2) Keywords: indent pretty-print formatter Message-ID: <1461@cod.NOSC.MIL> Date: 24 Mar 89 23:58:35 GMT Organization: Naval Ocean Systems Center, San Diego Lines: 1782 Some time back I saw a request to the net, asking for a prettyprint formating program. A reply stated that INDENT source code existed in comp.unix.source and the requestor could port it to MINIX. Well here is the INDENT port to MINIX. Rename the file 'indent.pro' to '.indent.pro' and put it in the directory refecenced by $HOME. On the MINIX distrubtion disks this directory was /usr/ast but on my system I rename it. '.indent.pro' maybe edited to set you preferences. As for documentation I am reading the man pages from a UNIX system to learn this myself :-) --------------------- cut here --------------- echo x - manifest sed '/^X/s///' > manifest << '/' X49235 8176 indent/args.c X38365 1688 indent/codes.h X33572 13083 indent/comment.c X60203 11917 indent/globs.h X19811 26348 indent/indent X41777 38309 indent/indent.c X21387 46 indent/indent.pro X47849 15307 indent/io.c X29448 14398 indent/lexi.c X09668 175 indent/makefile X58464 8670 indent/parse.c / echo x - makefile sed '/^X/s///' > makefile << '/' X# makefile for the 'indent' command X XCFLAGS = -i -F X XOBJS = indent.s io.s lexi.s parse.s comment.s args.s X Xindent: ${OBJS} X $(CC) -o indent ${OBJS} X X$(OBJS): globs.h codes.h X / echo x - indent.pro sed '/^X/s///' > indent.pro << '/' X-bl -c41 -cd41 -l72 -i3 -bap -ncdb -nfc1 -nsc / echo x - codes.h sed '/^X/s///' > codes.h << '/' X/* X * Copyright (c) 1985 Sun Microsystems, Inc. X * Copyright (c) 1980 The Regents of the University of California. X * Copyright (c) 1976 Board of Trustees of the University of Illinois. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley, the University of Illinois, X * Urbana, and Sun Microsystems, Inc. The name of either University X * or Sun Microsystems may not be used to endorse or promote products X * derived from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. X * X * @(#)indent_codes.h 5.6 (Berkeley) 9/15/88 X */ X X#define newline 1 X#define lparen 2 X#define rparen 3 X#define unary_op 4 X#define binary_op 5 X#define postop 6 X#define question 7 X#define casestmt 8 X#define colon 9 X#define semicolon 10 X#define lbrace 11 X#define rbrace 12 X#define ident 13 X#define comma 14 X#define comment 15 X#define swstmt 16 X#define preesc 17 X#define form_feed 18 X#define decl 19 X#define sp_paren 20 X#define sp_nparen 21 X#define ifstmt 22 X#define whilestmt 23 X#define forstmt 24 X#define stmt 25 X#define stmtl 26 X#define elselit 27 X#define dolit 28 X#define dohead 29 X#define ifhead 30 X#define elsehead 31 X#define period 32 / echo x - globs.h sed '/^X/s///' > globs.h << '/' X/* X * Copyright (c) 1985 Sun Microsystems, Inc. X * Copyright (c) 1980 The Regents of the University of California. X * Copyright (c) 1976 Board of Trustees of the University of Illinois. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley, the University of Illinois, X * Urbana, and Sun Microsystems, Inc. The name of either University X * or Sun Microsystems may not be used to endorse or promote products X * derived from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. X * X * @(#)indent_globs.h 5.7 (Berkeley) 9/15/88 X */ X X#include X X#define BACKSLASH '\\' X#define bufsize 200 /* size of internal buffers */ X#define inp_bufs 600 /* size of input buffer */ X#define sc_size 5000 /* size of save_com buffer */ X#define label_offset 2 /* number of levels a label is X placed to left of code */ X X#define tabsize 8 /* the size of a tab */ X#define tabmask 0177770 /* mask used when figuring X length of lines with tabs */ X X X#define false 0 X#define true !false X X XPUBLIC FILE *input; /* the fid for the input file */ XPUBLIC FILE *output; /* the output file */ X XPUBLIC char *labbuf; /* buffer for label */ XPUBLIC char *s_lab; /* start ... */ XPUBLIC char *e_lab; /* .. and end of stored label */ XPUBLIC char *l_lab; /* limit of label buffer */ X XPUBLIC char *codebuf; /* buffer for code section */ XPUBLIC char *s_code; /* start ... */ XPUBLIC char *e_code; /* .. and end of stored code */ XPUBLIC char *l_code; /* limit of code section */ X XPUBLIC char *combuf; /* buffer for comments */ XPUBLIC char *s_com; /* start ... */ XPUBLIC char *e_com; /* ... and end of stored X comments */ XPUBLIC char *l_com; /* limit of comment buffer */ X XPUBLIC char in_buffer[inp_bufs]; /* input buffer */ XPUBLIC char *buf_ptr; /* ptr to next character to be X taken from in_buffer */ XPUBLIC char *buf_end; /* ptr to first after last char X in in_buffer */ X XPUBLIC char save_com[sc_size]; /* input text is saved here X when looking for the brace X after an if, while, etc */ XPUBLIC char *sc_end; /* pointer into save_com buffer */ X XPUBLIC char *bp_save; /* saved value of buf_ptr when X taking input from save_com */ XPUBLIC char *be_save; /* similarly saved value of X buf_end */ X XPUBLIC char token[bufsize]; /* the last token scanned */ X X XPUBLIC int ptr_binop; /* pointer as binop */ XPUBLIC int bl_aft_decl; /* blanklines after X declarations */ XPUBLIC int bl_bef_bk; /* blanklines before X blockcomments */ XPUBLIC int bl_a_procs; /* blanklines after procs */ XPUBLIC int bl_around; /* blanklines around X conditional compilation */ XPUBLIC int swallow_opt_bl; /* swallow optional blanklines */ XPUBLIC int n_real_blanklines; XPUBLIC int prefix_blankline_requested; XPUBLIC int postfix_blankline_requested; XPUBLIC int break_comma; /* when true and not in parens, X break after a comma */ XPUBLIC int btype_2; /* when true, brace should be X on same line as if, while, X etc */ XPUBLIC long case_ind; /* indentation level to be used X for a "case n:" */ XPUBLIC int code_lines; /* count of lines with code */ XPUBLIC int had_eof; /* set to true when input is X exhausted */ XPUBLIC int line_no; /* the current line number. */ XPUBLIC int max_col; /* the maximum allowable line X length */ XPUBLIC int verbose; /* when true, non-essential X error messages are printed */ XPUBLIC int cuddle_else; /* true if else should cuddle X up to '}' */ XPUBLIC int star_comment_cont; /* true iff comment X continuation lines should X have stars at the beginning X of each line. */ XPUBLIC int del_on_bl; /* comment_delimiter_on_blanklin X e */ XPUBLIC int troff; /* true iff were generating X troff input */ XPUBLIC int proc_str_line; /* if true, the names of X procedures being defined get X placed in column 1 (ie. a X newline is placed between X the type of the procedure X and its name) */ XPUBLIC int proc_calls_space; /* If true, procedure calls X look like: foo(bar) rather X than foo (bar) */ XPUBLIC int format_col1_comments; /* If comments which start in X column 1 are to be magically X reformatted (just like X comments that begin in later X columns) */ XPUBLIC int inhibit_formatting; /* true if INDENT OFF is in X effect */ XPUBLIC int suppress_blanklines; /* set iff following blanklines X should be suppressed */ XPUBLIC int continuation_indent; /* set to the indentation X between the edge of code and X continuation lines */ XPUBLIC int lineup_to_parens; /* if true, continued code X within parens will be lined X up to the open paren */ XPUBLIC int Bill_Shannon; /* true iff a blank should X always be inserted after X sizeof */ XPUBLIC int bl_at_proctop; /* This is vaguely similar to X blanklines_after_declarations X except that it only applies X to the first set of X declarations in a procedure X (just after the first '{') X and it causes a blank line X to be generated even if X there are no declarations */ XPUBLIC int bk_max_col; XPUBLIC int ex_expr_indent; /* True if continuation lines X from the expression part of X "if(e)", "while(e)", X "for(e;e;e)" should be X indented an extra tab stop X so that they don't conflict X with the code that follows */ X X/* -troff font state information */ X Xstruct fstate X{ X char font[4]; X char size; X int allcaps; X}; Xchar *chfont(); X XPUBLIC struct fstate X keywordf, /* keyword font */ X stringf, /* string font */ X boxcomf, /* Box comment font */ X blkcomf, /* Block comment font */ X scomf, /* Same line comment font */ X bodyf; /* major body font */ X X X#define STACKSIZE 150 X XPUBLIC struct parser_state X{ X int last_token; X struct fstate cfont; /* Current font */ X int p_stack[STACKSIZE]; /* this is the parsers stack */ X int il[STACKSIZE]; /* this stack stores X indentation levels */ X long cstk[STACKSIZE]; /* used to store case stmt X indentation levels */ X int box_com; /* set to true when we are in a X "boxed" comment. In that X case, the first non-blank X char should be lined up with X the / in /* */ X int comment_delta, n_comment_delta; X int cast_mask; /* indicates which close parens X close off casts */ X int sizeof_mask; /* indicates which close parens X close off sizeof''s */ X int block_init; /* true iff inside a block X initialization */ X int block_init_level; /* The level of brace nesting X in an initialization */ X int last_nl; /* this is true if the last X thing scanned was a newline */ X int in_or_st; /* Will be true iff there has X been a declarator (e.g. int X or char) and no left paren X since the last semicolon. X When true, a '{' is starting X a structure definition or an X initialization list */ X int bl_line; /* set to 1 by dump_line if the X line is blank */ X int col_1; /* set to true if the last X token started in column 1 */ X int com_col; /* this is the column in which X the current coment should X start */ X int com_ind; /* the column in which comments X to the right of code should X start */ X int com_lines; /* the number of lines with X comments, set by dump_line */ X int dec_nest; /* current nesting level for X structure or init */ X int decl_com_ind; /* the column in which comments X after declarations should be X put */ X int decl_on_line; /* set to true if this line of X code has part of a X declaration on it */ X int i_l_follow; /* the level to which ind_level X should be set after the X current line is printed */ X int in_decl; /* set to true when we are in a X declaration stmt. The X processing of braces is then X slightly different */ X int in_stmt; /* set to 1 while in a stmt */ X int ind_level; /* the current indentation X level */ X int ind_size; /* the size of one indentation X level */ X int ind_stmt; /* set to 1 if next line should X have an extra indentation X level because we are in the X middle of a stmt */ X int last_u_d; /* set to true after scanning a X token which forces a X following operator to be X unary */ X int leave_comma; /* if true, never break X declarations after commas */ X int ljust_decl; /* true if declarations should X be left justified */ X int out_coms; /* the number of comments X processed, set by pr_comment */ X int out_lines; /* the number of lines written, X set by dump_line */ X int p_l_follow; /* used to remember how to X indent following statement */ X int paren_level; /* parenthesization level. used X to indent within stmts */ X short paren_indents[20]; /* column positions of each X paren */ X int pcase; /* set to 1 if the current line X label is a case. It is X printed differently from a X regular label */ X int search_brace; /* set to true by parse when it X is necessary to buffer up X all info up to the start of X a stmt after an if, while, X etc */ X int unindent_displace; /* comments not to the right of X code will be placed this X many indentation levels to X the left of code */ X int use_ff; /* set to one if the current X line should be terminated X with a form feed */ X int want_blank; /* set to true when the X following token should be X prefixed by a blank. (Said X prefixing is ignored in some X cases.) */ X int else_if; /* True iff else if pairs X should be handled specially */ X int decl_indent; /* column to indent declared X identifiers to */ X int its_a_keyword; X int sizeof_keyword; X int dumped_decl_indent; X long case_indent; /* The distance to indent case X labels from the switch X statement */ X int in_par_decl; X int indent_parameters; X int tos; /* pointer to top of stack */ X char procname[100]; /* The name of the current X procedure */ X int just_saw_decl; X} ps; X XPUBLIC int ifdef_level; XPUBLIC struct parser_state state_stack[5]; XPUBLIC struct parser_state match_state[5]; / echo x - indent.c sed '/^X/s///' > indent.c << '/' X/* X * Copyright (c) 1985 Sun Microsystems, Inc. X * Copyright (c) 1980 The Regents of the University of California. X * Copyright (c) 1976 Board of Trustees of the University of Illinois. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley, the University of Illinois, X * Urbana, and Sun Microsystems, Inc. The name of either University X * or Sun Microsystems may not be used to endorse or promote products X * derived from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#ifndef lint Xchar copyright[] = X"@(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\ X @(#) Copyright (c) 1980 The Regents of the University of California.\n\ X @(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\ XAll rights reserved.\ n "; X#endif /* not lint */ X X#ifndef lint Xstatic char sccsid[] = "@(#)indent.c 5.11 (Berkeley) 9/15/88"; X#endif /* not lint */ X X#define PUBLIC X#include "globs.h" X#include "codes.h" X#include X Xchar *in_name = "Standard Input"; /* will always point to X name of input file */ Xchar *out_name = "Standard Output"; /* will always point to X name of output file */ Xchar bakfile[60] = ""; X Xmain(argc, argv) X int argc; X char **argv; X{ X X extern int found_err; /* flag set in diag() on error */ X int dec_ind; /* current indentation for X declarations */ X int di_stack[20]; /* a stack of structure X indentation levels */ X int flushed_nl; /* used when buffering up X comments to remember that a X newline was passed over */ X int force_nl; /* when true, code must be X broken */ X int hd_type; /* used to store type of stmt X for if (...), for (...), etc */ X register int i; /* local loop counter */ X int scase; /* set to true when we see a X case, so we will know what X to do with the following X colon */ X int sp_sw; /* when true, we are in the X expressin of if(...), X while(...), etc. */ X int squest; /* when this is positive, we X have seen a ? without the X matching : in a ?: X construct */ X register char *t_ptr; /* used for copying tokens */ X int type_code; /* the type of token, returned X by lexi */ X X int last_else = 0; /* true iff last keyword was an X else */ X X X /*-----------------------------------------------*\ X | INITIALIZATION | X \*-----------------------------------------------*/ X X X ps.p_stack[0] = stmt; /* this is the parser's stack */ X ps.last_nl = true; /* this is true if the last X thing scanned was a newline */ X ps.last_token = semicolon; X combuf = (char *) malloc(bufsize); X labbuf = (char *) malloc(bufsize); X codebuf = (char *) malloc(bufsize); X l_com = combuf + bufsize - 5; X l_lab = labbuf + bufsize - 5; X l_code = codebuf + bufsize - 5; X combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, X and comment buffers */ X combuf[1] = codebuf[1] = labbuf[1] = '\0'; X ps.else_if = 1; /* Default else-if special X processing to on */ X s_lab = e_lab = labbuf + 1; X s_code = e_code = codebuf + 1; X s_com = e_com = combuf + 1; X X buf_ptr = buf_end = in_buffer; X line_no = 1; X had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; X sp_sw = force_nl = false; X ps.in_or_st = false; X ps.bl_line = true; X dec_ind = 0; X di_stack[ps.dec_nest = 0] = 0; X ps.want_blank = ps.in_stmt = ps.ind_stmt = false; X X X scase = ps.pcase = false; X squest = 0; X sc_end = 0; X bp_save = 0; X be_save = 0; X X output = 0; X X X X /*--------------------------------------------------*\ X | COMMAND LINE SCAN | X \*--------------------------------------------------*/ X X#ifdef undef X max_col = 78; /* -l78 */ X lineup_to_parens = 1; /* -lp */ X ps.ljust_decl = 0; /* -ndj */ X ps.com_ind = 33; /* -c33 */ X star_comment_cont = 1; /* -sc */ X ps.ind_size = 8; /* -i8 */ X verbose = 0; X ps.decl_indent = 16; /* -di16 */ X ps.indent_parameters = 1; /* -ip */ X ps.decl_com_ind = 0; /* if this is not set to some X positive value by an arg, we X will set this equal to X ps.com_ind */ X btype_2 = 1; /* -br */ X cuddle_else = 1; /* -ce */ X ps.unindent_displace = 0; /* -d0 */ X ps.case_indent = 0; /* -cli0 */ X format_col1_comments = 1; /* -fc1 */ X procnames_start_line = 1; /* -psl */ X proc_calls_space = 0; /* -npcs */ X comment_delimiter_on_blankline = 1; /* -cdb */ X ps.leave_comma = 1; /* -nbc */ X#endif X X for (i = 1; i < argc; ++i) X if (strcmp(argv[i], "-npro") == 0) X break; X set_defaults(); X if (i >= argc) X set_profile(); X X for (i = 1; i < argc; ++i) X { X X /* look thru args (if any) for changes to defaults */ X if (argv[i][0] != '-') X { /* no flag on parameter */ X if (input == 0) X { /* we must have the input file */ X in_name = argv[i]; /* remember name of input file */ X input = fopen(in_name, "r"); X if (input == 0) X { /* check for open error */ X fprintf(stderr, "indent: can't open %s\n", argv[i]); X exit(1); X } X continue; X } else if (output == 0) X { /* we have the output file */ X out_name = argv[i]; /* remember name of output file */ X if (strcmp(in_name, out_name) == 0) X { /* attempt to overwrite the X file */ X fprintf(stderr, "indent: input and output files must be different\n"); X exit(1); X } X output = fopen(out_name, "w"); X if (output == 0) X { /* check for create error */ X fprintf(stderr, "indent: can't create %s\n", argv[i]); X exit(1); X } X continue; X } X fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]); X exit(1); X } else X set_option(argv[i]); X } /* end of for */ X if (input == 0) X { X fprintf(stderr, "indent: usage: indent file [ outfile ] [ options ]\n"); X exit(1); X } X if (output == 0) X if (troff) X output = stdout; X else X { X out_name = in_name; X bakcopy(); X } X if (ps.com_ind <= 1) X ps.com_ind = 2; /* dont put normal comments X before column 2 */ X if (troff) X { X if (bodyf.font[0] == 0) X parsefont(&bodyf, "R"); X if (scomf.font[0] == 0) X parsefont(&scomf, "I"); X if (blkcomf.font[0] == 0) X blkcomf = scomf, blkcomf.size += 2; X if (boxcomf.font[0] == 0) X boxcomf = blkcomf; X if (stringf.font[0] == 0) X parsefont(&stringf, "L"); X if (keywordf.font[0] == 0) X parsefont(&keywordf, "B"); X writefdef(&bodyf, 'B'); X writefdef(&scomf, 'C'); X writefdef(&blkcomf, 'L'); X writefdef(&boxcomf, 'X'); X writefdef(&stringf, 'S'); X writefdef(&keywordf, 'K'); X } X if (bk_max_col <= 0) X bk_max_col = max_col; X if (ps.decl_com_ind <= 0) /* if not specified by user, X set this */ X ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; X if (continuation_indent == 0) X continuation_indent = ps.ind_size; X fill_buffer(); /* get first batch of stuff X into input buffer */ X X parse(semicolon); X { X register char *p = buf_ptr; X register col = 1; X X while (1) X { X if (*p == ' ') X col++; X else if (*p == '\t') X col = ((col - 1) & ~7) + 9; X else X break; X p++; X }; X if (col > ps.ind_size) X ps.ind_level = ps.i_l_follow = col / ps.ind_size; X } X if (troff) X { X register char *p = in_name, *beg = in_name; X X while (*p) X if (*p++ == '/') X beg = p; X fprintf(output, ".Fn \"%s\"\n", beg); X } X /* START OF MAIN LOOP */ X X while (1) X { /* this is the main loop. it X will go until we reach eof */ X int is_procname; X X type_code = lexi(); /* lexi reads one token. The X actual characters read are X stored in "token". lexi X returns a code indicating X the type of token */ X is_procname = ps.procname[0]; X X /* The following code moves everything following an if (), while X (), else, etc. up to the start of the following stmt to a X buffer. This allows proper handling of both kinds of brace X placement. */ X X flushed_nl = false; X while (ps.search_brace) X { /* if we scanned an if(), X while(), etc., we might need X to copy stuff into a buffer X we must loop, copying stuff X into save_com, until we find X the start of the stmt which X follows the if, or whatever */ X switch (type_code) X { X case newline: X ++line_no; X flushed_nl = true; X case form_feed: X break; /* form feeds and newlines X found here will be ignored */ X X case lbrace: /* this is a brace that starts X the compound stmt */ X if (sc_end == 0) X { /* ignore buffering if a X comment wasnt stored up */ X ps.search_brace = false; X goto check_type; X } X if (btype_2) X { X save_com[0] = '{'; /* we either want to put the X brace right after the if */ X goto sw_buffer; /* go to common code to get out X of this loop */ X } X case comment: /* we have a comment, so we X must copy it into the buffer */ X if (!flushed_nl || sc_end != 0) X { X if (sc_end == 0) X { /* if this is the first X comment, we must set up the X buffer */ X save_com[0] = save_com[1] = ' '; X sc_end = &(save_com[2]); X } else X { X *sc_end++ = '\n'; /* add newline between comments */ X *sc_end++ = ' '; X --line_no; X } X *sc_end++ = '/'; /* copy in start of comment */ X *sc_end++ = '*'; X X for (;;) X { /* loop until we get to the end X of the comment */ X *sc_end = *buf_ptr++; X if (buf_ptr >= buf_end) X fill_buffer(); X X if (*sc_end++ == '*' && *buf_ptr == '/') X break; /* we are at end of comment */ X X if (sc_end >= &(save_com[sc_size])) X { /* check for temp buffer X overflow */ X diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever."); X fflush(output); X exit(1); X } X } X *sc_end++ = '/'; /* add ending slash */ X if (++buf_ptr >= buf_end)/* get past / in buffer */ X fill_buffer(); X break; X } X default: /* it is the start of a normal X statment */ X if (flushed_nl) /* if we flushed a newline, X make sure it is put back */ X force_nl = true; X if (type_code == sp_paren && *token == 'i' X && last_else && ps.else_if X || type_code == sp_nparen && *token == 'e' X && e_code != s_code && e_code[-1] == '}') X force_nl = false; X X if (sc_end == 0) X { /* ignore buffering if comment X wasnt saved up */ X ps.search_brace = false; X goto check_type; X } X if (force_nl) X { /* if we should insert a nl X here, put it into the buffer */ X force_nl = false; X --line_no; /* this will be re-increased X when the nl is read from the X buffer */ X *sc_end++ = '\n'; X *sc_end++ = ' '; X if (verbose && !flushed_nl) /* print error msg if X the line was not X already broken */ X diag(0, "Line broken"); X flushed_nl = false; X } X for (t_ptr = token; *t_ptr; ++t_ptr) X *sc_end++ = *t_ptr; /* copy token into temp buffer */ X ps.procname[0] = 0; X X sw_buffer: X ps.search_brace = false; /* stop looking for start of X stmt */ X bp_save = buf_ptr; /* save current input buffer */ X be_save = buf_end; X buf_ptr = save_com; /* fix so that subsequent calls X to lexi will take tokens out X of save_com */ X *sc_end++ = ' '; /* add trailing blank, just in X case */ X buf_end = sc_end; X sc_end = 0; X break; X } /* end of switch */ X if (type_code != 0) /* we must make this check, X just in case there was an X unexpected EOF */ X type_code = lexi(); /* read another token */ X /* if (ps.search_brace) ps.procname[0] = 0; */ X if ((is_procname = ps.procname[0]) && flushed_nl X && !proc_str_line && ps.in_decl X && type_code == ident) X flushed_nl = 0; X } /* end of while (search_brace) */ X last_else = 0; Xcheck_type: X if (type_code == 0) X { /* we got eof */ X if (s_lab != e_lab || s_code != e_code X || s_com != e_com) /* must dump end of line */ X dump_line(); X if (ps.tos > 1) /* check for balanced braces */ X diag(1, "Stuff missing from end of file."); X X if (verbose) X { X printf("There were %d output lines and %d comments\n", X ps.out_lines, ps.out_coms); X printf("(Lines with comments)/(Lines with code): %6d\n", X ps.com_lines / code_lines); X } X fflush(output); X exit(found_err); X } X if ( X (type_code != comment) && X (type_code != newline) && X (type_code != preesc) && X (type_code != form_feed)) X { X if (force_nl && X (type_code != semicolon) && X (type_code != lbrace || !btype_2)) X { X /* we should force a broken line here */ X if (verbose && !flushed_nl) X diag(0, "Line broken"); X flushed_nl = false; X dump_line(); X ps.want_blank = false; /* dont insert blank at line X start */ X force_nl = false; X } X ps.in_stmt = true; /* turn on flag which causes an X extra level of indentation. X this is turned off by a ; or X '}' */ X if (s_com != e_com) X { /* the turkey has embedded a X comment in a line. fix it */ X *e_code++ = ' '; X for (t_ptr = s_com; *t_ptr; ++t_ptr) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = *t_ptr; X } X *e_code++ = ' '; X *e_code = '\0'; /* null terminate code sect */ X ps.want_blank = false; X e_com = s_com; X } X } else if (type_code != comment) /* preserve force_nl thru a X comment */ X force_nl = false; /* cancel forced newline after X newline, form feed, etc */ X X X X /*-----------------------------------------------------*\ X | do switch on type of token scanned | X \*-----------------------------------------------------*/ X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X switch (type_code) X { /* now, decide what to do with X the token */ X X case form_feed: /* found a form feed in line */ X ps.use_ff = true; /* a form feed is treated much X like a newline */ X dump_line(); X ps.want_blank = false; X break; X X case newline: X if (ps.last_token != comma || ps.p_l_follow > 0 X || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) X { X dump_line(); X ps.want_blank = false; X } X ++line_no; /* keep track of input line X number */ X break; X X case lparen: /* got a '(' or '[' */ X ++ps.p_l_follow; /* count parens to make Healy X happy */ X if (ps.want_blank && *token != '[' && X (ps.last_token != ident || proc_calls_space X || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon)))) X *e_code++ = ' '; X if (ps.in_decl && !ps.block_init) X if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) X { X ps.dumped_decl_indent = 1; X sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); X e_code += strlen(e_code); X } else X { X while ((e_code - s_code) < dec_ind) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = ' '; X } X *e_code++ = token[0]; X } X else X *e_code++ = token[0]; X ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; X if (sp_sw && ps.p_l_follow == 1 && ex_expr_indent X && ps.paren_indents[0] < 2 * ps.ind_size) X ps.paren_indents[0] = 2 * ps.ind_size; X ps.want_blank = false; X if (ps.in_or_st && *token == '(' && ps.tos <= 2) X { X /* this is a kluge to make sure that declarations will be X aligned right if proc decl has an explicit type on it, X i.e. "int a(x) {..." */ X parse(semicolon); /* I said this was a kluge... */ X ps.in_or_st = false; /* turn off flag for structure X decl or initialization */ X } X if (ps.sizeof_keyword) X ps.sizeof_mask |= 1 << ps.p_l_follow; X break; X X case rparen: /* got a ')' or ']' */ X if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) X { X ps.last_u_d = true; X ps.cast_mask &= (1 << ps.p_l_follow) - 1; X } X ps.sizeof_mask &= (1 << ps.p_l_follow) - 1; X if (--ps.p_l_follow < 0) X { X ps.p_l_follow = 0; X diag(0, "Extra %c", *token); X } X if (e_code == s_code) /* if the paren starts the line */ X ps.paren_level = ps.p_l_follow; /* then indent it */ X X *e_code++ = token[0]; X ps.want_blank = true; X X if (sp_sw && (ps.p_l_follow == 0)) X { /* check for end of if (...), X or some such */ X sp_sw = false; X force_nl = true; /* must force newline after if */ X ps.last_u_d = true; /* inform lexi that a following X operator is unary */ X ps.in_stmt = false; /* dont use stmt continuation X indentation */ X X parse(hd_type); /* let parser worry about if, X or whatever */ X } X ps.search_brace = btype_2; /* this should insure that X constructs such as X main(){...} and int[]{...} X have their braces put in the X right place */ X break; X X case unary_op: /* this could be any unary X operation */ X if (ps.want_blank) X *e_code++ = ' '; X X if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) X { X sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); X ps.dumped_decl_indent = 1; X e_code += strlen(e_code); X } else X { X char *res = token; X X if (ps.in_decl && !ps.block_init) X { /* if this is a unary op in a X declaration, we should X indent this token */ X for (i = 0; token[i]; ++i); /* find length of token */ X while ((e_code - s_code) < (dec_ind - i)) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = ' '; /* pad it */ X } X } X if (troff && token[0] == '-' && token[1] == '>') X res = "\\(->"; X for (t_ptr = res; *t_ptr; ++t_ptr) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = *t_ptr; X } X } X ps.want_blank = false; X break; X X case binary_op: /* any binary operation */ X do_binary: X if (ps.want_blank) X *e_code++ = ' '; X { X char *res = token; X X if (troff) X switch (token[0]) X { X case '<': X if (token[1] == '=') X res = "\\(<="; X break; X case '>': X if (token[1] == '=') X res = "\\(>="; X break; X case '!': X if (token[1] == '=') X res = "\\(!="; X break; X case '|': X if (token[1] == '|') X res = "\\(br\\(br"; X else if (token[1] == 0) X res = "\\(br"; X break; X } X for (t_ptr = res; *t_ptr; ++t_ptr) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = *t_ptr; /* move the operator */ X } X } X ps.want_blank = true; X break; X X case postop: /* got a trailing ++ or -- */ X *e_code++ = token[0]; X *e_code++ = token[1]; X ps.want_blank = true; X break; X X case question: /* got a ? */ X squest++; /* this will be used when a X later colon appears so we X can distinguish the X ?: construct */ X if (ps.want_blank) X *e_code++ = ' '; X *e_code++ = '?'; X ps.want_blank = true; X break; X X case casestmt: /* got word 'case' or 'default' */ X scase = true; /* so we can process the later X colon properly */ X goto copy_id; X X case colon: /* got a ':' */ X if (squest > 0) X { /* it is part of the ?: X construct */ X --squest; X if (ps.want_blank) X *e_code++ = ' '; X *e_code++ = ':'; X ps.want_blank = true; X break; X } X if (ps.in_decl) X { X *e_code++ = ':'; X ps.want_blank = false; X break; X } X ps.in_stmt = false; /* seeing a label does not X imply we are in a stmt */ X for (t_ptr = s_code; *t_ptr; ++t_ptr) X *e_lab++ = *t_ptr; /* turn everything so far into X a label */ X e_code = s_code; X *e_lab++ = ':'; X *e_lab++ = ' '; X *e_lab = '\0'; X X force_nl = ps.pcase = scase; /* ps.pcase will be used by X dump_line to decide how to X indent the label. force_nl X will force a case n: to be X on a line by itself */ X scase = false; X ps.want_blank = false; X break; X X case semicolon: /* got a ';' */ X ps.in_or_st = false; /* we are not in an X initialization or structure X declaration */ X scase = false; /* these will only need X resetting in a error */ X squest = 0; X if (ps.last_token == rparen) X ps.in_par_decl = 0; X ps.cast_mask = 0; X ps.sizeof_mask = 0; X ps.block_init = 0; X ps.block_init_level = 0; X ps.just_saw_decl--; X X if (ps.in_decl && s_code == e_code && !ps.block_init) X while ((e_code - s_code) < (dec_ind - 1)) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = ' '; X } X X ps.in_decl = (ps.dec_nest > 0);/* if we were in a first level X structure declaration, we X arent any more */ X X if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) X { X X /* This should be true iff there were unbalanced parens in X the stmt. It is a bit complicated, because the X semicolon might be in a for stmt */ X diag(1, "Unbalanced parens"); X ps.p_l_follow = 0; X if (sp_sw) X { /* this is a check for a if, X while, etc. with unbalanced X parens */ X sp_sw = false; X parse(hd_type); /* dont lose the if, or X whatever */ X } X } X *e_code++ = ';'; X ps.want_blank = true; X ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in X the middle of a stmt */ X X if (!sp_sw) X { /* if not if for (;;) */ X parse(semicolon); /* let parser know about end of X stmt */ X force_nl = true; /* force newline after a end of X stmt */ X } X break; X X case lbrace: /* got a '{' */ X ps.in_stmt = false; /* dont indent the {} */ X if (!ps.block_init) X force_nl = true; /* force other stuff on same X line as '{' onto new line */ X else if (ps.block_init_level <= 0) X ps.block_init_level = 1; X else X ps.block_init_level++; X X if (s_code != e_code && !ps.block_init) X { X if (!btype_2) X { X dump_line(); X ps.want_blank = false; X } else if (ps.in_par_decl && !ps.in_or_st) X { X ps.i_l_follow = 0; X dump_line(); X ps.want_blank = false; X } X } X if (ps.in_par_decl) X prefix_blankline_requested = 0; X X if (ps.p_l_follow > 0) X { /* check for preceeding X unbalanced parens */ X diag(1, "Unbalanced parens"); X ps.p_l_follow = 0; X if (sp_sw) X { /* check for unclosed if, for, X etc. */ X sp_sw = false; X parse(hd_type); X ps.ind_level = ps.i_l_follow; X } X } X if (s_code == e_code) X ps.ind_stmt = false; /* dont put extra indentation X on line with '{' */ X if (ps.in_decl && ps.in_or_st) X { /* this is either a structure X declaration or an init */ X di_stack[ps.dec_nest++] = dec_ind; X /* ? dec_ind = 0; */ X } else X { X ps.decl_on_line = false; /* we cant be in the middle of X a declaration, so dont do X special indentation of X comments */ X if (bl_at_proctop X && ps.in_par_decl) X postfix_blankline_requested = 1; X ps.in_par_decl = 0; X } X dec_ind = 0; X parse(lbrace); /* let parser know about this */ X if (ps.want_blank) /* put a blank before '{' if X '{' is not at start of line */ X *e_code++ = ' '; X ps.want_blank = false; X *e_code++ = '{'; X ps.just_saw_decl = 0; X break; X X case rbrace: /* got a '}' */ X if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be X omitted in X declarations */ X parse(semicolon); X if (ps.p_l_follow) X { /* check for unclosed if, for, X else. */ X diag(1, "Unbalanced parens"); X ps.p_l_follow = 0; X sp_sw = false; X } X ps.just_saw_decl = 0; X ps.block_init_level--; X if (s_code != e_code && !ps.block_init) X { /* '}' must be first on line */ X if (verbose) X diag(0, "Line broken"); X dump_line(); X } X *e_code++ = '}'; X ps.want_blank = true; X ps.in_stmt = ps.ind_stmt = false; X if (ps.dec_nest > 0) X { /* we are in multi-level X structure declaration */ X dec_ind = di_stack[--ps.dec_nest]; X if (ps.dec_nest == 0 && !ps.in_par_decl) X ps.just_saw_decl = 2; X ps.in_decl = true; X } X prefix_blankline_requested = 0; X parse(rbrace); /* let parser know about this */ X ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead X && ps.il[ps.tos] >= ps.ind_level; X if (ps.tos <= 1 && bl_a_procs && ps.dec_nest <= 0) X postfix_blankline_requested = 1; X break; X X case swstmt: /* got keyword "switch" */ X sp_sw = true; X hd_type = swstmt; /* keep this for when we have X seen the expression */ X goto copy_id; /* go move the token into X buffer */ X X case sp_paren: /* token is if, while, for */ X sp_sw = true; /* the interesting stuff is X done after the expression is X scanned */ X hd_type = (*token == 'i' ? ifstmt : X (*token == 'w' ? whilestmt : forstmt)); X X /* remember the type of header for later use by parser */ X goto copy_id; /* copy the token into line */ X X case sp_nparen: /* got else, do */ X ps.in_stmt = false; X if (*token == 'e') X { X if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) X { X if (verbose) X diag(0, "Line broken"); X dump_line(); /* make sure this starts a line */ X ps.want_blank = false; X } X force_nl = true; /* also, following stuff must X go onto new line */ X last_else = 1; X parse(elselit); X } else X { X if (e_code != s_code) X { /* make sure this starts a line */ X if (verbose) X diag(0, "Line broken"); X dump_line(); X ps.want_blank = false; X } X force_nl = true; /* also, following stuff must X go onto new line */ X last_else = 0; X parse(dolit); X } X goto copy_id; /* move the token into line */ X X case decl: /* we have a declaration type X (int, register, etc.) */ X parse(decl); /* let parser worry about X indentation */ X if (ps.last_token == rparen && ps.tos <= 1) X { X ps.in_par_decl = 1; X if (s_code != e_code) X { X dump_line(); X ps.want_blank = 0; X } X } X if (ps.in_par_decl && ps.indent_parameters && ps.dec_nest == 0) X { X ps.ind_level = ps.i_l_follow = 1; X ps.ind_stmt = 0; X } X ps.in_or_st = true; /* this might be a structure or X initialization declaration */ X ps.in_decl = ps.decl_on_line = true; X if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) X ps.just_saw_decl = 2; X prefix_blankline_requested = 0; X for (i = 0; token[i++];); /* get length of token */ X X /* dec_ind = e_code - s_code + (ps.decl_indent>i ? X ps.decl_indent : i); */ X dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; X goto copy_id; X X case ident: /* got an identifier or X constant */ X if (ps.in_decl) X { /* if we are in a declaration, X we must indent identifier */ X if (ps.want_blank) X *e_code++ = ' '; X ps.want_blank = false; X if (is_procname == 0 || !proc_str_line) X { X if (!ps.block_init) X if (troff && !ps.dumped_decl_indent) X { X sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7); X ps.dumped_decl_indent = 1; X e_code += strlen(e_code); X } else X while ((e_code - s_code) < dec_ind) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = ' '; X } X } else X { X if (dec_ind && s_code != e_code) X dump_line(); X dec_ind = 0; X ps.want_blank = false; X } X } else if (sp_sw && ps.p_l_follow == 0) X { X sp_sw = false; X force_nl = true; X ps.last_u_d = true; X ps.in_stmt = false; X parse(hd_type); X } X copy_id: X if (ps.want_blank) X *e_code++ = ' '; X if (troff && ps.its_a_keyword) X { X e_code = chfont(&bodyf, &keywordf, e_code); X for (t_ptr = token; *t_ptr; ++t_ptr) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = keywordf.allcaps && islower(*t_ptr) X ? toupper(*t_ptr) : *t_ptr; X } X e_code = chfont(&keywordf, &bodyf, e_code); X } else X for (t_ptr = token; *t_ptr; ++t_ptr) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = *t_ptr; X } X ps.want_blank = true; X break; X X case period: /* treat a period kind of like X a binary operation */ X *e_code++ = '.'; /* move the period into line */ X ps.want_blank = false; /* dont put a blank after a X period */ X break; X X case comma: X ps.want_blank = (s_code != e_code); /* only put blank after X comma if comma does X not start the line */ X if (ps.in_decl && is_procname == 0 && !ps.block_init) X while ((e_code - s_code) < (dec_ind - 1)) X { X if (e_code >= l_code) X { X register nsize = l_code - s_code + 400; X codebuf = (char *) realloc(codebuf, nsize); X e_code = codebuf + (e_code - s_code) + 1; X l_code = codebuf + nsize - 5; X s_code = codebuf + 1; X } X *e_code++ = ' '; X } X X *e_code++ = ','; X if (ps.p_l_follow == 0) X { X if (ps.block_init_level <= 0) X ps.block_init = 0; X if (break_comma && !ps.leave_comma) X force_nl = true; X } X break; X X case preesc: /* got the character '#' */ X if ((s_com != e_com) || X (s_lab != e_lab) || X (s_code != e_code)) X dump_line(); X *e_lab++ = '#'; /* move whole line to 'label' X buffer */ X { X int in_comment = 0; X int com_start = 0; X char quote = 0; X int com_end = 0; X X while (*buf_ptr != '\n' || in_comment) X { X if (e_lab >= l_lab) X { X register nsize = l_lab - s_lab + 400; X labbuf = (char *) realloc(labbuf, nsize); X e_lab = labbuf + (e_lab - s_lab) + 1; X l_lab = labbuf + nsize - 5; X s_lab = labbuf + 1; X } X *e_lab = *buf_ptr++; X if (buf_ptr >= buf_end) X fill_buffer(); X switch (*e_lab++) X { X case BACKSLASH: X if (troff) X *e_lab++ = BACKSLASH; X if (!in_comment) X { X *e_lab++ = *buf_ptr++; X if (buf_ptr >= buf_end) X fill_buffer(); X } X break; X case '/': X if (*buf_ptr == '*' && !in_comment && !quote) X { X in_comment = 1; X *e_lab++ = *buf_ptr++; X com_start = e_lab - s_lab - 2; X } X break; X case '"': X if (quote == '"') X quote = 0; X break; X case '\'': X if (quote == '\'') X quote = 0; X break; X case '*': X if (*buf_ptr == '/' && in_comment) X { X in_comment = 0; X *e_lab++ = *buf_ptr++; X com_end = e_lab - s_lab; X } X break; X } X } X X while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) X e_lab--; X if (e_lab - s_lab == com_end && bp_save == 0) X { /* comment on preprocessor line */ X if (sc_end == 0) /* if this is the first X comment, we must set up the X buffer */ X sc_end = &(save_com[0]); X else X { X *sc_end++ = '\n'; /* add newline between comments */ X *sc_end++ = ' '; X --line_no; X } X bcopy(s_lab + com_start, sc_end, com_end - com_start); X sc_end += com_end - com_start; X if (sc_end >= &save_com[sc_size]) X abort(); X e_lab = s_lab + com_start; X while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) X e_lab--; X bp_save = buf_ptr; /* save current input buffer */ X be_save = buf_end; X buf_ptr = save_com; /* fix so that subsequent calls X to lexi will take tokens out X of save_com */ X *sc_end++ = ' '; /* add trailing blank, just in X case */ X buf_end = sc_end; X sc_end = 0; X } X *e_lab = '\0'; /* null terminate line */ X ps.pcase = false; X } X X if (strncmp(s_lab, "#if", 3) == 0) X { X if (bl_around) X { X register c; X prefix_blankline_requested++; X while ((c = getc(input)) == '\n'); X ungetc(c, input); X } X if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) X { X match_state[ifdef_level].tos = -1; X state_stack[ifdef_level++] = ps; X } else X diag(1, "#if stack overflow"); X } else if (strncmp(s_lab, "#else", 5) == 0) X if (ifdef_level <= 0) X diag(1, "Unmatched #else"); X else X { X match_state[ifdef_level - 1] = ps; X ps = state_stack[ifdef_level - 1]; X } X else if (strncmp(s_lab, "#endif", 6) == 0) X { X if (ifdef_level <= 0) X diag(1, "Unmatched #endif"); X else X { X ifdef_level--; X X#ifdef undef X /* This match needs to be more intelligent before the X message is useful */ X if (match_state[ifdef_level].tos >= 0 X && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) X diag(0, "Syntactically inconsistant #ifdef alternatives."); X#endif X } X if (bl_around) X { X postfix_blankline_requested++; X n_real_blanklines = 0; X } X } X break; /* subsequent processing of the X newline character will cause X the line to be printed */ X X case comment: /* we have gotten a /* this is X a biggie */ X proc_comment: X if (flushed_nl) X { /* we should force a broken X line here */ X flushed_nl = false; X dump_line(); X ps.want_blank = false; /* dont insert blank at line X start */ X force_nl = false; X } X pr_comment(); X break; X } /* end of big switch stmt */ X X *e_code = '\0'; /* make sure code section is X null terminated */ X if (type_code != comment && type_code != newline && type_code != preesc) X ps.last_token = type_code; X } /* end of main while (1) loop */ X}; X X/* X * copy input file to backup file if in_name is /blah/blah/blah/file, then X * backup file will be ".Bfile" then make the backup file the input and X * original input file the output X */ Xbakcopy() X{ X int n, bakchn; X char buff[8 * 1024]; X register char *p; X X /* construct file name .Bfile */ X for (p = in_name; *p; p++); /* skip to end of string */ X while (p > in_name && *p != '/') /* find last '/' */ X p--; X if (*p == '/') X p++; X sprintf(bakfile, "%s.BAK", p); X X /* copy in_name to backup file */ X bakchn = creat(bakfile, 0600); X if (bakchn < 0) X { X fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile); X exit(1); X } X while (n = read(fileno(input), buff, sizeof buff)) X if (write(bakchn, buff, n) != n) X { X fprintf(stderr, "indent: error writing backup file \"%s\"\n", X bakfile); X exit(1); X } X if (n < 0) X { X fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name); X exit(1); X } X close(bakchn); X fclose(input); X X /* re-open backup file as the input file */ X input = fopen(bakfile, "r"); X if (input == 0) X { X fprintf(stderr, "indent: can't re-open backup file\n"); X exit(1); X } X /* now the original input file will be the output */ X output = fopen(in_name, "w"); X if (output == 0) X { X fprintf(stderr, "indent: can't create %s\n", in_name); X unlink(bakfile); X exit(1); X } X} /