]> Zhao Yanbai Git Server - minix.git/commitdiff
Imported indent
authorBen Gras <ben@minix3.org>
Fri, 22 Jul 2005 18:30:14 +0000 (18:30 +0000)
committerBen Gras <ben@minix3.org>
Fri, 22 Jul 2005 18:30:14 +0000 (18:30 +0000)
commands/indent/Makefile [new file with mode: 0644]
commands/indent/args.c [new file with mode: 0644]
commands/indent/codes.h [new file with mode: 0644]
commands/indent/comment.c [new file with mode: 0644]
commands/indent/globs.h [new file with mode: 0644]
commands/indent/indent.c [new file with mode: 0644]
commands/indent/indent.pro [new file with mode: 0644]
commands/indent/io.c [new file with mode: 0644]
commands/indent/lexi.c [new file with mode: 0644]
commands/indent/parse.c [new file with mode: 0644]
commands/indent/proto.h [new file with mode: 0644]

diff --git a/commands/indent/Makefile b/commands/indent/Makefile
new file mode 100644 (file)
index 0000000..e228f65
--- /dev/null
@@ -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 (file)
index 0000000..729452d
--- /dev/null
@@ -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 <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#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 (file)
index 0000000..1afea04
--- /dev/null
@@ -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 (file)
index 0000000..a4625a4
--- /dev/null
@@ -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
+ *
+ */\f
+
+/*
+ * 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 <stdlib.h>
+#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 (file)
index 0000000..cfd5878
--- /dev/null
@@ -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 <stdio.h>
+
+#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 (file)
index 0000000..b7b4a3e
--- /dev/null
@@ -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 <hall@pnet01.cts.com>  */
+
+#define _POSIX_SOURCE 1
+#define        PUBLIC
+#define NAME_SIZE _POSIX_NAME_MAX
+
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#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 <c>?<s>:<s>
+                                          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
+                                          <c>?<n>:<n> 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 <c>?<n>:
+                                          <n> 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 (file)
index 0000000..f1784e6
--- /dev/null
@@ -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 (file)
index 0000000..67a2781
--- /dev/null
@@ -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 <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#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
+ *
+ */\f
+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
+ *
+ */\f
+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
+ *
+ */\f
+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 '\b':                                /* 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 (file)
index 0000000..6cf42c8
--- /dev/null
@@ -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 <ctype.h>
+#include <string.h>
+#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
+                                          [/<char>]<char> */
+           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 (file)
index 0000000..18d22a4
--- /dev/null
@@ -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 <lbrace> <stmt> or <lbrace> <stmtl> */
+      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 <stmt> <stmt>   <stmtl> <stmtl> <stmt>  <stmtl> do
+ * <stmt>      "dostmt" if <stmt>      "ifstmt" switch <stmt>  <stmt> decl
+ * <stmt>      <stmt> "ifelse" <stmt>  <stmt> for <stmt>       <stmt> while
+ * <stmt>      <stmt> "dostmt" while   <stmt>
+ *
+ * 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
+ *
+ */\f
+/*----------------------------------------------*\
+|   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:                    /* <do> <stmt> */
+           ps.p_stack[--ps.tos] = dohead;
+           ps.i_l_follow = ps.il[ps.tos];
+           break;
+
+        case ifstmt:
+           /* <if> <stmt> */
+           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:
+           /* <switch> <stmt> */
+           case_ind = ps.cstk[ps.tos - 1];
+
+        case decl:                     /* finish of a declaration */
+        case elsehead:
+           /* <<if> <stmt> else> <stmt> */
+        case forstmt:
+           /* <for> <stmt> */
+        case whilestmt:
+           /* <while> <stmt> */
+           ps.p_stack[--ps.tos] = stmt;
+           ps.i_l_follow = ps.il[ps.tos];
+           break;
+
+        default:                       /* <anything else> <stmt> */
+           return;
+
+        }                              /* end of section for <stmt> 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 (file)
index 0000000..4aaa2d1
--- /dev/null
@@ -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 )    );
+