From: Ben Gras Date: Fri, 22 Jul 2005 18:30:14 +0000 (+0000) Subject: Imported indent X-Git-Tag: v3.1.0~566 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/index.css?a=commitdiff_plain;h=3a68bd323aa521971fb7e8ccc612d94181c73902;p=minix.git Imported indent --- diff --git a/commands/indent/Makefile b/commands/indent/Makefile new file mode 100644 index 000000000..e228f65f7 --- /dev/null +++ b/commands/indent/Makefile @@ -0,0 +1,21 @@ +# Makefile for indent + +CFLAGS= -c -O -D_MINIX -D_POSIX_SOURCE -wo -m + +all: indent + +OBJ = args.o comment.o lexi.o indent.o parse.o io.o + +indent: ${OBJ} + $(CC) -o indent -i ${OBJ} + install -S 32kw $@ + +install: /usr/bin/indent + +/usr/bin/indent: indent + install -cs -o bin indent $@ + +$(OBJ): globs.h codes.h + +clean: + rm -f *.bak *.o core indent diff --git a/commands/indent/args.c b/commands/indent/args.c new file mode 100644 index 000000000..729452d5b --- /dev/null +++ b/commands/indent/args.c @@ -0,0 +1,287 @@ +/** + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley, the University of Illinois, + * Urbana, and Sun Microsystems, Inc. The name of either University + * or Sun Microsystems may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * Argument scanning and profile reading code. Default parameters are set + * here as well. + */ + +#define PUBLIC extern +#include +#include +#include +#include +#include "globs.h" +#include "proto.h" + +/* profile types */ +#define PRO_SPECIAL 1 /* special case */ +#define PRO_BOOL 2 /* boolean */ +#define PRO_INT 3 /* integer */ +#define PRO_FONT 4 /* troff font */ + +/* profile specials for booleans */ +#define ON 1 /* turn it on */ +#define OFF 0 /* turn it off */ + +/* profile specials for specials */ +#define IGN 1 /* ignore it */ +#define CLI 2 /* case label indent (float) */ +#define STDIN 3 /* use stdin */ +#define KEY 4 /* type (keyword) */ + +/* + * N.B.: because of the way the table here is scanned, options whose names + * are substrings of other options must occur later; that is, with -lp vs -l, + * -lp must be first. Also, while (most) booleans occur more than once, the + * last default value is the one actually assigned. + */ +struct pro +{ + char *p_name; /* name, eg -bl, -cli */ + int p_type; /* type (int, bool, special) */ + int p_default; /* the default value (if int) */ + int p_special; /* depends on type */ + int *p_obj; /* the associated variable */ +} pro[] = + +{ + + "T", PRO_SPECIAL, 0, KEY, 0, + "bacc", PRO_BOOL, false, ON, &bl_around, + "badp", PRO_BOOL, false, ON, &bl_at_proctop, + "bad", PRO_BOOL, false, ON, &bl_aft_decl, + "bap", PRO_BOOL, false, ON, &bl_a_procs, + "bbb", PRO_BOOL, false, ON, &bl_bef_bk, + "bc", PRO_BOOL, true, OFF, &ps.leave_comma, + "bl", PRO_BOOL, true, OFF, &btype_2, + "br", PRO_BOOL, true, ON, &btype_2, + "bs", PRO_BOOL, false, ON, &Bill_Shannon, + "cdb", PRO_BOOL, true, ON, &del_on_bl, + "cd", PRO_INT, 0, 0, &ps.decl_com_ind, + "ce", PRO_BOOL, true, ON, &cuddle_else, + "ci", PRO_INT, 0, 0, &continuation_indent, + "cli", PRO_SPECIAL, 0, CLI, 0, + "c", PRO_INT, 33, 0, &ps.com_ind, + "di", PRO_INT, 16, 0, &ps.decl_indent, + "dj", PRO_BOOL, false, ON, &ps.ljust_decl, + "d", PRO_INT, 0, 0, &ps.unindent_displace, + "eei", PRO_BOOL, false, ON, &ex_expr_indent, + "ei", PRO_BOOL, true, ON, &ps.else_if, + "fbc", PRO_FONT, 0, 0, (int *) &blkcomf, + "fbx", PRO_FONT, 0, 0, (int *) &boxcomf, + "fb", PRO_FONT, 0, 0, (int *) &bodyf, + "fc1", PRO_BOOL, true, ON, &format_col1_comments, + "fc", PRO_FONT, 0, 0, (int *) &scomf, + "fk", PRO_FONT, 0, 0, (int *) &keywordf, + "fs", PRO_FONT, 0, 0, (int *) &stringf, + "ip", PRO_BOOL, true, ON, &ps.indent_parameters, + "i", PRO_INT, 8, 0, &ps.ind_size, + "lc", PRO_INT, 0, 0, &bk_max_col, + "lp", PRO_BOOL, true, ON, &lineup_to_parens, + "l", PRO_INT, 78, 0, &max_col, + "nbacc", PRO_BOOL, false, OFF, &bl_around, + "nbadp", PRO_BOOL, false, OFF, &bl_at_proctop, + "nbad", PRO_BOOL, false, OFF, &bl_aft_decl, + "nbap", PRO_BOOL, false, OFF, &bl_a_procs, + "nbbb", PRO_BOOL, false, OFF, &bl_bef_bk, + "nbc", PRO_BOOL, true, ON, &ps.leave_comma, + "nbs", PRO_BOOL, false, OFF, &Bill_Shannon, + "ncdb", PRO_BOOL, true, OFF, &del_on_bl, + "nce", PRO_BOOL, true, OFF, &cuddle_else, + "ndj", PRO_BOOL, false, OFF, &ps.ljust_decl, + "neei", PRO_BOOL, false, OFF, &ex_expr_indent, + "nei", PRO_BOOL, true, OFF, &ps.else_if, + "nfc1", PRO_BOOL, true, OFF, &format_col1_comments, + "nip", PRO_BOOL, true, OFF, &ps.indent_parameters, + "nlp", PRO_BOOL, true, OFF, &lineup_to_parens, + "npcs", PRO_BOOL, false, OFF, &proc_calls_space, + "npro", PRO_SPECIAL, 0, IGN, 0, + "npsl", PRO_BOOL, true, OFF, &proc_str_line, + "nps", PRO_BOOL, false, OFF, &ptr_binop, + "nsc", PRO_BOOL, true, OFF, &star_comment_cont, + "nsob", PRO_BOOL, false, OFF, &swallow_opt_bl, + "nv", PRO_BOOL, false, OFF, &verbose, + "pcs", PRO_BOOL, false, ON, &proc_calls_space, + "psl", PRO_BOOL, true, ON, &proc_str_line, + "ps", PRO_BOOL, false, ON, &ptr_binop, + "sc", PRO_BOOL, true, ON, &star_comment_cont, + "sob", PRO_BOOL, false, ON, &swallow_opt_bl, + "st", PRO_SPECIAL, 0, STDIN, 0, + "troff", PRO_BOOL, false, ON, &troff, + "v", PRO_BOOL, false, ON, &verbose, + /* whew! */ + 0, 0, 0, 0, 0 +}; + +/* + * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles + * arguments given in these files. + */ +void set_profile() +{ + register FILE *f; + char fname[BUFSIZ]; + static char prof[] = ".indent.pro"; + + sprintf(fname, "%s/%s", getenv("HOME"), prof); + if ((f = fopen(fname, "r")) != NULL) + { + scan_profile(f); + (void) fclose(f); + } + if ((f = fopen(prof, "r")) != NULL) + { + scan_profile(f); + (void) fclose(f); + } +} + +void scan_profile(f) + register FILE *f; +{ + register int i; + register char *p; + char buf[BUFSIZ]; + + while (1) + { + for (p = buf; (i = getc(f)) != EOF && (*p = (char)i) > ' '; ++p); + if (p != buf) + { + *p++ = 0; + if (verbose) + printf("profile: %s\n", buf); + set_option(buf); + } else if (i == EOF) + return; + } +} + +char *param_start; + +int eqin(s1, s2) + register char *s1; + register char *s2; +{ + while (*s1) + { + if (*s1++ != *s2++) + return (false); + } + param_start = s2; + return (true); +} + +/* + * Set the defaults. + */ +void set_defaults() +{ + register struct pro *p; + + /* Because ps.case_indent is a float, we can't initialize it from + the table: */ + ps.case_indent = 0; /* -cli0.0 */ + for (p = pro; p->p_name; p++) + if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT) + *p->p_obj = p->p_default; +} + +void set_option(arg) + register char *arg; +{ + register struct pro *p; + + arg++; /* ignore leading "-" */ + for (p = pro; p->p_name; p++) + if (*p->p_name == *arg && eqin(p->p_name, arg)) + goto found; + fprintf(stderr, "indent: unknown parameter \"%s\"\n", arg - 1); + exit(1); +found: + switch (p->p_type) + { + + case PRO_SPECIAL: + switch (p->p_special) + { + + case IGN: + break; + + case CLI: + if (*param_start == 0) + goto need_param; + ps.case_indent = atoi(param_start); + break; + + case STDIN: + if (input == 0) + input = stdin; + if (output == 0) + output = stdout; + break; + + case KEY: + if (*param_start == 0) + goto need_param; + { + register char *str = (char *) malloc(strlen(param_start) + 1); + strcpy(str, param_start); + addkey(str, 4); + } + break; + + default: + fprintf(stderr, "\ +indent: set_option: internal error: p_special %d\n", p->p_special); + exit(1); + } + break; + + case PRO_BOOL: + if (p->p_special == OFF) + *p->p_obj = false; + else + *p->p_obj = true; + break; + + case PRO_INT: + if (*param_start == 0) + { + need_param: + fprintf(stderr, "indent: ``%s'' requires a parameter\n", + arg - 1); + exit(1); + } + *p->p_obj = atoi(param_start); + break; + + case PRO_FONT: + parsefont((struct fstate *) p->p_obj, param_start); + break; + + default: + fprintf(stderr, "indent: set_option: internal error: p_type %d\n", + p->p_type); + exit(1); + } +} diff --git a/commands/indent/codes.h b/commands/indent/codes.h new file mode 100644 index 000000000..1afea04cd --- /dev/null +++ b/commands/indent/codes.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley, the University of Illinois, + * Urbana, and Sun Microsystems, Inc. The name of either University + * or Sun Microsystems may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)indent_codes.h 5.6 (Berkeley) 9/15/88 + */ + +#define newline 1 +#define lparen 2 +#define rparen 3 +#define unary_op 4 +#define binary_op 5 +#define postop 6 +#define question 7 +#define casestmt 8 +#define colon 9 +#define semicolon 10 +#define lbrace 11 +#define rbrace 12 +#define ident 13 +#define comma 14 +#define comment 15 +#define swstmt 16 +#define preesc 17 +#define form_feed 18 +#define decl 19 +#define sp_paren 20 +#define sp_nparen 21 +#define ifstmt 22 +#define whilestmt 23 +#define forstmt 24 +#define stmt 25 +#define stmtl 26 +#define elselit 27 +#define dolit 28 +#define dohead 29 +#define ifhead 30 +#define elsehead 31 +#define period 32 diff --git a/commands/indent/comment.c b/commands/indent/comment.c new file mode 100644 index 000000000..a4625a46f --- /dev/null +++ b/commands/indent/comment.c @@ -0,0 +1,457 @@ +/** + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley, the University of Illinois, + * Urbana, and Sun Microsystems, Inc. The name of either University + * or Sun Microsystems may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * NAME: pr_comment + * + * FUNCTION: This routine takes care of scanning and printing comments. + * + * ALGORITHM: 1) Decide where the comment should be aligned, and if lines should + * be broken. 2) If lines should not be broken and filled, just copy up to + * end of comment. 3) If lines should be filled, then scan thru input_buffer + * copying characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and continue + * copying. + * + * HISTORY: November 1976 D A Willcox of CAC Initial coding 12/6/76 + * A Willcox of CAC Modification to handle UNIX-style comments + * + */ + +/* + * this routine processes comments. It makes an attempt to keep comments + * from going over the max line length. If a line is too long, it moves + * everything from the last blank to the next comment line. Blanks and tabs + * from the beginning of the input line are removed + */ + + +#define PUBLIC extern +#include +#include "globs.h" +#include "proto.h" + + +void pr_comment() +{ + int now_col; /* column we are in now */ + + int adj_max_col; /* Adjusted max_col for when we + * decide to spill comments + * over the right margin + */ + + char *last_bl; /* points to the last blank in + * the output buffer + */ + + char *t_ptr; /* used for moving string */ + + int unix_comment; /* tri-state variable used to + * decide if it is a unix-style + * comment. 0 means only blanks + * since / *, 1 means regular + * style comment, 2 means unix + * style comment + */ + + int break_delim = del_on_bl; + int l_just_saw_decl = ps.just_saw_decl; + /* int ps.last_nl = 0; */ /* true iff the last + sig thing we have seen is a nl */ + + int one_liner = 1; /* true iff this comment is a + one-liner */ + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = 0; /* no blanks found so far */ + ps.box_com = false; /* at first, assume that we are + not in a boxed comment or + some other comment that + should not be touched */ + ++ps.out_coms; /* keep track of number of + comments */ + unix_comment = 1; /* set flag to let us figure + out if there is a unix-style + comment ** DISABLED: use 0 + to reenable this hack! */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) + { /* if comment starts in column + 1 it should not be touched */ + ps.box_com = true; + ps.com_col = 1; + } else + { + if (*buf_ptr == '-' || *buf_ptr == '*') + { + ps.box_com = true; /* a comment with a '-' or '*' + immediately after the / * is + assumed to be a boxed + comment */ + break_delim = 0; + } + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) + { + /* klg: check only if this line is blank */ + /* If this (*and previous lines are*) blank, dont put comment + way out at left */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = bk_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } else + { + register target_col; + break_delim = 0; + if (s_code != e_code) + target_col = count_spaces(code_target(), s_code); + else + { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(label_target(), s_lab); + } + ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col < target_col) + ps.com_col = ((target_col + 7) & ~7) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; + } + } + if (ps.box_com) + { + buf_ptr[-2] = 0; + ps.n_comment_delta = 1 - count_spaces(1, in_buffer); + buf_ptr[-2] = '/'; + } else + { + ps.n_comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/ *' into buffer */ + *e_com++ = '*'; + if (*buf_ptr != ' ' && !ps.box_com) + *e_com++ = ' '; + + *e_com = '\0'; + if (troff) + { + now_col = 1; + adj_max_col = 80; + } else + now_col = count_spaces(ps.com_col, s_com); /* figure what column we + would be in if we + printed the comment + now */ + + /* Start to copy the comment */ + + while (1) + { /* this loop will go until the + comment is copied */ + if (*buf_ptr > 040 && *buf_ptr != '*') + ps.last_nl = 0; + if (e_com >= l_com) + { + register nsize = l_com - s_com + 400; + combuf = (char *) realloc(combuf, nsize); + e_com = combuf + (e_com - s_com) + 1; + l_com = combuf + nsize - 5; + s_com = combuf + 1; + } + switch (*buf_ptr) + { /* this checks for various spcl + cases */ + case 014: /* check for a form feed */ + if (!ps.box_com) + { /* in a text comment, break the + line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); + last_bl = 0; + *e_com++ = ' '; + *e_com++ = '*'; + *e_com++ = ' '; + while (*++buf_ptr == ' ' || *buf_ptr == '\t'); + } else + { + if (++buf_ptr >= buf_end) + fill_buffer(); + *e_com++ = 014; + } + break; + + case '\n': + if (had_eof) + { /* check for unexpected eof */ + printf("Unterminated comment\n"); + *e_com = '\0'; + dump_line(); + return; + } + one_liner = 0; + if (ps.box_com || ps.last_nl) + { /* if this is a boxed comment, + we dont ignore the newline */ + if (s_com == e_com) + { + *e_com++ = ' '; + *e_com++ = ' '; + } + *e_com = '\0'; + if (!ps.box_com && e_com - s_com > 3) + { + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') + { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (bl_bef_bk) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + dump_line(); + if (e_com >= l_com) + { + register nsize = l_com - s_com + 400; + combuf = (char *) realloc(combuf, nsize); + e_com = combuf + (e_com - s_com) + 1; + l_com = combuf + nsize - 5; + s_com = combuf + 1; + } + *e_com++ = ' '; + *e_com++ = ' '; + } + dump_line(); + now_col = ps.com_col; + } else + { + ps.last_nl = 1; + if (unix_comment != 1) + { /* we not are in unix_style + comment */ + if (unix_comment == 0 && s_code == e_code) + { + /* if it is a UNIX-style comment, ignore the + requirement that previous line be blank for + unindention */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + if (ps.com_col <= 1) + ps.com_col = 2; + } + unix_comment = 2; /* permanently remember that we + are in this type of comment */ + dump_line(); + ++line_no; + now_col = ps.com_col; + *e_com++ = ' '; + /* fix so that the star at the start of the line will + line up */ + do /* flush leading white space */ + if (++buf_ptr >= buf_end) + fill_buffer(); + while (*buf_ptr == ' ' || *buf_ptr == '\t'); + break; + } + if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') + last_bl = e_com - 1; + /* if there was a space at the end of the last line, + remember where it was */ + else + { /* otherwise, insert one */ + last_bl = e_com; + *e_com++ = ' '; + if (e_com >= l_com) + { + register nsize = l_com - s_com + 400; + combuf = (char *) realloc(combuf, nsize); + e_com = combuf + (e_com - s_com) + 1; + l_com = combuf + nsize - 5; + s_com = combuf + 1; + } + ++now_col; + } + } + ++line_no; /* keep track of input line + number */ + if (!ps.box_com) + { + int nstar = 1; + do + { /* flush any blanks and/or tabs + at start of next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) + { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } else if (++buf_ptr >= buf_end) + fill_buffer(); + break; /* end of case for newline */ + + case '*': /* must check for possibility + of being at end of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); + + if (unix_comment == 0) /* set flag to show we are not + in unix-style comment */ + unix_comment = 1; + + if (*buf_ptr == '/') + { /* it is the end!!! */ + end_of_comment: + if (++buf_ptr >= buf_end) + fill_buffer(); + + if (*(e_com - 1) != ' ' && !ps.box_com) + { /* insure blank before end */ + *e_com++ = ' '; + ++now_col; + } + if (break_delim == 1 && !one_liner && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') + { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (bl_bef_bk) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (break_delim == 2 && e_com > s_com + 3 + /* now_col > adj_max_col - 2 && !ps.box_com */ ) + { + *e_com = '\0'; + dump_line(); + now_col = ps.com_col; + } + if (e_com >= l_com) + { + register nsize = l_com - s_com + 400; + combuf = (char *) realloc(combuf, nsize); + e_com = combuf + (e_com - s_com) + 1; + l_com = combuf + nsize - 5; + s_com = combuf + 1; + } + *e_com++ = '*'; + *e_com++ = '/'; + *e_com = '\0'; + ps.just_saw_decl = l_just_saw_decl; + return; + } else + { /* handle isolated '*' */ + *e_com++ = '*'; + ++now_col; + } + break; + default: /* we have a random char */ + if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t') + unix_comment = 1; /* we are not in unix-style + comment */ + + *e_com = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*e_com == '\t') /* keep track of column */ + now_col = ((now_col - 1) & tabmask) + tabsize + 1; + else if (*e_com == '\b') /* this is a backspace */ + --now_col; + else + ++now_col; + + if (*e_com == ' ' || *e_com == '\t') + last_bl = e_com; + /* remember we saw a blank */ + + ++e_com; + if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ') + { + /* the comment is too long, it must be broken up */ + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') + { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (bl_bef_bk) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (last_bl == 0) + { /* we have seen no blanks */ + last_bl = e_com; /* fake it */ + *e_com++ = ' '; + } + *e_com = '\0'; /* print what we have */ + *last_bl = '\0'; + while (last_bl > s_com && last_bl[-1] < 040) + *--last_bl = 0; + e_com = last_bl; + dump_line(); + + *e_com++ = ' '; /* add blanks for continuation */ + *e_com++ = ' '; + *e_com++ = ' '; + + t_ptr = last_bl + 1; + last_bl = 0; + if (t_ptr >= e_com) + { + while (*t_ptr == ' ' || *t_ptr == '\t') + t_ptr++; + while (*t_ptr != '\0') + { /* move unprinted part of + comment down in buffer */ + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } + } + *e_com = '\0'; + now_col = count_spaces(ps.com_col, s_com); /* recompute current + position */ + } + break; + } + } +} diff --git a/commands/indent/globs.h b/commands/indent/globs.h new file mode 100644 index 000000000..cfd587829 --- /dev/null +++ b/commands/indent/globs.h @@ -0,0 +1,308 @@ +/** + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley, the University of Illinois, + * Urbana, and Sun Microsystems, Inc. The name of either University + * or Sun Microsystems may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)indent_globs.h 5.7 (Berkeley) 9/15/88 + */ + +#include + +#define BACKSLASH '\\' +#define bufsize 200 /* size of internal buffers */ +#define inp_bufs 600 /* size of input buffer */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is + placed to left of code */ + +#define tabsize 8 /* the size of a tab */ +#define tabmask 0177770 /* mask used when figuring + length of lines with tabs */ + + +#define false 0 +#define true !false + + +PUBLIC FILE *input; /* the fid for the input file */ +PUBLIC FILE *output; /* the output file */ + +PUBLIC char *labbuf; /* buffer for label */ +PUBLIC char *s_lab; /* start ... */ +PUBLIC char *e_lab; /* .. and end of stored label */ +PUBLIC char *l_lab; /* limit of label buffer */ + +PUBLIC char *codebuf; /* buffer for code section */ +PUBLIC char *s_code; /* start ... */ +PUBLIC char *e_code; /* .. and end of stored code */ +PUBLIC char *l_code; /* limit of code section */ + +PUBLIC char *combuf; /* buffer for comments */ +PUBLIC char *s_com; /* start ... */ +PUBLIC char *e_com; /* ... and end of stored + comments */ +PUBLIC char *l_com; /* limit of comment buffer */ + +PUBLIC char in_buffer[inp_bufs]; /* input buffer */ +PUBLIC char *buf_ptr; /* ptr to next character to be + taken from in_buffer */ +PUBLIC char *buf_end; /* ptr to first after last char + in in_buffer */ + +PUBLIC char save_com[sc_size]; /* input text is saved here + when looking for the brace + after an if, while, etc */ +PUBLIC char *sc_end; /* pointer into save_com buffer */ + +PUBLIC char *bp_save; /* saved value of buf_ptr when + taking input from save_com */ +PUBLIC char *be_save; /* similarly saved value of + buf_end */ + +PUBLIC char token[bufsize]; /* the last token scanned */ + + +PUBLIC int ptr_binop; /* pointer as binop */ +PUBLIC int bl_aft_decl; /* blanklines after + declarations */ +PUBLIC int bl_bef_bk; /* blanklines before + blockcomments */ +PUBLIC int bl_a_procs; /* blanklines after procs */ +PUBLIC int bl_around; /* blanklines around + conditional compilation */ +PUBLIC int swallow_opt_bl; /* swallow optional blanklines */ +PUBLIC int n_real_blanklines; +PUBLIC int prefix_blankline_requested; +PUBLIC int postfix_blankline_requested; +PUBLIC int break_comma; /* when true and not in parens, + break after a comma */ +PUBLIC int btype_2; /* when true, brace should be + on same line as if, while, + etc */ +PUBLIC long case_ind; /* indentation level to be used + for a "case n:" */ +PUBLIC int code_lines; /* count of lines with code */ +PUBLIC int had_eof; /* set to true when input is + exhausted */ +PUBLIC int line_no; /* the current line number. */ +PUBLIC int max_col; /* the maximum allowable line + length */ +PUBLIC int verbose; /* when true, non-essential + error messages are printed */ +PUBLIC int cuddle_else; /* true if else should cuddle + up to '}' */ +PUBLIC int star_comment_cont; /* true iff comment + continuation lines should + have stars at the beginning + of each line. */ +PUBLIC int del_on_bl; /* comment_delimiter_on_blanklin + e */ +PUBLIC int troff; /* true iff were generating + troff input */ +PUBLIC int proc_str_line; /* if true, the names of + procedures being defined get + placed in column 1 (ie. a + newline is placed between + the type of the procedure + and its name) */ +PUBLIC int proc_calls_space; /* If true, procedure calls + look like: foo(bar) rather + than foo (bar) */ +PUBLIC int format_col1_comments; /* If comments which start in + column 1 are to be magically + reformatted (just like + comments that begin in later + columns) */ +PUBLIC int inhibit_formatting; /* true if INDENT OFF is in + effect */ +PUBLIC int suppress_blanklines; /* set iff following blanklines + should be suppressed */ +PUBLIC int continuation_indent; /* set to the indentation + between the edge of code and + continuation lines */ +PUBLIC int lineup_to_parens; /* if true, continued code + within parens will be lined + up to the open paren */ +PUBLIC int Bill_Shannon; /* true iff a blank should + always be inserted after + sizeof */ +PUBLIC int bl_at_proctop; /* This is vaguely similar to + blanklines_after_declarations + except that it only applies + to the first set of + declarations in a procedure + (just after the first '{') + and it causes a blank line + to be generated even if + there are no declarations */ +PUBLIC int bk_max_col; +PUBLIC int ex_expr_indent; /* True if continuation lines + from the expression part of + "if(e)", "while(e)", + "for(e;e;e)" should be + indented an extra tab stop + so that they don't conflict + with the code that follows */ + +/* -troff font state information */ + +struct fstate +{ + char font[4]; + char size; + int allcaps; +}; + +PUBLIC struct fstate + keywordf, /* keyword font */ + stringf, /* string font */ + boxcomf, /* Box comment font */ + blkcomf, /* Block comment font */ + scomf, /* Same line comment font */ + bodyf; /* major body font */ + + +#define STACKSIZE 150 + +PUBLIC struct parser_state +{ + int last_token; + struct fstate cfont; /* Current font */ + int p_stack[STACKSIZE]; /* this is the parsers stack */ + int il[STACKSIZE]; /* this stack stores + indentation levels */ + long cstk[STACKSIZE]; /* used to store case stmt + indentation levels */ + int box_com; /* set to true when we are in a + "boxed" comment. In that + case, the first non-blank + char should be lined up with + the / in / * */ + int comment_delta, n_comment_delta; + int cast_mask; /* indicates which close parens + close off casts */ + int sizeof_mask; /* indicates which close parens + close off sizeof''s */ + int block_init; /* true iff inside a block + initialization */ + int block_init_level; /* The level of brace nesting + in an initialization */ + int last_nl; /* this is true if the last + thing scanned was a newline */ + int in_or_st; /* Will be true iff there has + been a declarator (e.g. int + or char) and no left paren + since the last semicolon. + When true, a '{' is starting + a structure definition or an + initialization list */ + int bl_line; /* set to 1 by dump_line if the + line is blank */ + int col_1; /* set to true if the last + token started in column 1 */ + int com_col; /* this is the column in which + the current coment should + start */ + int com_ind; /* the column in which comments + to the right of code should + start */ + int com_lines; /* the number of lines with + comments, set by dump_line */ + int dec_nest; /* current nesting level for + structure or init */ + int decl_com_ind; /* the column in which comments + after declarations should be + put */ + int decl_on_line; /* set to true if this line of + code has part of a + declaration on it */ + int i_l_follow; /* the level to which ind_level + should be set after the + current line is printed */ + int in_decl; /* set to true when we are in a + declaration stmt. The + processing of braces is then + slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation + level */ + int ind_size; /* the size of one indentation + level */ + int ind_stmt; /* set to 1 if next line should + have an extra indentation + level because we are in the + middle of a stmt */ + int last_u_d; /* set to true after scanning a + token which forces a + following operator to be + unary */ + int leave_comma; /* if true, never break + declarations after commas */ + int ljust_decl; /* true if declarations should + be left justified */ + int out_coms; /* the number of comments + processed, set by pr_comment */ + int out_lines; /* the number of lines written, + set by dump_line */ + int p_l_follow; /* used to remember how to + indent following statement */ + int paren_level; /* parenthesization level. used + to indent within stmts */ + short paren_indents[20]; /* column positions of each + paren */ + int pcase; /* set to 1 if the current line + label is a case. It is + printed differently from a + regular label */ + int search_brace; /* set to true by parse when it + is necessary to buffer up + all info up to the start of + a stmt after an if, while, + etc */ + int unindent_displace; /* comments not to the right of + code will be placed this + many indentation levels to + the left of code */ + int use_ff; /* set to one if the current + line should be terminated + with a form feed */ + int want_blank; /* set to true when the + following token should be + prefixed by a blank. (Said + prefixing is ignored in some + cases.) */ + int else_if; /* True iff else if pairs + should be handled specially */ + int decl_indent; /* column to indent declared + identifiers to */ + int its_a_keyword; + int sizeof_keyword; + int dumped_decl_indent; + int case_indent; /* The distance to indent case + labels from the switch + statement */ + int in_par_decl; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current + procedure */ + int just_saw_decl; +} ps; + +PUBLIC int ifdef_level; +PUBLIC struct parser_state state_stack[5]; +PUBLIC struct parser_state match_state[5]; diff --git a/commands/indent/indent.c b/commands/indent/indent.c new file mode 100644 index 000000000..b7b4a3e4e --- /dev/null +++ b/commands/indent/indent.c @@ -0,0 +1,1374 @@ +/** + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley, the University of Illinois, + * Urbana, and Sun Microsystems, Inc. The name of either University + * or Sun Microsystems may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* ported to MINIX by: Robert R. Hall */ + +#define _POSIX_SOURCE 1 +#define PUBLIC +#define NAME_SIZE _POSIX_NAME_MAX + +#include +#include +#include +#include +#include +#include +#include +#include +#include "globs.h" +#include "codes.h" +#include "proto.h" + +char *in_name = "Standard Input"; /* will always point to + name of input file */ +char *out_name = "Standard Output"; /* will always point to + name of output file */ +char bakfile[60]; + +void main(argc, argv) + int argc; + char **argv; +{ + + extern int found_err; /* flag set in diag() on error */ + int dec_ind; /* current indentation for + declarations */ + int di_stack[20]; /* a stack of structure + indentation levels */ + int flushed_nl; /* used when buffering up + comments to remember that a + newline was passed over */ + int force_nl; /* when true, code must be + broken */ + int hd_type; /* used to store type of stmt + for if (...), for (...), etc */ + register int i; /* local loop counter */ + int scase; /* set to true when we see a + case, so we will know what + to do with the following + colon */ + int sp_sw; /* when true, we are in the + expressin of if(...), + while(...), etc. */ + int squest; /* when this is positive, we + have seen a ? without the + matching : in a ?: + construct */ + register char *t_ptr; /* used for copying tokens */ + int type_code; /* the type of token, returned + by lexi */ + + int last_else = 0; /* true iff last keyword was an + else */ + + + /*-----------------------------------------------*\ + | INITIALIZATION | + \*-----------------------------------------------*/ + + + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last + thing scanned was a newline */ + ps.last_token = semicolon; + combuf = (char *) malloc(bufsize); + labbuf = (char *) malloc(bufsize); + codebuf = (char *) malloc(bufsize); + l_com = combuf + bufsize - 5; + l_lab = labbuf + bufsize - 5; + l_code = codebuf + bufsize - 5; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, + and comment buffers */ + combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special + processing to on */ + s_lab = e_lab = labbuf + 1; + s_code = e_code = codebuf + 1; + s_com = e_com = combuf + 1; + + buf_ptr = buf_end = in_buffer; + line_no = 1; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; + sp_sw = force_nl = false; + ps.in_or_st = false; + ps.bl_line = true; + dec_ind = 0; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; + + + scase = ps.pcase = false; + squest = 0; + sc_end = 0; + bp_save = 0; + be_save = 0; + + output = 0; + + + + /*--------------------------------------------------*\ + | COMMAND LINE SCAN | + \*--------------------------------------------------*/ + +#ifdef undef + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some + positive value by an arg, we + will set this equal to + ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ +#endif + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + set_defaults(); + if (i >= argc) + set_profile(); + + for (i = 1; i < argc; ++i) + { + + /* look thru args (if any) for changes to defaults */ + if (argv[i][0] != '-') + { /* no flag on parameter */ + if (input == 0) + { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == 0) + { /* check for open error */ + fprintf(stderr, "indent: can't open %s\n", argv[i]); + exit(1); + } + continue; + } else if (output == 0) + { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) + { /* attempt to overwrite the + file */ + fprintf(stderr, "indent: input and output files must be different\n"); + exit(1); + } + output = fopen(out_name, "w"); + if (output == 0) + { /* check for create error */ + fprintf(stderr, "indent: can't create %s\n", argv[i]); + exit(1); + } + continue; + } + fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]); + exit(1); + } else + set_option(argv[i]); + } /* end of for */ + if (input == 0) + { + fprintf(stderr, "indent: usage: indent file [ outfile ] [ options ]\n"); + exit(1); + } + if (output == 0) + if (troff) + output = stdout; + else + { + out_name = in_name; + bakcopy(); + } + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments + before column 2 */ + if (troff) + { + if (bodyf.font[0] == 0) + parsefont(&bodyf, "R"); + if (scomf.font[0] == 0) + parsefont(&scomf, "I"); + if (blkcomf.font[0] == 0) + blkcomf = scomf, blkcomf.size += 2; + if (boxcomf.font[0] == 0) + boxcomf = blkcomf; + if (stringf.font[0] == 0) + parsefont(&stringf, "L"); + if (keywordf.font[0] == 0) + parsefont(&keywordf, "B"); + writefdef(&bodyf, 'B'); + writefdef(&scomf, 'C'); + writefdef(&blkcomf, 'L'); + writefdef(&boxcomf, 'X'); + writefdef(&stringf, 'S'); + writefdef(&keywordf, 'K'); + } + if (bk_max_col <= 0) + bk_max_col = max_col; + if (ps.decl_com_ind <= 0) /* if not specified by user, + set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff + into input buffer */ + + parse(semicolon); + { + register char *p = buf_ptr; + register col = 1; + + while (1) + { + if (*p == ' ') + col++; + else if (*p == '\t') + col = ((col - 1) & ~7) + 9; + else + break; + p++; + }; + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; + } + if (troff) + { + register char *p = in_name, *beg = in_name; + + while (*p) + if (*p++ == '/') + beg = p; + fprintf(output, ".Fn \"%s\"\n", beg); + } + /* START OF MAIN LOOP */ + + while (1) + { /* this is the main loop. it + will go until we reach eof */ + int is_procname; + + type_code = lexi(); /* lexi reads one token. The + actual characters read are + stored in "token". lexi + returns a code indicating + the type of token */ + is_procname = ps.procname[0]; + + /* The following code moves everything following an if (), while + (), else, etc. up to the start of the following stmt to a + buffer. This allows proper handling of both kinds of brace + placement. */ + + flushed_nl = false; + while (ps.search_brace) + { /* if we scanned an if(), + while(), etc., we might need + to copy stuff into a buffer + we must loop, copying stuff + into save_com, until we find + the start of the stmt which + follows the if, or whatever */ + switch (type_code) + { + case newline: + ++line_no; + flushed_nl = true; + case form_feed: + break; /* form feeds and newlines + found here will be ignored */ + + case lbrace: /* this is a brace that starts + the compound stmt */ + if (sc_end == 0) + { /* ignore buffering if a + comment wasnt stored up */ + ps.search_brace = false; + goto check_type; + } + if (btype_2) + { + save_com[0] = '{'; /* we either want to put the + brace right after the if */ + goto sw_buffer; /* go to common code to get out + of this loop */ + } +/* + * Something is buffered up in save_com, and -bl processing is in effect. + * Add the brace after the comment so it will come out on the next line. + */ + flushed_nl = 0; /* comment can start on the same line */ + *sc_end++ = '\n'; /* break line after comment */ + *sc_end++ = '{'; + goto sw_buffer; + + case comment: /* we have a comment, so we + must copy it into the buffer */ + if (!flushed_nl || sc_end != 0) + { + if (sc_end == 0) + { /* if this is the first + comment, we must set up the + buffer */ + save_com[0] = save_com[1] = ' '; + sc_end = &(save_com[2]); + } else + { + *sc_end++ = '\n'; /* add newline between comments */ + *sc_end++ = ' '; + --line_no; + } + *sc_end++ = '/'; /* copy in start of comment */ + *sc_end++ = '*'; + + for (;;) + { /* loop until we get to the end + of the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + + if (sc_end >= &(save_com[sc_size])) + { /* check for temp buffer + overflow */ + diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever."); + fflush(output); + exit(1); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end)/* get past / in buffer */ + fill_buffer(); + break; + } + default: /* it is the start of a normal + statment */ + if (flushed_nl) /* if we flushed a newline, + make sure it is put back */ + force_nl = true; + if ((type_code == sp_paren && *token == 'i' + && last_else && ps.else_if) + || (type_code == sp_nparen && *token == 'e' + && e_code != s_code && e_code[-1] == '}')) + force_nl = false; + + if (sc_end == 0) + { /* ignore buffering if comment + wasnt saved up */ + ps.search_brace = false; + goto check_type; + } + if (force_nl) + { /* if we should insert a nl + here, put it into the buffer */ + force_nl = false; + --line_no; /* this will be re-increased + when the nl is read from the + buffer */ + *sc_end++ = '\n'; + *sc_end++ = ' '; + if (verbose && !flushed_nl) /* print error msg if + the line was not + already broken */ + diag(0, "Line broken"); + flushed_nl = false; + } + for (t_ptr = token; *t_ptr; ++t_ptr) + *sc_end++ = *t_ptr; /* copy token into temp buffer */ + ps.procname[0] = 0; + + sw_buffer: + ps.search_brace = false; /* stop looking for start of + stmt */ + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls + to lexi will take tokens out + of save_com */ + *sc_end++ = ' '; /* add trailing blank, just in + case */ + buf_end = sc_end; + sc_end = 0; + break; + } /* end of switch */ + if (type_code != 0) /* we must make this check, + just in case there was an + unexpected EOF */ + type_code = lexi(); /* read another token */ + /* if (ps.search_brace) ps.procname[0] = 0; */ + if ((is_procname = ps.procname[0]) && flushed_nl + && !proc_str_line && ps.in_decl + && type_code == ident) + flushed_nl = 0; + } /* end of while (search_brace) */ + last_else = 0; +check_type: + if (type_code == 0) + { /* we got eof */ + if (s_lab != e_lab || s_code != e_code + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag(1, "Stuff missing from end of file."); + + if (verbose) + { + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6d\n", + ps.com_lines / code_lines); + } + fflush(output); + exit(found_err); + } + if ( + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) + { + if (force_nl && + (type_code != semicolon) && + (type_code != lbrace || !btype_2)) + { + /* we should force a broken line here */ + if (verbose && !flushed_nl) + diag(0, "Line broken"); + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at line + start */ + force_nl = false; + } + ps.in_stmt = true; /* turn on flag which causes an + extra level of indentation. + this is turned off by a ; or + '}' */ + if (s_com != e_com) + { /* the turkey has embedded a + comment in a line. fix it */ + *e_code++ = ' '; + for (t_ptr = s_com; *t_ptr; ++t_ptr) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = *t_ptr; + } + *e_code++ = ' '; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; + e_com = s_com; + } + } else if (type_code != comment) /* preserve force_nl thru a + comment */ + force_nl = false; /* cancel forced newline after + newline, form feed, etc */ + + + + /*-----------------------------------------------------*\ + | do switch on type of token scanned | + \*-----------------------------------------------------*/ + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + switch (type_code) + { /* now, decide what to do with + the token */ + + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much + like a newline */ + dump_line(); + ps.want_blank = false; + break; + + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) + { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line + number */ + break; + + case lparen: /* got a '(' or '[' */ + ++ps.p_l_follow; /* count parens to make Healy + happy */ + if (ps.want_blank && *token != '[' && + (ps.last_token != ident || proc_calls_space + || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon)))) + *e_code++ = ' '; + if (ps.in_decl && !ps.block_init) + if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) + { + ps.dumped_decl_indent = 1; + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + e_code += strlen(e_code); + } else + { + while ((e_code - s_code) < dec_ind) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = ' '; + } + *e_code++ = token[0]; + } + else + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; + if (sp_sw && ps.p_l_follow == 1 && ex_expr_indent + && ps.paren_indents[0] < 2 * ps.ind_size) + ps.paren_indents[0] = 2 * ps.ind_size; + ps.want_blank = false; + if (ps.in_or_st && *token == '(' && ps.tos <= 2) + { + /* this is a kluge to make sure that declarations will be + aligned right if proc decl has an explicit type on it, + i.e. "int a(x) {..." */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for structure + decl or initialization */ + } + if (ps.sizeof_keyword) + ps.sizeof_mask |= 1 << ps.p_l_follow; + break; + + case rparen: /* got a ')' or ']' */ + if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) + { + ps.last_u_d = true; + ps.cast_mask &= (1 << ps.p_l_follow) - 1; + } + ps.sizeof_mask &= (1 << ps.p_l_follow) - 1; + if (--ps.p_l_follow < 0) + { + ps.p_l_follow = 0; + diag(0, "Extra %c", *token); + } + if (e_code == s_code) /* if the paren starts the line */ + ps.paren_level = ps.p_l_follow; /* then indent it */ + + *e_code++ = token[0]; + ps.want_blank = true; + + if (sp_sw && (ps.p_l_follow == 0)) + { /* check for end of if (...), + or some such */ + sp_sw = false; + force_nl = true; /* must force newline after if */ + ps.last_u_d = true; /* inform lexi that a following + operator is unary */ + ps.in_stmt = false; /* dont use stmt continuation + indentation */ + + parse(hd_type); /* let parser worry about if, + or whatever */ + } + ps.search_brace = btype_2; /* this should insure that + constructs such as + main(){...} and int[]{...} + have their braces put in the + right place */ + break; + + case unary_op: /* this could be any unary + operation */ + if (ps.want_blank) + *e_code++ = ' '; + + if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) + { + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } else + { + char *res = token; + + if (ps.in_decl && !ps.block_init) + { /* if this is a unary op in a + declaration, we should + indent this token */ + for (i = 0; token[i]; ++i); /* find length of token */ + while ((e_code - s_code) < (dec_ind - i)) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = ' '; /* pad it */ + } + } + if (troff && token[0] == '-' && token[1] == '>') + res = "\\(->"; + for (t_ptr = res; *t_ptr; ++t_ptr) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = *t_ptr; + } + } + ps.want_blank = false; + break; + + case binary_op: /* any binary operation */ + if (ps.want_blank) + *e_code++ = ' '; + { + char *res = token; + + if (troff) + switch (token[0]) + { + case '<': + if (token[1] == '=') + res = "\\(<="; + break; + case '>': + if (token[1] == '=') + res = "\\(>="; + break; + case '!': + if (token[1] == '=') + res = "\\(!="; + break; + case '|': + if (token[1] == '|') + res = "\\(br\\(br"; + else if (token[1] == 0) + res = "\\(br"; + break; + } + for (t_ptr = res; *t_ptr; ++t_ptr) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = *t_ptr; /* move the operator */ + } + } + ps.want_blank = true; + break; + + case postop: /* got a trailing ++ or -- */ + *e_code++ = token[0]; + *e_code++ = token[1]; + ps.want_blank = true; + break; + + case question: /* got a ? */ + squest++; /* this will be used when a + later colon appears so we + can distinguish the + ?: construct */ + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = '?'; + ps.want_blank = true; + break; + + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later + colon properly */ + goto copy_id; + + case colon: /* got a ':' */ + if (squest > 0) + { /* it is part of the ?: + construct */ + --squest; + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = ':'; + ps.want_blank = true; + break; + } + if (ps.in_decl) + { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not + imply we are in a stmt */ + for (t_ptr = s_code; *t_ptr; ++t_ptr) + *e_lab++ = *t_ptr; /* turn everything so far into + a label */ + e_code = s_code; + *e_lab++ = ':'; + *e_lab++ = ' '; + *e_lab = '\0'; + + force_nl = ps.pcase = scase; /* ps.pcase will be used by + dump_line to decide how to + indent the label. force_nl + will force a case n: to be + on a line by itself */ + scase = false; + ps.want_blank = false; + break; + + case semicolon: /* got a ';' */ + ps.in_or_st = false; /* we are not in an + initialization or structure + declaration */ + scase = false; /* these will only need + resetting in a error */ + squest = 0; + if (ps.last_token == rparen) + ps.in_par_decl = 0; + ps.cast_mask = 0; + ps.sizeof_mask = 0; + ps.block_init = 0; + ps.block_init_level = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init) + while ((e_code - s_code) < (dec_ind - 1)) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = ' '; + } + + ps.in_decl = (ps.dec_nest > 0);/* if we were in a first level + structure declaration, we + arent any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) + { + + /* This should be true iff there were unbalanced parens in + the stmt. It is a bit complicated, because the + semicolon might be in a for stmt */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) + { /* this is a check for a if, + while, etc. with unbalanced + parens */ + sp_sw = false; + parse(hd_type); /* dont lose the if, or + whatever */ + } + } + *e_code++ = ';'; + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in + the middle of a stmt */ + + if (!sp_sw) + { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of + stmt */ + force_nl = true; /* force newline after a end of + stmt */ + } + break; + + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true; /* force other stuff on same + line as '{' onto new line */ + else if (ps.block_init_level <= 0) + ps.block_init_level = 1; + else + ps.block_init_level++; + + if (s_code != e_code && !ps.block_init) + { + if (!btype_2) + { + dump_line(); + ps.want_blank = false; + } else if (ps.in_par_decl && !ps.in_or_st) + { + ps.i_l_follow = 0; + dump_line(); + ps.want_blank = false; + } + } + if (ps.in_par_decl) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) + { /* check for preceeding + unbalanced parens */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) + { /* check for unclosed if, for, + etc. */ + sp_sw = false; + parse(hd_type); + ps.ind_level = ps.i_l_follow; + } + } + if (s_code == e_code) + ps.ind_stmt = false; /* dont put extra indentation + on line with '{' */ + if (ps.in_decl && ps.in_or_st) + { /* this is either a structure + declaration or an init */ + di_stack[ps.dec_nest++] = dec_ind; + /* ? dec_ind = 0; */ + } else + { + ps.decl_on_line = false; /* we cant be in the middle of + a declaration, so dont do + special indentation of + comments */ + if (bl_at_proctop + && ps.in_par_decl) + postfix_blankline_requested = 1; + ps.in_par_decl = 0; + } + dec_ind = 0; + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if + '{' is not at start of line */ + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = '{'; + ps.just_saw_decl = 0; + break; + + case rbrace: /* got a '}' */ + if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be + omitted in + declarations */ + parse(semicolon); + if (ps.p_l_follow) + { /* check for unclosed if, for, + else. */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; + sp_sw = false; + } + ps.just_saw_decl = 0; + ps.block_init_level--; + if (s_code != e_code && !ps.block_init) + { /* '}' must be first on line */ + if (verbose) + diag(0, "Line broken"); + dump_line(); + } + *e_code++ = '}'; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) + { /* we are in multi-level + structure declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_par_decl) + ps.just_saw_decl = 2; + ps.in_decl = true; + } + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead + && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && bl_a_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; + break; + + case swstmt: /* got keyword "switch" */ + sp_sw = true; + hd_type = swstmt; /* keep this for when we have + seen the expression */ + goto copy_id; /* go move the token into + buffer */ + + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is + done after the expression is + scanned */ + hd_type = (*token == 'i' ? ifstmt : + (*token == 'w' ? whilestmt : forstmt)); + + /* remember the type of header for later use by parser */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') + { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) + { + if (verbose) + diag(0, "Line broken"); + dump_line(); /* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true; /* also, following stuff must + go onto new line */ + last_else = 1; + parse(elselit); + } else + { + if (e_code != s_code) + { /* make sure this starts a line */ + if (verbose) + diag(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true; /* also, following stuff must + go onto new line */ + last_else = 0; + parse(dolit); + } + goto copy_id; /* move the token into line */ + + case decl: /* we have a declaration type + (int, register, etc.) */ + parse(decl); /* let parser worry about + indentation */ + if (ps.last_token == rparen && ps.tos <= 1) + { + ps.in_par_decl = 1; + if (s_code != e_code) + { + dump_line(); + ps.want_blank = 0; + } + } + if (ps.in_par_decl && ps.indent_parameters && ps.dec_nest == 0) + { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or + initialization declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + /* dec_ind = e_code - s_code + (ps.decl_indent>i ? + ps.decl_indent : i); */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; + goto copy_id; + + case ident: /* got an identifier or + constant */ + if (ps.in_decl) + { /* if we are in a declaration, + we must indent identifier */ + if (ps.want_blank) + *e_code++ = ' '; + ps.want_blank = false; + if (is_procname == 0 || !proc_str_line) + { + if (!ps.block_init) + if (troff && !ps.dumped_decl_indent) + { + sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } else + while ((e_code - s_code) < dec_ind) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = ' '; + } + } else + { + if (dec_ind && s_code != e_code) + dump_line(); + dec_ind = 0; + ps.want_blank = false; + } + } else if (sp_sw && ps.p_l_follow == 0) + { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + if (ps.want_blank) + *e_code++ = ' '; + if (troff && ps.its_a_keyword) + { + e_code = chfont(&bodyf, &keywordf, e_code); + for (t_ptr = token; *t_ptr; ++t_ptr) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = keywordf.allcaps && islower(*t_ptr) + ? toupper(*t_ptr) : *t_ptr; + } + e_code = chfont(&keywordf, &bodyf, e_code); + } else + for (t_ptr = token; *t_ptr; ++t_ptr) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = *t_ptr; + } + ps.want_blank = true; + break; + + case period: /* treat a period kind of like + a binary operation */ + *e_code++ = '.'; /* move the period into line */ + ps.want_blank = false; /* dont put a blank after a + period */ + break; + + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after + comma if comma does + not start the line */ + if (ps.in_decl && is_procname == 0 && !ps.block_init) + while ((e_code - s_code) < (dec_ind - 1)) + { + if (e_code >= l_code) + { + register nsize = l_code - s_code + 400; + codebuf = (char *) realloc(codebuf, nsize); + e_code = codebuf + (e_code - s_code) + 1; + l_code = codebuf + nsize - 5; + s_code = codebuf + 1; + } + *e_code++ = ' '; + } + + *e_code++ = ','; + if (ps.p_l_follow == 0) + { + if (ps.block_init_level <= 0) + ps.block_init = 0; + if (break_comma && !ps.leave_comma) + force_nl = true; + } + break; + + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + *e_lab++ = '#'; /* move whole line to 'label' + buffer */ + { + int in_comment = 0; + int com_start = 0; + char quote = 0; + int com_end = 0; + + while (*buf_ptr != '\n' || in_comment) + { + if (e_lab >= l_lab) + { + register nsize = l_lab - s_lab + 400; + labbuf = (char *) realloc(labbuf, nsize); + e_lab = labbuf + (e_lab - s_lab) + 1; + l_lab = labbuf + nsize - 5; + s_lab = labbuf + 1; + } + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) + { + case BACKSLASH: + if (troff) + *e_lab++ = BACKSLASH; + if (!in_comment) + { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) + { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - s_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) + { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab - s_lab; + } + break; + } + } + + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab - s_lab == com_end && bp_save == 0) + { /* comment on preprocessor line */ + if (sc_end == 0) /* if this is the first + comment, we must set up the + buffer */ + sc_end = &(save_com[0]); + else + { + *sc_end++ = '\n'; /* add newline between comments */ + *sc_end++ = ' '; + --line_no; + } + memcpy(sc_end, s_lab + com_start, com_end - com_start); + sc_end += com_end - com_start; + if (sc_end >= &save_com[sc_size]) + abort(); + e_lab = s_lab + com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls + to lexi will take tokens out + of save_com */ + *sc_end++ = ' '; /* add trailing blank, just in + case */ + buf_end = sc_end; + sc_end = 0; + } + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; + } + + if (strncmp(s_lab, "#if", 3) == 0) + { + if (bl_around) + { + register c; + prefix_blankline_requested++; + while ((c = getc(input)) == '\n'); + ungetc(c, input); + } + if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) + { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } else + diag(1, "#if stack overflow"); + } else if (strncmp(s_lab, "#else", 5) == 0) + if (ifdef_level <= 0) + diag(1, "Unmatched #else"); + else + { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } + else if (strncmp(s_lab, "#endif", 6) == 0) + { + if (ifdef_level <= 0) + diag(1, "Unmatched #endif"); + else + { + ifdef_level--; + +#ifdef undef + /* This match needs to be more intelligent before the + message is useful */ + if (match_state[ifdef_level].tos >= 0 + && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) + diag(0, "Syntactically inconsistant #ifdef alternatives."); +#endif + } + if (bl_around) + { + postfix_blankline_requested++; + n_real_blanklines = 0; + } + } + break; /* subsequent processing of the + newline character will cause + the line to be printed */ + + case comment: /* we have gotten a / * this is + a biggie */ + if (flushed_nl) + { /* we should force a broken + line here */ + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at line + start */ + force_nl = false; + } + pr_comment(); + break; + } /* end of big switch stmt */ + + *e_code = '\0'; /* make sure code section is + null terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ +} + +/* + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output + */ +void bakcopy() +{ + int n, bakchn; + char buff[8 * 1024]; + register char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ + p--; + if (*p == '/') + p++; + sprintf(bakfile, "%s.BAK", p); + if (strlen(p) >= NAME_SIZE) *bakfile ^= 040; /* toggle char */ + + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); + if (bakchn < 0) + { + fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile); + exit(1); + } + while (n = read(fileno(input), buff, sizeof buff)) + if (write(bakchn, buff, n) != n) + { + fprintf(stderr, "indent: error writing backup file \"%s\"\n", + bakfile); + exit(1); + } + if (n < 0) + { + fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name); + exit(1); + } + close(bakchn); + fclose(input); + + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); + if (input == 0) + { + fprintf(stderr, "indent: can't re-open backup file\n"); + exit(1); + } + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == 0) + { + fprintf(stderr, "indent: can't create %s\n", in_name); + unlink(bakfile); + exit(1); + } +} diff --git a/commands/indent/indent.pro b/commands/indent/indent.pro new file mode 100644 index 000000000..f1784e604 --- /dev/null +++ b/commands/indent/indent.pro @@ -0,0 +1 @@ +-bap -bbb -br -ncdb -cli0.5 -di1 -lp -npsl -nfc1 -nip diff --git a/commands/indent/io.c b/commands/indent/io.c new file mode 100644 index 000000000..67a2781fb --- /dev/null +++ b/commands/indent/io.c @@ -0,0 +1,636 @@ +/** + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley, the University of Illinois, + * Urbana, and Sun Microsystems, Inc. The name of either University + * or Sun Microsystems may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define PUBLIC extern +#include +#include +#include +#include "globs.h" +#include "proto.h" + + +int comment_open; +static paren_target; + +void dump_line() +{ /* dump_line is the routine + that actually effects the + printing of the new source. + It prints the label section, + followed by the code section + with the appropriate nesting + level, followed by any + comments */ + register int cur_col, target_col; + static not_first_line; + + if (ps.procname[0]) + { + if (troff) + { + if (comment_open) + { + comment_open = 0; + fprintf(output, ".*/\n"); + } + fprintf(output, ".Pr \"%s\"\n", ps.procname); + } + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) + { + if (suppress_blanklines > 0) + suppress_blanklines--; + else + { + ps.bl_line = true; + n_real_blanklines++; + } + } else if (!inhibit_formatting) + { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested && not_first_line) + if (swallow_opt_bl) + { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } else + { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. + dont do additional statement + indentation if we are at + bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with + code */ + + + if (e_lab != s_lab) + { /* print lab, if any */ + if (comment_open) + { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + cur_col = pad_output(1, label_target()); + fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab); + cur_col = count_spaces(cur_col, s_lab); + } else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) + { /* print code section, if any */ + register char *p; + + if (comment_open) + { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = code_target(); + { + register i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == (char) 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) + if (troff) + { + int all_here = 0; + register char *p; + + if (e_com[-1] == '/' && e_com[-2] == '*') + e_com -= 2, all_here++; + while (e_com > s_com && e_com[-1] == ' ') + e_com--; + *e_com = 0; + p = s_com; + while (*p == ' ') + p++; + if (p[0] == '/' && p[1] == '*') + p += 2, all_here++; + else if (p[0] == '*') + p += p[1] == '/' ? 2 : 1; + while (*p == ' ') + p++; + if (*p == 0) + goto inhibit_newline; + if (comment_open < 2 && ps.box_com) + { + comment_open = 0; + fprintf(output, ".*/\n"); + } + if (comment_open == 0) + { + if ('a' <= *p && *p <= 'z') + *p = *p + 'A' - 'a'; + if (e_com - p < 50 && all_here == 2) + { + register char *follow = p; + fprintf(output, "\n.nr C! \\w\1"); + while (follow < e_com) + { + switch (*follow) + { + case '\n': + putc(' ', output); + case 1: + break; + case '\\': + putc('\\', output); + default: + putc(*follow, output); + } + follow++; + } + putc(1, output); + } + fprintf(output, "\n./* %dp %d %dp\n", + ps.com_col * 7, + (s_code != e_code || s_lab != e_lab) - ps.box_com, + target_col * 7); + } + comment_open = 1 + ps.box_com; + while (*p) + { + if (*p == BACKSLASH) + putc(BACKSLASH, output); + putc(*p++, output); + } + } else + { /* print comment, if any */ + register target = ps.com_col; + register char *com_st = s_com; + + target += ps.comment_delta; + while (*com_st == '\t') + com_st++, target += 8; /* ? */ + while (target <= 0) + if (*com_st == ' ') + target++, com_st++; + else if (*com_st == '\t') + target = ((target - 1) & ~7) + 9, com_st++; + else + target = 1; + if (cur_col > target) + { /* if comment cant fit on this + line, put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + while (e_com > com_st && isspace(e_com[-1])) + e_com--; + cur_col = pad_output(cur_col, target); + if (!ps.box_com) + { + if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1)) + if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1) + com_st[1] = '*'; + else + fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output); + } + fwrite(com_st, (int)(e_com - com_st), 1, output); + ps.comment_delta = ps.n_comment_delta; + cur_col = count_spaces(cur_col, com_st); + ++ps.com_lines; /* count lines with comments */ + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); +inhibit_newline: + ++ps.out_lines; + if (ps.just_saw_decl == 1 && bl_aft_decl) + { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; + } + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + declaration, remember that + fact for proper comment + indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + indented if we have + not completed this + stmt and if we are + not in the middle of + a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ + *(e_code = s_code) = '\0'; + *(e_com = s_com) = '\0'; + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + paren_target = -ps.paren_indents[ps.paren_level - 1]; + not_first_line = 1; + return; +} + +int code_target() +{ + register target_col = ps.ind_size * ps.ind_level + 1; + + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent * ps.paren_level; + else + { + register w; + register t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) + { + t -= w + 1; + if (t > target_col) + target_col = t; + } else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} + +int label_target() +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) + 1 + : *s_lab == '#' ? 1 + : ps.ind_size * (ps.ind_level - label_offset) + 1; +} + + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: fill_buffer + * + * FUNCTION: Reads one block of input into input_buffer + * + * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A + * Willcox of CAC Added check for switch back to partly full input + * buffer from temporary buffer + * + */ +void +fill_buffer() +{ /* this routine reads stuff + from the input */ + register char *p; + register int i; + register FILE *f = input; + + if (bp_save != 0) + { /* there is a partly filled + input buffer left */ + buf_ptr = bp_save; /* dont read anything, just + switch buffers */ + buf_end = be_save; + bp_save = be_save = 0; + if (buf_ptr < buf_end) + return; /* only return if there is + really something in this + buffer */ + } + for (p = buf_ptr = in_buffer;;) + { + if ((i = getc(f)) == EOF) + { + *p++ = ' '; + *p++ = '\n'; + had_eof = true; + break; + } + *p++ = (char)i; + if (i == '\n') + break; + } + buf_end = p; + if (p[-2] == '/' && p[-3] == '*') + { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else + { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') + { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') + { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) + { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) + { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) + { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } + return; +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the desired + * position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column target + * nteger The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no action + * is taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int pad_output(current, target) /* writes tabs and blanks (if + necessary) to get the + current output position up + to the target column */ + int current; /* the current column value */ + int target; /* position we want it at */ +{ + register int curr; /* internal column pointer */ + register int tcur; + + if (troff) + fprintf(output, "\\h'|%dp'", (target - 1) * 7); + else + { + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) + { + putc('\t', output); + curr = tcur; + } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ + } + return (target); +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in column + * "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces(current, buffer) +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ + int current; + char *buffer; +{ + register char *buf; /* used to look thru buffer */ + register int cur; /* current character counter */ + + cur = current; + + for (buf = buffer; *buf != '\0'; ++buf) + { + switch (*buf) + { + + case '\n': + case 014: /* form feed */ + cur = 1; + break; + + case '\t': + cur = ((cur - 1) & tabmask) + tabsize + 1; + break; + + case '': /* this is a backspace */ + --cur; + break; + + default: + ++cur; + break; + } /* end of switch */ + } /* end of for loop */ + return (cur); +} + +int found_err; +void diag(level, msg, a, b) +int level; +char *msg; +int a, b; +{ + if (level) + found_err = 1; + if (output == stdout) + { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); + } else + { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); + } +} + +void writefdef(f, nm) + register struct fstate *f; + int nm; +{ + fprintf(output, ".ds f%c %s\n.nr s%c %d\n", + nm, f->font, nm, f->size); +} + +char * +chfont(of, nf, s) + register struct fstate *of, *nf; + char *s; +{ + if (of->font[0] != nf->font[0] + || of->font[1] != nf->font[1]) + { + *s++ = '\\'; + *s++ = 'f'; + if (nf->font[1]) + { + *s++ = '('; + *s++ = nf->font[0]; + *s++ = nf->font[1]; + } else + *s++ = nf->font[0]; + } + if (nf->size != of->size) + { + *s++ = '\\'; + *s++ = 's'; + if (nf->size < of->size) + { + *s++ = '-'; + *s++ = (char)'0' + of->size - nf->size; + } else + { + *s++ = '+'; + *s++ = (char)'0' + nf->size - of->size; + } + } + return s; +} + + +void parsefont(f, s0) + register struct fstate *f; + char *s0; +{ + register char *s = s0; + int sizedelta = 0; + memset(f, '\0', sizeof *f); + while (*s) + { + if (isdigit(*s)) + f->size = f->size * 10 + *s - '0'; + else if (isupper(*s)) + if (f->font[0]) + f->font[1] = *s; + else + f->font[0] = *s; + else if (*s == 'c') + f->allcaps = 1; + else if (*s == '+') + sizedelta++; + else if (*s == '-') + sizedelta--; + else + { + fprintf(stderr, "indent: bad font specification: %s\n", s0); + exit(1); + } + s++; + } + if (f->font[0] == 0) + f->font[0] = 'R'; + if (bodyf.size == 0) + bodyf.size = 11; + if (f->size == 0) + f->size = bodyf.size + sizedelta; + else if (sizedelta > 0) + f->size += bodyf.size; + else + f->size = bodyf.size - f->size; +} diff --git a/commands/indent/lexi.c b/commands/indent/lexi.c new file mode 100644 index 000000000..6cf42c8c0 --- /dev/null +++ b/commands/indent/lexi.c @@ -0,0 +1,571 @@ +/** + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley, the University of Illinois, + * Urbana, and Sun Microsystems, Inc. The name of either University + * or Sun Microsystems may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * Here we have the token scanner for indent. It scans off one token and + * puts it in the global variable "token". It returns a code, indicating the + * type of token scanned. + */ + +#define PUBLIC extern +#include +#include +#include "globs.h" +#include "codes.h" +#include "proto.h" + +#define alphanum 1 +#define opchar 3 + +struct templ +{ + char *rwd; + int rwcode; +}; + +struct templ specials[100] = +{ + "switch", 1, + "case", 2, + "break", 0, + "struct", 3, + "union", 3, + "enum", 3, + "default", 2, + "int", 4, + "char", 4, + "float", 4, + "double", 4, + "long", 4, + "short", 4, + "typedef", 4, + "unsigned", 4, + "register", 4, + "static", 4, + "global", 4, + "extern", 4, + "void", 4, + "goto", 0, + "return", 0, + "if", 5, + "while", 5, + "for", 5, + "else", 6, + "do", 6, + "sizeof", 7, + 0, 0 +}; + +char chartype[128] = +{ /* this is used to facilitate + the decision of what type + (alphanumeric, operator) + each character is */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 3, 3, 0, + 0, 0, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 3, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 0, 3, 0 +}; + + + + +int +lexi() +{ + register char *tok; /* local pointer to next char + in token */ + int unary_delim; /* this is set to 1 if the + current token + + forces a following operator to + be unary */ + static int last_code; /* the last token type returned */ + static int l_struct; /* set to 1 if the last token + was 'struct' */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for + a string */ + + tok = token; /* point to start of place to + save token */ + unary_delim = false; + ps.col_1 = ps.last_nl; /* tell world that this token + started in column 1 iff the + last thing scanned was nl */ + ps.last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') + { /* get rid of blanks */ + ps.col_1 = false; /* leading blanks imply token + is not in column 1 */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + + /* Scan an alphanumeric token */ + if (chartype[*buf_ptr] == alphanum || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) + { + /* we have a character or number */ + register char *j; /* used for searching thru list + of + + reserved words */ + register struct templ *p; + + if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) + { + int seendot = 0, seenexp = 0; + if (*buf_ptr == '0' && + (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) + { + *tok++ = *buf_ptr++; + *tok++ = *buf_ptr++; + while (isxdigit(*buf_ptr)) + *tok++ = *buf_ptr++; + } else + while (1) + { + if (*buf_ptr == '.') + if (seendot) + break; + else + seendot++; + *tok++ = *buf_ptr++; + if (!isdigit(*buf_ptr) && *buf_ptr != '.') + if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) + break; + else + { + seenexp++; + seendot++; + *tok++ = *buf_ptr++; + if (*buf_ptr == '+' || *buf_ptr == '-') + *tok++ = *buf_ptr++; + } + } + if (*buf_ptr == 'L' || *buf_ptr == 'l') + *tok++ = *buf_ptr++; + } else + while (chartype[*buf_ptr] == alphanum) + { /* copy it over */ + *tok++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + *tok++ = '\0'; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + ps.its_a_keyword = false; + ps.sizeof_keyword = false; + if (l_struct) + { /* if last token was 'struct', + then this token should be + treated as a declaration */ + l_struct = false; + last_code = ident; + ps.last_u_d = true; + return (decl); + } + ps.last_u_d = false; /* Operator after indentifier + is binary */ + last_code = ident; /* Remember that this is the + code we will return */ + + /* This loop will check if the token is a keyword. */ + for (p = specials; (j = p->rwd) != 0; p++) + { + tok = token; /* point at scanned token */ + if (*j++ != *tok++ || *j++ != *tok++) + continue; /* This test depends on the + fact that identifiers are + always at least 1 character + long (ie. the first two + bytes of the identifier are + always meaningful) */ + if (tok[-1] == 0) + break; /* If its a one-character + identifier */ + while (*tok++ == *j) + if (*j++ == 0) + goto found_keyword; /* I wish that C had a + multi-level break... */ + } + if (p->rwd) + { /* we have a keyword */ + found_keyword: + ps.its_a_keyword = true; + ps.last_u_d = true; + switch (p->rwcode) + { + case 1: /* it is a switch */ + return (swstmt); + case 2: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + if (ps.p_l_follow) + break; /* inside parens: cast */ + l_struct = true; + + /* Next time around, we will want to know that we have had + a 'struct' */ + case 4: /* one of the declaration + keywords */ + if (ps.p_l_follow) + { + ps.cast_mask |= 1 << ps.p_l_follow; + break; /* inside parens: cast */ + } + last_code = decl; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 7: + ps.sizeof_keyword = true; + default: /* all others are treated like + any other identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) + { + register char *tp = buf_ptr; + while (tp < buf_end) + if (*tp++ == ')' && *tp == ';') + goto not_proc; + strncpy(ps.procname, token, sizeof ps.procname - 1); + ps.in_par_decl = 1; + not_proc:; + } + /* The following hack attempts to guess whether or not the + current token is in fact a declaration keyword -- one that has + been typedefd */ + if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_') + && !ps.p_l_follow + && !ps.block_init + && (ps.last_token == rparen || ps.last_token == semicolon || + ps.last_token == decl || + ps.last_token == lbrace || ps.last_token == rbrace)) + { + ps.its_a_keyword = true; + ps.last_u_d = true; + last_code = decl; + return decl; + } + if (last_code == decl) /* if this is a declared + variable, then following + sign is unary */ + ps.last_u_d = true; /* will make "int a -1" work */ + last_code = ident; + return (ident); /* the ident is not in the list */ + } /* end of procesing for alpanum + character */ + /* l l l Scan a non-alphanumeric token */ + *tok++ = *buf_ptr; /* if it is only a + one-character token, it is + moved here */ + *tok = '\0'; + if (++buf_ptr >= buf_end) + fill_buffer(); + + switch (*token) + { + case '\n': + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember that we just had a + newline */ + code = (had_eof ? 0 : newline); + + /* if data has been exausted, the newline is a dummy, and we + should return code to stop */ + break; + + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + if (troff) + { + tok[-1] = '`'; + if (qchar == '"') + *tok++ = '`'; + tok = chfont(&bodyf, &stringf, tok); + } + do + { /* copy the string */ + while (1) + { /* move one character or + [/] */ + if (*buf_ptr == '\n') + { + printf("%d: Unterminated literal\n", line_no); + goto stop_lit; + } + *tok = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (had_eof || ((tok - token) > (bufsize - 2))) + { + printf("Unterminated literal\n"); + ++tok; + goto stop_lit; + /* get outof literal copying loop */ + } + if (*tok == BACKSLASH) + { /* if escape, copy extra char */ + if (*buf_ptr == '\n') /* check for escaped newline */ + ++line_no; + if (troff) + { + *++tok = BACKSLASH; + if (*buf_ptr == BACKSLASH) + *++tok = BACKSLASH; + } + *++tok = *buf_ptr++; + ++tok; /* we must increment this again + because we copied two chars */ + if (buf_ptr >= buf_end) + fill_buffer(); + } else + break; /* we copied one character */ + } /* end of while (1) */ + } while (*tok++ != qchar); + if (troff) + { + tok = chfont(&stringf, &bodyf, tok - 1); + if (qchar == '"') + *tok++ = '\''; + } +stop_lit: + code = ident; + break; + + case ('('): + case ('['): + unary_delim = true; + code = lparen; + break; + + case (')'): + case (']'): + code = rparen; + break; + + case '#': + unary_delim = ps.last_u_d; + code = preesc; + break; + + case '?': + unary_delim = true; + code = question; + break; + + case (':'): + code = colon; + unary_delim = true; + break; + + case (';'): + unary_delim = true; + code = semicolon; + break; + + case ('{'): + unary_delim = true; + + /* if (ps.in_or_st) ps.block_init = 1; */ + code = ps.block_init ? lparen : lbrace; + break; + + case ('}'): + unary_delim = true; + code = ps.block_init ? rparen : rbrace; + break; + + case 014: /* a form feed */ + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember this so we can set + 'ps.col_1' right */ + code = form_feed; + break; + + case (','): + unary_delim = true; + code = comma; + break; + + case '.': + unary_delim = false; + code = period; + break; + + case '-': + case '+': /* check for -, +, --, ++ */ + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + + if (*buf_ptr == token[0]) + { + /* check for doubled character */ + *tok++ = *buf_ptr++; + /* buffer overflow will be checked at end of loop */ + if (last_code == ident || last_code == rparen) + { + code = (ps.last_u_d ? unary_op : postop); + /* check for following ++ or -- */ + unary_delim = false; + } + } else if (*buf_ptr == '=') + /* check for operator += */ + *tok++ = *buf_ptr++; + else if (*buf_ptr == '>') + { + /* check for operator -> */ + *tok++ = *buf_ptr++; + if (!ptr_binop) + { + unary_delim = false; + code = unary_op; + ps.want_blank = false; + } + } + break; /* buffer overflow will be + checked at end of switch */ + + case '=': + if (ps.in_or_st) + ps.block_init = 1; +#ifdef undef + if (chartype[*buf_ptr] == opchar) + { /* we have two char assignment */ + tok[-1] = *buf_ptr++; + if ((tok[-1] == '<' || tok[-1] == '>') && tok[-1] == *buf_ptr) + *tok++ = *buf_ptr++; + *tok++ = '='; /* Flip =+ to += */ + *tok = 0; + } +#else + if (*buf_ptr == '=') + { /* == */ + *tok++ = '='; /* Flip =+ to += */ + buf_ptr++; + *tok = 0; + } +#endif + code = binary_op; + unary_delim = true; + break; + /* can drop thru!!! */ + + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ + if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') + { + *tok++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + if (*buf_ptr == '=') + *tok++ = *buf_ptr++; + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + break; + + default: + if (token[0] == '/' && *buf_ptr == '*') + { + /* it is start of comment */ + *tok++ = '*'; + + if (++buf_ptr >= buf_end) + fill_buffer(); + + code = comment; + unary_delim = ps.last_u_d; + break; + } + while (*(tok - 1) == *buf_ptr || *buf_ptr == '=') + { + /* handle ||, &&, etc, and also things as in int *****i */ + *tok++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + + + } /* end of switch */ + if (code != newline) + { + l_struct = false; + last_code = code; + } + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + ps.last_u_d = unary_delim; + *tok = '\0'; /* null terminate the token */ + return (code); +} + +/* + * Add the given keyword to the keyword table, using val as the keyword type + */ +void addkey(key, val) + char *key; + int val; +{ + register struct templ *p = specials; + while (p->rwd) + if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0) + return; + else + p++; + if (p >= specials + sizeof specials / sizeof specials[0]) + return; /* For now, table overflows are + silently ignored */ + p->rwd = key; + p->rwcode = val; + p[1].rwd = 0; + p[1].rwcode = 0; + return; +} diff --git a/commands/indent/parse.c b/commands/indent/parse.c new file mode 100644 index 000000000..18d22a42e --- /dev/null +++ b/commands/indent/parse.c @@ -0,0 +1,319 @@ +/** + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley, the University of Illinois, + * Urbana, and Sun Microsystems, Inc. The name of either University + * or Sun Microsystems may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define PUBLIC extern +#include "./globs.h" +#include "./codes.h" +#include "proto.h" + + + + +void parse(tk) + int tk; /* the code for the construct + scanned */ +{ + int i; + +#ifdef debug + printf("%2d - %s\n", tk, token); +#endif + + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) + { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= + stmt reduction */ + reduce(); /* see if this allows any + reduction */ + } + + + switch (tk) + { /* go on and figure out what to + do with the input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) + { /* only put one declaration + onto stack */ + break_comma = true; /* while in declaration, + newline should be forced + after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) + { /* only do if we want left + justified declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number of + declaration levels deep we + are */ + ps.i_l_follow = ps.ind_level; + } + } + break; + + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + ps.i_l_follow = ps.il[ps.tos]; + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should + be indented 1 */ + ps.search_brace = btype_2; + break; + + case lbrace: /* scanned { */ + break_comma = false; /* don't break comma in an + initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated + stmt group or a declaration */ + else + { + if (s_code == e_code) + { + /* only do this if there is nothing on the line */ + --ps.ind_level; + /* it is a group as part of a while, for, etc. */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) + --ps.ind_level; + /* for a switch, brace should be two levels out from the + code */ + } + } + + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; + break; + + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) + { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + } else + { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; + } + + break; + + case elselit: /* scanned an else */ + + if (ps.p_stack[ps.tos] != ifhead) + diag(1, "Unmatched 'else'"); + else + { + ps.ind_level = ps.il[ps.tos]; /* indentation for else should + be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following + should be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2 | ps.else_if; + } + break; + + case rbrace: /* scanned a } */ + /* stack should have or */ + if (ps.p_stack[ps.tos - 1] == lbrace) + { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; + } else + diag(1, "Stmt nesting error."); + break; + + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + level down from + switch */ + ps.i_l_follow += ps.case_indent + 1; /* statements should be + two levels in */ + ps.search_brace = btype_2; + break; + + case semicolon: /* this indicates a simple stmt */ + break_comma = false; /* turn off flag to break after + commas in a declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; + break; + + default: /* this is an error */ + diag(1, "Unknown code to parser"); + return; + + + } /* end of switch */ + + reduce(); /* see if any reduction can be + done */ + +#ifdef debug + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); +#endif + + return; +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated until + * no more are possible. + * + * Old TOS New TOS do + * "dostmt" if "ifstmt" switch decl + * "ifelse" for while + * "dostmt" while + * + * On each reduction, ps.i_l_follow (the indentation for the following line) is + * set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +/*----------------------------------------------*\ +| REDUCTION PHASE | +\*----------------------------------------------*/ +void reduce() +{ + + register int i; + + for (;;) + { /* keep looping until there is + nothing left to reduce */ + + switch (ps.p_stack[ps.tos]) + { + + case stmt: + switch (ps.p_stack[ps.tos - 1]) + { + + case stmt: + case stmtl: + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; + break; + + case dolit: /* */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + break; + + case ifstmt: + /* */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; + ( + ps.p_stack[i] != stmt + && + ps.p_stack[i] != stmtl + && + ps.p_stack[i] != lbrace + ); + --i); + ps.i_l_follow = ps.il[i]; + /* for the time being, we will assume that there is no else + on this if, and set the indentation level accordingly. + If an else is scanned, it will be fixed up later */ + break; + + case swstmt: + /* */ + case_ind = ps.cstk[ps.tos - 1]; + + case decl: /* finish of a declaration */ + case elsehead: + /* < else> */ + case forstmt: + /* */ + case whilestmt: + /* */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + break; + + default: /* */ + return; + + } /* end of section for on + top of stack */ + break; + + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) + { + /* it is termination of a do while */ + ps.p_stack[--ps.tos] = stmt; + break; + } else + return; + + default: /* anything else on top */ + return; + + } + } +} diff --git a/commands/indent/proto.h b/commands/indent/proto.h new file mode 100644 index 000000000..4aaa2d1a4 --- /dev/null +++ b/commands/indent/proto.h @@ -0,0 +1,26 @@ +/* _PROTOTYPE( void diag, (int level,char *msg, int a, int b) ); */ +void diag(); /* HACK. should be varargs */ + +_PROTOTYPE( void set_profile, (void ) ); +_PROTOTYPE( void scan_profile, (FILE *f) ); +_PROTOTYPE( int eqin, (char *s1,char *s2) ); +_PROTOTYPE( void set_defaults, (void ) ); +_PROTOTYPE( void set_option, (char *arg) ); +_PROTOTYPE( void pr_comment, (void ) ); +_PROTOTYPE( void main, (int argc,char * *argv) ); +_PROTOTYPE( void bakcopy, (void ) ); +_PROTOTYPE( void dump_line, (void ) ); +_PROTOTYPE( int code_target, (void ) ); +_PROTOTYPE( int label_target, (void ) ); +_PROTOTYPE( void fill_buffer, (void ) ); +_PROTOTYPE( int pad_output, (int current,int target) ); +_PROTOTYPE( int count_spaces, (int current,char *buffer) ); +_PROTOTYPE( void writefdef, (struct fstate *f,int nm) ); +_PROTOTYPE( char *chfont, (struct fstate *of,struct fstate *nf,char *s) ); +_PROTOTYPE( void parsefont, (struct fstate *f,char *s0) ); +_PROTOTYPE( int lexi, (void ) ); +_PROTOTYPE( void addkey, (char *key,int val) ); +_PROTOTYPE( void makext, (char *newname,char *newext) ); +_PROTOTYPE( void parse, (int tk) ); +_PROTOTYPE( void reduce, (void ) ); +