Re: adding feature to indent

Jean-Christophe Dubois <[email protected]>
Newsgroups gmane.comp.gnu.indent.bugs
Message-ID <[email protected]>
On Thursday 17 May 2007 19:02:14 david wrote:
> Jean-Christophe,
> Please send the update again. The bug-indent filter seems to have
> removed your attachment.
> I would prefer it if you send the whole updated files rather than
> patches as then I can see your updates in the context of the version of
> the file you actually updated - which may be older than the current SVN
> head. 

So here is the diff again and the 3 files as a whole. My source base is the 
FC5 indent package.

I'll study how to update documentation (man, info, ...).

JC

_______________________________________________
bug-indent mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-indent
indent.diff (text/x-diff, 6.3 KB)
diff -rNu indent-2.2.9.org/src/args.c indent-2.2.9/src/args.c
--- indent-2.2.9.org/src/args.c	2002-11-10 22:02:48.000000000 +0100
+++ indent-2.2.9/src/args.c	2007-05-17 10:08:17.000000000 +0200
@@ -62,6 +62,11 @@
      "-ce\0-ci4\0-cli0\0-cp33\0-di16\0-fc1\0-fca\0-i4\0-l75\0-lp\0-npcs\0-nprs\0" \
      "-psl\0-sc\0-sai\0-saf\0-saw\0-nsob\0-nss\0-ts8\0"
 
+#define LINUX_SETTINGS_STRING (int *) \
+     "-nbad\0-bap\0-nbc\0-bbo\0-hnl\0-br\0-brs\0-c33\0-cd33\0" \
+     "-ncdb\0-ce\0-ci4\0-cli0\0-d0\0-di1\0-nfc1\0-i8\0-ip0\0-l80\0-lp\0" \
+     "-npcs\0-nprs\0-npsl\0-sai\0-saf\0-saw\0-ncs\0-nsc\0-sob\0-nfca\0-cp33\0-ss\0" \
+     "-ts8\0-il1\0"
 
 /* profile types */
 typedef enum profile
@@ -121,9 +126,11 @@
 static int exp_gnu  = 0;
 static int exp_hnl  = 0;
 static int exp_i    = 0;
+static int exp_il   = 0;
 static int exp_ip   = 0;
 static int exp_kr   = 0;
 static int exp_l    = 0;
+static int exp_linux = 0;
 static int exp_lc   = 0;
 static int exp_lp   = 0;
 static int exp_lps  = 0;
@@ -250,11 +257,13 @@
     {"nbadp",   PRO_BOOL,                           false,      OFF, &settings.blanklines_after_declarations_at_proctop,  &exp_badp},
     {"nbad",    PRO_BOOL,                           false,      OFF, &settings.blanklines_after_declarations,    &exp_bad},
     {"nbacc",   PRO_BOOL,                           false,      OFF, &settings.blanklines_around_conditional_compilation, &exp_bacc},
+    {"linux",   PRO_SETTINGS,                           0, ONOFF_NA, LINUX_SETTINGS_STRING,                      &exp_linux},
     {"lps",     PRO_BOOL,                           false,       ON, &settings.leave_preproc_space,              &exp_lps},
     {"lp",      PRO_BOOL,                            true,       ON, &settings.lineup_to_parens,                 &exp_lp},
     {"lc",      PRO_INT,     DEFAULT_RIGHT_COMMENT_MARGIN, ONOFF_NA, &settings.comment_max_col,                  &exp_lc},
     {"l",       PRO_INT,             DEFAULT_RIGHT_MARGIN, ONOFF_NA, &settings.max_col,                          &exp_l},
     {"kr",      PRO_SETTINGS,                           0, ONOFF_NA, KR_SETTINGS_STRING,                         &exp_kr},
+    {"il",      PRO_INT,                                0, ONOFF_NA, &settings.label_offset,                     &exp_il},
     {"ip",      PRO_INT,                                4, ONOFF_NA, &settings.indent_parameters,                &exp_ip},
     {"i",       PRO_INT,                                4, ONOFF_NA, &settings.ind_size,                         &exp_i},
     {"hnl",     PRO_BOOL,                            true,       ON, &settings.honour_newlines,                  &exp_hnl},
@@ -363,11 +372,13 @@
     {"nbadp",   PRO_BOOL,                           false,      OFF, &settings.blanklines_after_declarations_at_proctop,  &exp_badp},
     {"nbad",    PRO_BOOL,                           false,      OFF, &settings.blanklines_after_declarations,    &exp_bad},
     {"nbacc",   PRO_BOOL,                           false,      OFF, &settings.blanklines_around_conditional_compilation, &exp_bacc},
+    {"linux",   PRO_SETTINGS,                           0, ONOFF_NA, LINUX_SETTINGS_STRING,                      &exp_linux},
     {"lps",     PRO_BOOL,                           false,       ON, &settings.leave_preproc_space,              &exp_lps},
     {"lp",      PRO_BOOL,                            true,       ON, &settings.lineup_to_parens,                 &exp_lp},
     {"lc",      PRO_INT,     DEFAULT_RIGHT_COMMENT_MARGIN, ONOFF_NA, &settings.comment_max_col,                  &exp_lc},
     {"l",       PRO_INT,             DEFAULT_RIGHT_MARGIN, ONOFF_NA, &settings.max_col,                          &exp_l},
     {"kr",      PRO_SETTINGS,                           0, ONOFF_NA, KR_SETTINGS_STRING,                         &exp_kr},
+    {"il",      PRO_INT,                                0, ONOFF_NA, &settings.label_offset,                     &exp_il},
     {"ip",      PRO_INT,                                5, ONOFF_NA, &settings.indent_parameters,                &exp_ip},
     {"i",       PRO_INT,                                2, ONOFF_NA, &settings.ind_size,                         &exp_i},
     {"hnl",     PRO_BOOL,                            true,       ON, &settings.honour_newlines,                  &exp_hnl},
@@ -470,14 +481,17 @@
     {"no-blank-lines-after-commas",                 "nbc"},
     {"no-blank-before-sizeof",                      "nbs"},
     {"no-Bill-Shannon",                             "nbs"},
+    {"label-offset",                                "il"},
     {"line-length",                                 "l"},
     {"line-comments-indentation",                   "d"},
+    {"linux-style",                                 "linux"},
     {"left-justify-declarations",                   "dj"},
     {"leave-preprocessor-space",                    "lps"},
     {"leave-optional-blank-lines",                  "nsob"},
     {"kernighan-and-ritchie-style",                 "kr"},
     {"kernighan-and-ritchie",                       "kr"},
     {"k-and-r-style",                               "kr"},
+    {"indent-label",                                "il"},
     {"indentation-level",                           "i"},
     {"indent-level",                                "i"},
     {"ignore-profile",                              "npro"},
diff -rNu indent-2.2.9.org/src/indent.h indent-2.2.9/src/indent.h
--- indent-2.2.9.org/src/indent.h	2007-05-16 21:16:17.000000000 +0200
+++ indent-2.2.9/src/indent.h	2007-05-17 10:08:15.000000000 +0200
@@ -229,6 +229,7 @@
     int blanklines_around_conditional_compilation;
     int comment_max_col;
     int max_col;             /* the maximum allowable line length */
+    int label_offset;        /* offset of labels */
     int ind_size; /* The size of one indentation level in spaces.  */
     int indent_parameters; /* Number of spaces to indent parameters.  */
     int decl_indent;         /* column to indent declared identifiers to */
diff -rNu indent-2.2.9.org/src/io.c indent-2.2.9/src/io.c
--- indent-2.2.9.org/src/io.c	2002-08-04 19:08:41.000000000 +0200
+++ indent-2.2.9/src/io.c	2007-05-17 10:08:16.000000000 +0200
@@ -312,6 +312,10 @@
         /* FIXME: does this belong here at all? */
         return 1;
     }
+    else if (settings.label_offset)
+    {
+        return settings.label_offset;
+    } 
     else
     {
         return parser_state_tos->ind_level - LABEL_OFFSET + 1;
args.c (text/x-csrc, 52.8 KB)
/* Copyright (c) 1999, 2000 Carlo Wood.  All rights reserved.
 * Copyright (c) 1994 Joseph Arceneaux.  All rights reserved.
 * Copyright (c) 1992 Free Software Foundation, Inc.  All rights reserved.
 *
 * Copyright (c) 1985 Sun Microsystems, Inc.
 * Copyright (c) 1980 The Regents of the University of California.
 * Copyright (c) 1976 Board of Trustees ofthe 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.
*
 *
 * HISTORY
 * 2002-03-14 DI restructured scan_profile and fixed bug handling comments
 * 2002-06-13 DI fixed handling of missing int parameter.
 * 2002-08-05 Matthias <[email protected]> and Eric Lloyd <[email protected]>
 *            Added support for -brf to place function opening brace after function
 *            declaration.
 * 2002-11-10 Cristalle Azundris Sabon <[email protected]>
 *            Added --preprocessor-indentation (ppi)   if set, will indent nested
 *            preprocessor-statements with n spaces per level.  overrides -lps.
 */

/* Argument scanning and profile reading code.  Default parameters are set
 * here as well. */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sys.h"
#include "indent.h"
#include "args.h"
#include "globs.h"

RCSTAG_CC ("$Id: args.c,v 1.42 2002/11/10 21:02:48 david Exp $");

#define KR_SETTINGS_STRING (int *) \
     "-nbad\0-bap\0-nbc\0-bbo\0-hnl\0-br\0-brs\0-c33\0-cd33\0" \
     "-ncdb\0-ce\0-ci4\0-cli0\0-d0\0-di1\0-nfc1\0-i4\0-ip0\0-l75\0-lp\0" \
     "-npcs\0-nprs\0-npsl\0-sai\0-saf\0-saw\0-cs\0-nsc\0-nsob\0-nfca\0-cp33\0-nss\0"

#define GNU_SETTINGS_STRING  (int *) \
     "-nbad\0-bap\0-bbo\0-hnl\0-nbc\0-bl\0-bls\0-ncdb\0-cs\0-nce\0" \
     "-di2\0-ndj\0-nfc1\0-i2\0-ip5\0-lp\0-pcs\0-nprs\0-psl\0-nsc\0-sai\0-saf\0-saw\0-nsob\0" \
     "-bli2\0-cp1\0-nfca\0"

#define ORIG_SETTINGS_STRING (int *) \
     "-nbap\0-nbad\0-bbo\0-hnl\0-bc\0-br\0-brs\0-c33\0-cd33\0-cdb\0" \
     "-ce\0-ci4\0-cli0\0-cp33\0-di16\0-fc1\0-fca\0-i4\0-l75\0-lp\0-npcs\0-nprs\0" \
     "-psl\0-sc\0-sai\0-saf\0-saw\0-nsob\0-nss\0-ts8\0"

#define LINUX_SETTINGS_STRING (int *) \
     "-nbad\0-bap\0-nbc\0-bbo\0-hnl\0-br\0-brs\0-c33\0-cd33\0" \
     "-ncdb\0-ce\0-ci4\0-cli0\0-d0\0-di1\0-nfc1\0-i8\0-ip0\0-l80\0-lp\0" \
     "-npcs\0-nprs\0-npsl\0-sai\0-saf\0-saw\0-ncs\0-nsc\0-sob\0-nfca\0-cp33\0-ss\0" \
     "-ts8\0-il1\0"

/* profile types */
typedef enum profile
{
    PRO_BOOL,                     /* boolean */
    PRO_INT,                      /* integer */
    PRO_IGN,                      /* ignore it */
    PRO_KEY,                      /* -T switch */
    PRO_SETTINGS,                 /* bundled set of settings */
    PRO_PRSTRING,                 /* Print string and exit */
    PRO_FUNCTION                  /* Call the associated function. */
} profile_ty;

/* profile specials for booleans */
typedef enum on_or_off
{
    ONOFF_NA,                     /* Not applicable.  Used in table for
                                   * non-booleans.  */
    OFF,                          /* This option turns on the boolean variable
                                   * in question.  */
    ON                            /* it turns it off */
} on_or_off_ty;

/* Explicit flags for each option.  */
static int exp_T    = 0;
static int exp_bacc = 0;
static int exp_badp = 0;
static int exp_bad  = 0;
static int exp_bap  = 0;
static int exp_bbb  = 0;
static int exp_bbo  = 0;
static int exp_bc   = 0;
static int exp_bl   = 0;
static int exp_blf  = 0;
static int exp_bli  = 0;
static int exp_bls  = 0;
static int exp_bs   = 0;
static int exp_c    = 0;
static int exp_cbi  = 0;
static int exp_cdb  = 0;
static int exp_cd   = 0;
static int exp_cdw  = 0;
static int exp_ce   = 0;
static int exp_ci   = 0;
static int exp_cli  = 0;
static int exp_cp   = 0;
static int exp_cpp  = 0;
static int exp_cs   = 0;
static int exp_d    = 0;
static int exp_bfda = 0;
static int exp_bfde = 0;
static int exp_di   = 0;
static int exp_dj   = 0;
static int exp_eei  = 0;
static int exp_fc1  = 0;
static int exp_fca  = 0;
static int exp_gnu  = 0;
static int exp_hnl  = 0;
static int exp_i    = 0;
static int exp_il   = 0;
static int exp_ip   = 0;
static int exp_kr   = 0;
static int exp_l    = 0;
static int exp_linux = 0;
static int exp_lc   = 0;
static int exp_lp   = 0;
static int exp_lps  = 0;
static int exp_nip  = 0; 
static int exp_o    = 0;
static int exp_orig = 0;
static int exp_pcs  = 0;
static int exp_pi   = 0;
static int exp_pmt  = 0;
static int exp_pro  = 0;
static int exp_prs  = 0;
static int exp_psl  = 0;
static int exp_ppi  = 0;  /* force preprocessor indent at width... */
static int exp_sai  = 0;
static int exp_saf  = 0;
static int exp_saw  = 0;
static int exp_sbi  = 0;
static int exp_sc   = 0;
static int exp_sob  = 0;
static int exp_ss   = 0;
static int exp_st   = 0;
static int exp_ts   = 0;
static int exp_ut   = 0;
static int exp_v    = 0;
static int exp_version = 0;

/* The following structure is controlled by command line parameters and
 * their meaning is explained in indent.h.  */

user_options_ty settings = {0};

static void usage (void);

/* 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. */

typedef struct pro
{
    char       * p_name;        /* option name, e.g. "bl", "cli" */
    profile_ty   p_type;        /* profile type */
    int          p_default;     /* the default value (if PRO_BOOL or PRO_INT) */

    on_or_off_ty p_special;     /* If p_type == PRO_BOOL, ON or OFF to tell how
                                 * this switch affects the variable. Not used
                                 * for other p_type's.  */

    int        * p_obj;         /* if p_type == PRO_SETTINGS, a (char *) pointing
                                 *    to a list of the switches to set, separated by
                                 *    NULLs, terminated by 2 NULLs.
                                 * if p_type ==PRO_BOOL or PRO_INT, the address of
                                 *     the variable that gets set by the option.
                                 * if p_type == PRO_PRSTRING, a (char *) pointing
                                 *     to the string.
                                 * if p_type == PRO_FUNCTION, a pointer to a
                                 *     function to be called. */

  int          * p_explicit;    /* Points to a nonzero value (allocated statically
                                 * for all options) if the option has been specified
                                 * explicitly.  This is necessary because for
                                 * boolean options, the options to set and reset the
                                 * variable must share the explicit flag.  */
} pro_ty;

#ifdef BERKELEY_DEFAULTS
/* Settings for original defaults */
const pro_ty pro[] =
{
    {"version", PRO_PRSTRING,                           0, ONOFF_NA, (int *) VERSION,                            &exp_version},
    {"v",       PRO_BOOL,                           false,       ON, &settings.verbose,                          &exp_v},
    {"ut",      PRO_BOOL,                            true,       ON, &settings.use_tabs,                         &exp_ut},
    {"ts",      PRO_INT,                                8, ONOFF_NA, &settings.tabsize,                          &exp_ts},
    {"st",      PRO_BOOL,                           false,       ON, &settings.use_stdout,                       &exp_st},
    {"ss",      PRO_BOOL,                           false,       ON, &settings.space_sp_semicolon,               &exp_ss},
    {"sob",     PRO_BOOL,                           false,       ON, &settings.swallow_optional_blanklines,      &exp_sob},
    {"sc",      PRO_BOOL,                            true,       ON, &settings.star_comment_cont,                &exp_sc},
    {"sbi",     PRO_INT,                                0, ONOFF_NA, &settings.struct_brace_indent,              &exp_sbi},
    {"saw",     PRO_BOOL,                            true,       ON, &settings.space_after_while,                &exp_saw},
    {"sai",     PRO_BOOL,                            true,       ON, &settings.space_after_if,                   &exp_sai},
    {"saf",     PRO_BOOL,                            true,       ON, &settings.space_after_for,                  &exp_saf},
    {"psl",     PRO_BOOL,                            true,       ON, &settings.procnames_start_line,             &exp_psl},
    {"prs",     PRO_BOOL,                           false,       ON, &settings.parentheses_space,                &exp_prs},
#ifdef PRESERVE_MTIME
    {"pmt",     PRO_BOOL,                           false,       ON, &settings.preserve_mtime,                   &exp_pmt},
#endif
    {"pi",      PRO_INT,                               -1, ONOFF_NA, &settings.paren_indent,                     &exp_pi},
    {"pcs",     PRO_BOOL,                           false,       ON, &settings.proc_calls_space,                 &exp_pcs},
    {"o",       PRO_BOOL,                           false,       ON, &settings.expect_output_file,               &exp_o},
    {"nv",      PRO_BOOL,                           false,      OFF, &settings.verbose,                          &exp_v},
    {"nut",     PRO_BOOL,                            true,      OFF, &settings.use_tabs,                         &exp_ut},
    {"nss",     PRO_BOOL,                           false,      OFF, &settings.space_sp_semicolon,               &exp_ss},
    {"nsob",    PRO_BOOL,                           false,      OFF, &settings.swallow_optional_blanklines,      &exp_sob},
    {"nsc",     PRO_BOOL,                            true,      OFF, &settings.star_comment_cont,                &exp_sc},
    {"nsaw",    PRO_BOOL,                            true,      OFF, &settings.space_after_while,                &exp_saw},
    {"nsai",    PRO_BOOL,                            true,      OFF, &settings.space_after_if,                   &exp_sai},
    {"nsaf",    PRO_BOOL,                            true,      OFF, &settings.space_after_for,                  &exp_saf},
    {"npsl",    PRO_BOOL,                            true,      OFF, &settings.procnames_start_line,             &exp_psl},
    {"nprs",    PRO_BOOL,                           false,      OFF, &settings.parentheses_space,                &exp_prs},
    {"npro",    PRO_IGN,                                0, ONOFF_NA, 0,                                          &exp_pro},
#ifdef PRESERVE_MTIME
    {"npmt",    PRO_BOOL,                           false,      OFF, &settings.preserve_mtime,                   &exp_pmt},
#endif
    {"npcs",    PRO_BOOL,                           false,      OFF, &settings.proc_calls_space,                 &exp_pcs},
    {"nlps",    PRO_BOOL,                           false,      OFF, &settings.leave_preproc_space,              &exp_lps},
    {"nlp",     PRO_BOOL,                            true,      OFF, &settings.lineup_to_parens,                 &exp_lp},
    {"nip",     PRO_SETTINGS,                           0, ONOFF_NA, (int *) "-ip0",                             &exp_nip},
    {"nhnl",    PRO_BOOL,                            true,      OFF, &settings.honour_newlines,                  &exp_hnl},
    {"nfca",    PRO_BOOL,                            true,      OFF, &settings.format_comments,                  &exp_fca},
    {"nfc1",    PRO_BOOL,                            true,      OFF, &settings.format_col1_comments,             &exp_fc1},
    {"neei",    PRO_BOOL,                           false,      OFF, &settings.extra_expression_indent,          &exp_eei},
    {"ndj",     PRO_BOOL,                           false,      OFF, &settings.ljust_decl,                       &exp_dj},
    {"ncs",     PRO_BOOL,                            true,      OFF, &settings.cast_space,                       &exp_cs},
    {"nce",     PRO_BOOL,                            true,      OFF, &settings.cuddle_else,                      &exp_ce},
    {"ncdw",    PRO_BOOL,                           false,      OFF, &settings.cuddle_do_while,                  &exp_cdw},
    {"ncdb",    PRO_BOOL,                            true,      OFF, &settings.comment_delimiter_on_blankline,   &exp_cdb},
    {"nbs",     PRO_BOOL,                           false,      OFF, &settings.blank_after_sizeof,               &exp_bs},
    {"nbfda",   PRO_BOOL,                           false,      OFF, &settings.break_function_decl_args,         &exp_bfda},
    {"nbfde",   PRO_BOOL,                           false,      OFF, &settings.break_function_decl_args_end,     &exp_bfde},
    {"nbc",     PRO_BOOL,                            true,       ON, &settings.leave_comma,                      &exp_bc},
    {"nbbo",    PRO_BOOL,                            true,      OFF, &settings.break_before_boolean_operator,    &exp_bbo},
    {"nbbb",    PRO_BOOL,                           false,      OFF, &settings.blanklines_before_blockcomments,  &exp_bbb},
    {"nbap",    PRO_BOOL,                           false,      OFF, &settings.blanklines_after_procs,           &exp_bap},
    {"nbadp",   PRO_BOOL,                           false,      OFF, &settings.blanklines_after_declarations_at_proctop,  &exp_badp},
    {"nbad",    PRO_BOOL,                           false,      OFF, &settings.blanklines_after_declarations,    &exp_bad},
    {"nbacc",   PRO_BOOL,                           false,      OFF, &settings.blanklines_around_conditional_compilation, &exp_bacc},
    {"linux",   PRO_SETTINGS,                           0, ONOFF_NA, LINUX_SETTINGS_STRING,                      &exp_linux},
    {"lps",     PRO_BOOL,                           false,       ON, &settings.leave_preproc_space,              &exp_lps},
    {"lp",      PRO_BOOL,                            true,       ON, &settings.lineup_to_parens,                 &exp_lp},
    {"lc",      PRO_INT,     DEFAULT_RIGHT_COMMENT_MARGIN, ONOFF_NA, &settings.comment_max_col,                  &exp_lc},
    {"l",       PRO_INT,             DEFAULT_RIGHT_MARGIN, ONOFF_NA, &settings.max_col,                          &exp_l},
    {"kr",      PRO_SETTINGS,                           0, ONOFF_NA, KR_SETTINGS_STRING,                         &exp_kr},
    {"il",      PRO_INT,                                0, ONOFF_NA, &settings.label_offset,                     &exp_il},
    {"ip",      PRO_INT,                                4, ONOFF_NA, &settings.indent_parameters,                &exp_ip},
    {"i",       PRO_INT,                                4, ONOFF_NA, &settings.ind_size,                         &exp_i},
    {"hnl",     PRO_BOOL,                            true,       ON, &settings.honour_newlines,                  &exp_hnl},
    {"h",       PRO_FUNCTION,                           0, ONOFF_NA, (int *) usage,                              &exp_version},
    {"gnu",     PRO_SETTINGS,                           0, ONOFF_NA, GNU_SETTINGS_STRING,                        &exp_gnu},
    {"fca",     PRO_BOOL,                            true,       ON, &settings.format_comments,                  &exp_fca},
    {"fc1",     PRO_BOOL,                            true,       ON, &settings.format_col1_comments,             &exp_fc1},
    {"eei",     PRO_BOOL,                           false,       ON, &settings.extra_expression_indent,          &exp_eei},
    {"dj",      PRO_BOOL,                           false,       ON, &settings.ljust_decl,                       &exp_dj},
    {"di",      PRO_INT,                               16, ONOFF_NA, &settings.decl_indent,                      &exp_di},
    {"d",       PRO_INT,                                0, ONOFF_NA, &settings.unindent_displace,                &exp_d},
    {"cs",      PRO_BOOL,                            true,       ON, &settings.cast_space,                       &exp_cs},
    {"cp",      PRO_INT,                               33, ONOFF_NA, &settings.else_endif_col,                   &exp_cp},
    {"cli",     PRO_INT,                                0, ONOFF_NA, &settings.case_indent,                      &exp_cli},
    {"ci",      PRO_INT,                                4, ONOFF_NA, &settings.continuation_indent,              &exp_ci},
    {"ce",      PRO_BOOL,                            true,       ON, &settings.cuddle_else,                      &exp_ce},
    {"cdw",     PRO_BOOL,                           false,       ON, &settings.cuddle_do_while,                  &exp_cdw},
    {"cdb",     PRO_BOOL,                            true,       ON, &settings.comment_delimiter_on_blankline,   &exp_cdb},
    {"cd",      PRO_INT,                               33, ONOFF_NA, &settings.decl_com_ind,                     &exp_cd},
    {"cbi",     PRO_INT,                               -1, ONOFF_NA, &settings.case_brace_indent,                &exp_cbi},
    {"c++",     PRO_BOOL,                           false,       ON, &settings.c_plus_plus,                      &exp_cpp},
    {"c",       PRO_INT,                               33, ONOFF_NA, &settings.com_ind,                          &exp_c},
    {"bs",      PRO_BOOL,                           false,       ON, &settings.blank_after_sizeof,               &exp_bs},
    {"brs",     PRO_BOOL,                            true,       ON, &settings.braces_on_struct_decl_line,       &exp_bls},
    {"brf",     PRO_BOOL,                           false,       ON, &settings.braces_on_func_def_line,		 &exp_blf},
    {"br",      PRO_BOOL,                            true,       ON, &settings.btype_2,                          &exp_bl},
    {"bls",     PRO_BOOL,                            true,      OFF, &settings.braces_on_struct_decl_line,       &exp_bls},
    {"blf",     PRO_BOOL,                           false,      OFF, &settings.braces_on_func_def_line,          &exp_blf},
    {"bli",     PRO_INT,                                0, ONOFF_NA, &settings.brace_indent,                     &exp_bli},
    {"bl",      PRO_BOOL,                            true,      OFF, &settings.btype_2,                          &exp_bl},
    {"bfda",    PRO_BOOL,                           false,       ON, &settings.break_function_decl_args,         &exp_bfda},
    {"bfde",    PRO_BOOL,                           false,       ON, &settings.break_function_decl_args_end,     &exp_bfde},
    {"bc",      PRO_BOOL,                            true,      OFF, &settings.leave_comma,                      &exp_bc},
    {"bbo",     PRO_BOOL,                            true,       ON, &settings.break_before_boolean_operator,    &exp_bbo},
    {"bbb",     PRO_BOOL,                           false,       ON, &settings.blanklines_before_blockcomments,  &exp_bbb},
    {"bap",     PRO_BOOL,                           false,       ON, &settings.blanklines_after_procs,           &exp_bap},
    {"badp",    PRO_BOOL,                           false,       ON, &settings.blanklines_after_declarations_at_proctop,  &exp_badp},
    {"bad",     PRO_BOOL,                           false,       ON, &settings.blanklines_after_declarations,    &exp_bad},
    {"bacc",    PRO_BOOL,                           false,       ON, &settings.blanklines_around_conditional_compilation, &exp_bacc},
    {"T",       PRO_KEY,                                0, ONOFF_NA, 0,                                          &exp_T},
    {"ppi",     PRO_INT,                                0, ONOFF_NA, &settings.force_preproc_width,              &exp_ppi},
    /* Signify end of structure.  */
    {0,         PRO_IGN,                                0, ONOFF_NA, 0,                                          0}
};

#else /* Default to GNU style */

/* Changed to make GNU style the default. */
const pro_ty pro[] =
{
    {"version", PRO_PRSTRING,                           0, ONOFF_NA, (int *) VERSION,                            &exp_version},
    {"v",       PRO_BOOL,                           false,       ON, &settings.verbose,                          &exp_v},
    {"ut",      PRO_BOOL,                            true,       ON, &settings.use_tabs,                         &exp_ut},
    {"ts",      PRO_INT,                                8, ONOFF_NA, &settings.tabsize,                          &exp_ts},
    {"st",      PRO_BOOL,                           false,       ON, &settings.use_stdout,                       &exp_st},
    {"ss",      PRO_BOOL,                           false,       ON, &settings.space_sp_semicolon,               &exp_ss},
    {"sob",     PRO_BOOL,                           false,       ON, &settings.swallow_optional_blanklines,      &exp_sob},
    {"sc",      PRO_BOOL,                           false,       ON, &settings.star_comment_cont,                &exp_sc},
    {"sbi",     PRO_INT,                                0, ONOFF_NA, &settings.struct_brace_indent,              &exp_sbi},
    {"saw",     PRO_BOOL,                            true,       ON, &settings.space_after_while,                &exp_saw},
    {"sai",     PRO_BOOL,                            true,       ON, &settings.space_after_if,                   &exp_sai},
    {"saf",     PRO_BOOL,                            true,       ON, &settings.space_after_for,                  &exp_saf},
    {"psl",     PRO_BOOL,                            true,       ON, &settings.procnames_start_line,             &exp_psl},
    {"prs",     PRO_BOOL,                           false,       ON, &settings.parentheses_space,                &exp_prs},
#ifdef PRESERVE_MTIME
    {"pmt",     PRO_BOOL,                           false,       ON, &settings.preserve_mtime,                   &exp_pmt},
#endif
    {"pi",      PRO_INT,                               -1, ONOFF_NA, &settings.paren_indent,                     &exp_pi},
    {"pcs",     PRO_BOOL,                            true,       ON, &settings.proc_calls_space,                 &exp_pcs},
    {"orig",    PRO_SETTINGS,                           0, ONOFF_NA, ORIG_SETTINGS_STRING,                       &exp_orig},
    {"o",       PRO_BOOL,                           false,       ON, &settings.expect_output_file,               &exp_o},
    {"nv",      PRO_BOOL,                           false,      OFF, &settings.verbose,                          &exp_v},
    {"nut",     PRO_BOOL,                            true,      OFF, &settings.use_tabs,                         &exp_ut},
    {"nss",     PRO_BOOL,                           false,      OFF, &settings.space_sp_semicolon,               &exp_ss},
    {"nsob",    PRO_BOOL,                           false,      OFF, &settings.swallow_optional_blanklines,      &exp_sob},
    {"nsc",     PRO_BOOL,                           false,      OFF, &settings.star_comment_cont,                &exp_sc},
    {"nsaw",    PRO_BOOL,                            true,      OFF, &settings.space_after_while,                &exp_saw},
    {"nsai",    PRO_BOOL,                            true,      OFF, &settings.space_after_if,                   &exp_sai},
    {"nsaf",    PRO_BOOL,                            true,      OFF, &settings.space_after_for,                  &exp_saf},
    {"npsl",    PRO_BOOL,                            true,      OFF, &settings.procnames_start_line,             &exp_psl},
    {"nprs",    PRO_BOOL,                           false,      OFF, &settings.parentheses_space,                &exp_prs},
    {"npro",    PRO_IGN,                                0, ONOFF_NA, 0,                                          &exp_pro},
#ifdef PRESERVE_MTIME
    {"npmt",    PRO_BOOL,                           false,      OFF, &settings.preserve_mtime,                   &exp_pmt},
#endif
    {"npcs",    PRO_BOOL,                            true,      OFF, &settings.proc_calls_space,                 &exp_pcs},
    {"nlps",    PRO_BOOL,                           false,      OFF, &settings.leave_preproc_space,              &exp_lps},
    {"nlp",     PRO_BOOL,                            true,      OFF, &settings.lineup_to_parens,                 &exp_lp},
    {"nip",     PRO_SETTINGS,                           0, ONOFF_NA, (int *) "-ip0\0",                           &exp_nip},
    {"nhnl",    PRO_BOOL,                            true,      OFF, &settings.honour_newlines,                  &exp_hnl},
    {"nfca",    PRO_BOOL,                           false,      OFF, &settings.format_comments,                  &exp_fca},
    {"nfc1",    PRO_BOOL,                           false,      OFF, &settings.format_col1_comments,             &exp_fc1},
    {"neei",    PRO_BOOL,                           false,      OFF, &settings.extra_expression_indent,          &exp_eei},
    {"ndj",     PRO_BOOL,                           false,      OFF, &settings.ljust_decl,                       &exp_dj},
    {"ncs",     PRO_BOOL,                            true,      OFF, &settings.cast_space,                       &exp_cs},
    {"nce",     PRO_BOOL,                           false,      OFF, &settings.cuddle_else,                      &exp_ce},
    {"ncdw",    PRO_BOOL,                           false,      OFF, &settings.cuddle_do_while,                  &exp_cdw},
    {"ncdb",    PRO_BOOL,                           false,      OFF, &settings.comment_delimiter_on_blankline,   &exp_cdb},
    {"nbs",     PRO_BOOL,                           false,      OFF, &settings.blank_after_sizeof,               &exp_bs},
    {"nbfda",   PRO_BOOL,                           false,      OFF, &settings.break_function_decl_args,         &exp_bfda},
    {"nbfde",   PRO_BOOL,                           false,      OFF, &settings.break_function_decl_args_end,     &exp_bfde},
    {"nbc",     PRO_BOOL,                            true,       ON, &settings.leave_comma,                      &exp_bc},
    {"nbbo",    PRO_BOOL,                            true,      OFF, &settings.break_before_boolean_operator,    &exp_bbo},
    {"nbbb",    PRO_BOOL,                           false,      OFF, &settings.blanklines_before_blockcomments,  &exp_bbb},
    {"nbap",    PRO_BOOL,                            true,      OFF, &settings.blanklines_after_procs,           &exp_bap},
    {"nbadp",   PRO_BOOL,                           false,      OFF, &settings.blanklines_after_declarations_at_proctop,  &exp_badp},
    {"nbad",    PRO_BOOL,                           false,      OFF, &settings.blanklines_after_declarations,    &exp_bad},
    {"nbacc",   PRO_BOOL,                           false,      OFF, &settings.blanklines_around_conditional_compilation, &exp_bacc},
    {"linux",   PRO_SETTINGS,                           0, ONOFF_NA, LINUX_SETTINGS_STRING,                      &exp_linux},
    {"lps",     PRO_BOOL,                           false,       ON, &settings.leave_preproc_space,              &exp_lps},
    {"lp",      PRO_BOOL,                            true,       ON, &settings.lineup_to_parens,                 &exp_lp},
    {"lc",      PRO_INT,     DEFAULT_RIGHT_COMMENT_MARGIN, ONOFF_NA, &settings.comment_max_col,                  &exp_lc},
    {"l",       PRO_INT,             DEFAULT_RIGHT_MARGIN, ONOFF_NA, &settings.max_col,                          &exp_l},
    {"kr",      PRO_SETTINGS,                           0, ONOFF_NA, KR_SETTINGS_STRING,                         &exp_kr},
    {"il",      PRO_INT,                                0, ONOFF_NA, &settings.label_offset,                     &exp_il},
    {"ip",      PRO_INT,                                5, ONOFF_NA, &settings.indent_parameters,                &exp_ip},
    {"i",       PRO_INT,                                2, ONOFF_NA, &settings.ind_size,                         &exp_i},
    {"hnl",     PRO_BOOL,                            true,       ON, &settings.honour_newlines,                  &exp_hnl},
    {"h",       PRO_FUNCTION,                           0, ONOFF_NA, (int *) usage,                              &exp_version},
    /* This is now the default. */
    {"gnu",     PRO_SETTINGS,                           0, ONOFF_NA, GNU_SETTINGS_STRING,                        &exp_gnu},
    {"fca",     PRO_BOOL,                           false,       ON, &settings.format_comments,                  &exp_fca},
    {"fc1",     PRO_BOOL,                           false,       ON, &settings.format_col1_comments,             &exp_fc1},
    {"eei",     PRO_BOOL,                           false,       ON, &settings.extra_expression_indent,          &exp_eei},
    {"dj",      PRO_BOOL,                           false,       ON, &settings.ljust_decl,                       &exp_dj},
    {"di",      PRO_INT,                                2, ONOFF_NA, &settings.decl_indent,                      &exp_di},
    {"d",       PRO_INT,                                0, ONOFF_NA, &settings.unindent_displace,                &exp_d},
    {"cs",      PRO_BOOL,                            true,       ON, &settings.cast_space,                       &exp_cs},
    {"cp",      PRO_INT,                                1, ONOFF_NA, &settings.else_endif_col,                   &exp_cp},
    {"cli",     PRO_INT,                                0, ONOFF_NA, &settings.case_indent,                      &exp_cli},
    {"ci",      PRO_INT,                                0, ONOFF_NA, &settings.continuation_indent,              &exp_ci},
    {"ce",      PRO_BOOL,                           false,       ON, &settings.cuddle_else,                      &exp_ce},
    {"cdw",     PRO_BOOL,                           false,       ON, &settings.cuddle_do_while,                  &exp_cdw},
    {"cdb",     PRO_BOOL,                           false,       ON, &settings.comment_delimiter_on_blankline,   &exp_cdb},
    {"cd",      PRO_INT,                               33, ONOFF_NA, &settings.decl_com_ind,                     &exp_cd},
    {"cbi",     PRO_INT,                               -1, ONOFF_NA, &settings.case_brace_indent,                &exp_cbi},
    {"c++",     PRO_BOOL,                           false,       ON, &settings.c_plus_plus,                      &exp_cpp},
    {"c",       PRO_INT,                               33, ONOFF_NA, &settings.com_ind,                          &exp_c},
    {"bs",      PRO_BOOL,                           false,       ON, &settings.blank_after_sizeof,               &exp_bs},
    {"brs",     PRO_BOOL,                           false,       ON, &settings.braces_on_struct_decl_line,       &exp_bls},
    {"bls",     PRO_BOOL,                           false,      OFF, &settings.braces_on_struct_decl_line,       &exp_bls},
    {"brf",     PRO_BOOL,                           false,       ON, &settings.braces_on_func_def_line,          &exp_blf},
    {"blf",     PRO_BOOL,                           false,      OFF, &settings.braces_on_func_def_line,          &exp_blf},
    {"bli",     PRO_INT,                                2, ONOFF_NA, &settings.brace_indent,                     &exp_bli},
    {"br",      PRO_BOOL,                           false,       ON, &settings.btype_2,                          &exp_bl},
    {"bl",      PRO_BOOL,                           false,      OFF, &settings.btype_2,                          &exp_bl},
    {"bfda",    PRO_BOOL,                           false,       ON, &settings.break_function_decl_args,         &exp_bfda},
    {"bfde",    PRO_BOOL,                           false,       ON, &settings.break_function_decl_args_end,     &exp_bfde},
    {"bc",      PRO_BOOL,                            true,      OFF, &settings.leave_comma,                      &exp_bc},
    {"bbo",     PRO_BOOL,                            true,       ON, &settings.break_before_boolean_operator,    &exp_bbo},
    {"bbb",     PRO_BOOL,                           false,       ON, &settings.blanklines_before_blockcomments,  &exp_bbb},
    {"bap",     PRO_BOOL,                            true,       ON, &settings.blanklines_after_procs,           &exp_bap},
    {"badp",    PRO_BOOL,                           false,       ON, &settings.blanklines_after_declarations_at_proctop,  &exp_badp},
    {"bad",     PRO_BOOL,                           false,       ON, &settings.blanklines_after_declarations,    &exp_bad},
    {"bacc",    PRO_BOOL,                           false,       ON, &settings.blanklines_around_conditional_compilation, &exp_bacc},
    {"T",       PRO_KEY,                                0, ONOFF_NA, 0,                                          &exp_T},
    {"ppi",     PRO_INT,                                0, ONOFF_NA, &settings.force_preproc_width,              &exp_ppi},
    /* Signify end of structure.  */
    {0,         PRO_IGN,                                0, ONOFF_NA, 0,                                          0}
};

#endif /* GNU defaults */

typedef struct long_option_conversion
{
    char *long_name;
    char *short_name;
} long_option_conversion_ty;

const long_option_conversion_ty option_conversions[] =
{
    {"version",                                     "version"},
    {"verbose",                                     "v"},
    {"usage",                                       "h"},
    {"use-tabs",                                    "ut"},
    {"tab-size",                                    "ts"},
    {"swallow-optional-blank-lines",                "sob"},
    {"struct-brace-indentation",                    "sbi"},
    {"start-left-side-of-comments",                 "sc"},
    {"standard-output",                             "st"},
    {"space-special-semicolon",                     "ss"},
    {"space-after-while",                           "saw"},
    {"space-after-procedure-calls",                 "pcs"},
    {"space-after-parentheses",                     "prs"},
    {"space-after-if",                              "sai"},
    {"space-after-for",                             "saf"},
    {"space-after-cast",                            "cs"},
    {"remove-preprocessor-space",                   "nlps"},
    {"procnames-start-lines",                       "psl"},
#ifdef PRESERVE_MTIME
    {"preserve-mtime",                              "pmt"},
#endif
    {"paren-indentation",                           "pi"},
    {"parameter-indentation",                       "ip"},
    {"output-file",                                 "o"},
    {"output",                                      "o"},
    {"original-style",                              "orig"},
    {"original",                                    "orig"},
    {"no-verbosity",                                "nv"},
    {"no-tabs",                                     "nut"},
    {"no-space-after-while",                        "nsaw"},
    {"no-space-after-parentheses",                  "nprs"},
    {"no-space-after-if",                           "nsai"},
    {"no-space-after-function-call-names",          "npcs"},
    {"no-space-after-for",                          "nsaf"},
    {"no-space-after-casts",                        "ncs"},
    {"no-parameter-indentation",                    "nip"},
    {"no-extra-expression-indentation",             "neei"},
    {"no-comment-delimiters-on-blank-lines",        "ncdb"},
    {"no-blank-lines-before-block-comments",        "nbbb"},
    {"no-blank-lines-after-procedures",             "nbap"},
    {"no-blank-lines-after-procedure-declarations", "nbadp"},
    {"no-blank-lines-after-ifdefs",                 "nbacc"},
    {"no-blank-lines-after-declarations",           "nbad"},
    {"no-blank-lines-after-commas",                 "nbc"},
    {"no-blank-before-sizeof",                      "nbs"},
    {"no-Bill-Shannon",                             "nbs"},
    {"label-offset",                                "il"},
    {"line-length",                                 "l"},
    {"line-comments-indentation",                   "d"},
    {"linux-style",                                 "linux"},
    {"left-justify-declarations",                   "dj"},
    {"leave-preprocessor-space",                    "lps"},
    {"leave-optional-blank-lines",                  "nsob"},
    {"kernighan-and-ritchie-style",                 "kr"},
    {"kernighan-and-ritchie",                       "kr"},
    {"k-and-r-style",                               "kr"},
    {"indent-label",                                "il"},
    {"indentation-level",                           "i"},
    {"indent-level",                                "i"},
    {"ignore-profile",                              "npro"},
    {"ignore-newlines",                             "nhnl"},
    {"honour-newlines",                             "hnl"},
    {"help",                                        "h"},
    {"gnu-style",                                   "gnu"},
    {"format-first-column-comments",                "fc1"},
    {"format-all-comments",                         "fca"},
    {"extra-expression-indentation",                "eei"},
    {"else-endif-column",                           "cp"},
    {"dont-star-comments",                          "nsc"},
    {"dont-space-special-semicolon",                "nss"},
    {"dont-line-up-parentheses",                    "nlp"},
    {"dont-left-justify-declarations",              "ndj"},
    {"dont-indent-parameters",                      "nip"},
    {"dont-format-first-column-comments",           "nfc1"},
    {"dont-format-comments",                        "nfca"},
    {"dont-cuddle-else",                            "nce"},
    {"dont-cuddle-do-while",                        "ncdw"},
    {"dont-break-procedure-type",                   "npsl"},
    {"dont-break-function-decl-args",               "nbfda"},
    {"dont-break-function-decl-args-end",           "nbfde"},
    {"declaration-indentation",                     "di"},
    {"declaration-comment-column",                  "cd"},
    {"cuddle-else",                                 "ce"},
    {"cuddle-do-while",                             "cdw"},
    {"continue-at-parentheses",                     "lp"},
    {"continuation-indentation",                    "ci"},
    {"comment-line-length",                         "lc"},
    {"comment-indentation",                         "c"},
    {"comment-delimiters-on-blank-lines",           "cdb"},
    {"case-indentation",                            "cli"},
    {"case-brace-indentation",                      "cbi"},
    {"c-plus-plus",                                 "c++"},
    {"break-function-decl-args",                    "bfda"},
    {"break-function-decl-args-end",                "bfde"},
    {"break-before-boolean-operator",               "bbo"},
    {"break-after-boolean-operator",                "nbbo"},
    {"braces-on-struct-decl-line",                  "brs"},
    {"braces-on-func-def-line",                     "brf"},
    {"braces-on-if-line",                           "br"},
    {"braces-after-struct-decl-line",               "bls"},
    {"braces-after-func-def-line",                  "blf"},
    {"braces-after-if-line",                        "bl"},
    {"brace-indent",                                "bli"},
    {"blank-lines-before-block-comments",           "bbb"},
    {"blank-lines-after-procedures",                "bap"},
    {"blank-lines-after-procedure-declarations",    "badp"},
    {"blank-lines-after-ifdefs",                    "bacc"},
    {"blank-lines-after-declarations",              "bad"},
    {"blank-lines-after-commas",                    "bc"},
    {"blank-before-sizeof",                         "bs"},
    {"berkeley-style",                              "orig"},
    {"berkeley",                                    "orig"},
    {"Bill-Shannon",                                "bs"},
    {"preprocessor-indentation",                    "ppi"},
    {0,                                             0},
};

static void usage (void)
{
  fprintf (stderr, _("usage: indent file [-o outfile ] [ options ]\n"));
  fprintf (stderr, _("       indent file1 file2 ... fileN [ options ]\n"));
  exit (invocation_error);
}

/* S1 should be a string.  S2 should be a string, perhaps followed by an
   argument.  Compare the two, returning true if they are equal, and if they
   are equal set *START_PARAM to point to the argument in S2.  */

static BOOLEAN eqin (
    const char   * s1,
    const char   * s2,
    const  char ** start_param)
{
    BOOLEAN ret = true;
    
    while (*s1)
    {
        if (*s1++ != *s2++)
        {
            ret = false;
        }
    }
  
    *start_param = s2;
    return ret;
}

/* Set the defaults. */

void set_defaults (void)
{
    const pro_ty *p;

    for (p = pro; p->p_name; p++)
    {
        if ((p->p_type == PRO_BOOL && p->p_special == ON) || p->p_type == PRO_INT)
        {
            *p->p_obj = p->p_default;
        }
    }
}

/* Set the defaults after options set */

void set_defaults_after (void)
{
    if (!exp_lc)                        /* if no -lc option was given */
    {
        settings.comment_max_col = settings.max_col;
    }
}

/* Strings which can prefix an option, longest first. */

static char *option_prefixes[] =
{
    "--",
    "-",
    "+",
    0
};

static void arg_missing(
    const char *option)
{
    fprintf (stderr, _("indent: missing argument to parameter %s\n"), option);
    exit (invocation_error);
}

static int option_prefix (
    const char * arg)
{
    char       ** prefixes    = option_prefixes;
    char        * this_prefix = *prefixes;
    const char  * argp        = arg;
    int           ret         = 0;

    do
    {
        this_prefix = *prefixes;
        argp = arg;
        
        while (*this_prefix == *argp)
        {
            this_prefix++;
            argp++;
        }
      
        if (*this_prefix == '\0')
        {
            ret = this_prefix - *prefixes;
            break;
        }
      
    } while (*++prefixes);

    return ret;
}

/* Process an option ARG (e.g. "-l60").  PARAM is a possible value
 * for ARG, if PARAM is nonzero.  EXPLICT should be nonzero iff the
 * argument is being explicitly specified (as opposed to being taken from a
 * PRO_SETTINGS group of settings).
 *
 * Returns 1 if the option had a value, returns 0 otherwise.
 *
 * 2002-06-13 D.Ingamells. Fixed check for int param without an int argument.
 */

int set_option (
    const char * option,
    const char * param,
    int          explicit)
{
    const pro_ty * p             = pro;
    const char   * param_start   = NULL;
    int            option_length = option_prefix (option);
    int            val           = 0;
    BOOLEAN        found         = false;
  
    if (option_length > 0)
    {
        if ((option_length == 1) && (*option == '-'))
        {
            /* Short option prefix */
            option++;
            
            for (p = pro; p->p_name; p++)
            {
                if ((*p->p_name == *option) &&
                    eqin (p->p_name, option, &param_start))
                {
                    found = true;
                    break;
                }
            }
        }
        else
        {
            /* Long prefix */
            const long_option_conversion_ty *o = option_conversions;

            option += option_length;

            while (o->short_name)
            {
                if (eqin (o->long_name, option, &param_start))
                {
                    break;
                }
                
                o++;
            }

            /* Searching twice means we don't have to keep the two tables in
             * sync. */
            
            if (o->short_name)
            {
                for (p = pro; p->p_name; p++)
                {
                    if (!strcmp (p->p_name, o->short_name))
                    {
                        found = true;
                        break;
                    }
                }
            }
        }
    }

    if (!found)
    {
        fprintf (stderr, _("indent: unknown option \"%s\"\n"), option - 1);
        exit (invocation_error);
    }
    else
    {
        /* If the parameter has been explicitly specified, we don't
         * want a group of bundled settings to override the explicit
         * setting.  */
        
        if (settings.verbose)
        {
            fprintf (stderr, _("option: %s\n"), p->p_name);
        }
        
        if (explicit || !*(p->p_explicit))
        {
            if (explicit)
            {
                *(p->p_explicit) = 1;
            }
            
            switch (p->p_type)
            {
                
            case PRO_PRSTRING:
                /* This is not really an error, but zero exit values are
                   returned only when code has been successfully formatted. */
                printf (_("GNU indent %s\n"), (char *) p->p_obj);
                exit (invocation_error);
                
            case PRO_FUNCTION:
                ((void (*)()) p->p_obj) ();
                break;
                
            case PRO_SETTINGS:
                {
                    char *t;            /* current position */
                    
                    t = (char *) p->p_obj;
                    
                    do
                    {
                        set_option (t, 0, 0);
                        /* advance to character following next NUL */
                        
                        while (*t++)
                        {
                        }
                    } while (*t);
                }

            case PRO_IGN:
                break;

            case PRO_KEY:
                {
                    char *str;

                    if (*param_start == 0)
                    {
                        if (!(param_start = param))
                        {
                            arg_missing(option);
                        }
                        else
                        {
                            val = 1;
                        }
                    }

                    str = (char *) xmalloc (strlen (param_start) + 1);
                    strcpy (str, param_start);
                    addkey (str, rw_decl);
                }
                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')
                {
                    param_start = param;
                    
                    if (param_start == NULL)
                    {
                        arg_missing(option);
                    }
                    else
                    {
                        val = 1;
                    }
                }

                if (isdigit (*param_start) || ((*param_start == '-') && isdigit (*(param_start + 1))))
                {
                    *p->p_obj = atoi (param_start);
                }
                else
                {
                    fprintf (stderr,
                             _("indent: option ``%s'' requires a numeric parameter\n"),
                             option - 1);
                    exit (invocation_error);
                }
                
                break;

            default:
                fprintf (stderr,
                         _("indent: set_option: internal error: p_type %d\n"),
                         (int) p->p_type);
                exit (invocation_error);
            }
        }
    }
    
    return val;
}

/* The first 2 characters of a c++ comment have been read skip the remainder of the line
 * and return the first character from the next line.
 */

static int skip_cpp_comment(
    FILE * f)
{

    int i;
    
    do
    {
        i = getc (f);
    } while ((i != EOF) && (i != EOL));

    if (i == EOL)
    {
        i = getc (f);
    }
    
    return i;
}

/*
 * the first 2 characters of a c comment have been read. Read past the
 * remainder of the comment and return the first character after the
 * comment.
 */

static int skip_c_comment(
    FILE * f)
{
    int i = getc (f);
    
    do
    {
        /* skip to the next '*' character */
        
        while ((i != EOF) && (i != '*'))
        {
            i = getc (f);
        }
                        
                        
        if (i == EOF)
        {
            WARNING (_("Profile contains an unterminated comment"), 0, 0);
            break;
        }
        /* current char is '*' so skip over it. */
        
        i = getc (f);
        
        /* If the current character is a '/' the comment is over. */
    } while (i != '/');

    if (i != EOF)
    {
        i = getc (f);
    }
    
    return i;
}

/* The starting / of a comment has been read.
 * skip over the rest of the comment and return the
 * first character after the comment.
 */

static int skip_comment(
    FILE * f)
{
    int i = getc (f);
    
    switch (i)
    {
        case '/':
            i = skip_cpp_comment(f);
            break;
        case '*':
            i = skip_c_comment(f);
            break;
        default:
            WARNING (_("Profile contains unpalatable characters"), 0, 0);
    }
    
    return i;
}

/*
 * Skip a sequence of space and control characters and return the
 * first character after the sequence.
 */

static int skip_spaces(
    FILE * f,
    int    first)
{
    int    i = first;

    while ((i <= ' ') &&
           (i != EOF))
    {
        i = getc (f);
    }
           
    return i;
}

/* Read a string from the input until the next control character, space or /.
 * Return the first character after the read string.
 */

static int read_string(
    FILE  * f,
    char  * buff,
    int     first)
{
    int i = first;
    char *p = buff;
    
    while ( ( i != EOF) &&
            (i > ' ')   &&
            (i != '/')  &&
            (p < buff + BUFSIZ))
    {
        *(p++) = i;
        i = getc (f);
    }

    *p = EOS;
    
    return i;
}

/* Scan the options in the file f. */

static void scan_profile (
    FILE  * f)
{
    char   b0[BUFSIZ];
    char   b1[BUFSIZ];
    char * current = b0;

    int    i = skip_spaces(f, ' ');
    
    while (i != EOF)
    {
        if (i == '/')
        {
            /* The start of a comment. */
            i = skip_comment(f);
        }
        else
        {
            i = read_string(f, current, i);

            /* We've scanned something... */

            if (current == b0)
            {
                /* Second buffer still has to be filled. */
                current = b1;
            }
            else if (set_option (b0, b1, 1) == 1)
            {
                /* The option had a parameter, thus both values
                 * have been consumed.
                 * Reset the 2 buffers to 'empty'
                 */
                current = b0;
            }
            else
            {
                /* Set option consumed one value. Move the
                 * other value to the first buffer and go get a new
                 * second value.
                 */
                
                strcpy(b0, b1);
                current = b1;
            }
            
        }
        
        i = skip_spaces(f, i);
    }

    if (current != b0)
    {
        set_option (b0, NULL, 1);
    }
}


/* Some operating systems don't allow more than one dot in a filename.  */
#if defined (ONE_DOT_PER_FILENAME)
#define INDENT_PROFILE "indent.pro"
#else
#define INDENT_PROFILE ".indent.pro"
#endif

#ifndef PROFILE_FORMAT
#define PROFILE_FORMAT "%s/%s"
#endif

#define PROFILE_ENV_NAME "INDENT_PROFILE"

/* set_profile looks for ./.indent.pro or $HOME/.indent.pro, in
 * that order, and reads the options given in that file.  Return the
 * path of the file read.
 *
 * Note that as of version 1.3, indent only reads one file. */

char * set_profile (void)
{
    FILE        * f       = NULL;
    char        * fname   = NULL;
    static char   prof[]  = INDENT_PROFILE;
    char        * homedir = NULL;
    char        * envname = getenv(PROFILE_ENV_NAME);

    if (envname != NULL)
    {
        f = fopen (envname, "r");
    }

    if (f != NULL)
    {
        scan_profile (f);
        
        (void) fclose (f);
        
        fname = strdup(envname);
    }
    else
    {
        f = fopen (INDENT_PROFILE, "r");
        
        if (f != NULL)
        {
            int len = strlen (INDENT_PROFILE) + 3;

            scan_profile (f);
            (void) fclose (f);
            fname = xmalloc (len);
            strcpy(fname, "./");
            (void) strcat (fname, INDENT_PROFILE);
        }
        else
        {
            homedir = getenv ("HOME");
    
            if (homedir)
            {
                fname = xmalloc (strlen (homedir) + strlen(PROFILE_FORMAT) + sizeof (prof));
                sprintf (fname, PROFILE_FORMAT, homedir, prof);
                
                if ((f = fopen (fname, "r")) != NULL)
                {
                    scan_profile (f);
                    (void) fclose (f);
                }
                else
                {
                    free (fname);
                    fname = NULL;
                }
            }
        }
    }
    
    return fname;
}
indent.h (text/x-chdr, 21.2 KB)
/* Copyright (c) 1999 Carlo Wood.  All rights reserved.
 * Copyright (c) 1994 Joseph Arceneaux.  All rights reserved.
 * Copyright (c) 1992 Free Software Foundation, Inc.  All rights reserved.
 *
 * 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.
 *
 * 2002-11-10 Cristalle Azundris Sabon <[email protected]>
 *            Added --preprocessor-indentation (ppi)   if set, will indent nested
 *            preprocessor-statements with n spaces per level.  overrides -lps.
 */

#ifndef INDENT_INDENT_H
#define INDENT_INDENT_H

#include "sys.h"
RCSTAG_H (indent, "$Id: indent.h,v 1.37 2002/11/10 21:02:48 david Exp $");
#include <config.h>

#include <libgettext.h>
#ifdef ENABLE_NLS
#define _(X) gettext(X)
#else
#define _(X) X
#endif

#include "lexi.h"
#include "io.h"

/* Values that `indent' can return for exit status.
 *
 *  `total_success' means no errors or warnings were found during a successful
 *    invocation of the program.
 *
 *  `invocation_error' is returned if an invocation problem (like an incorrect
 *    option) prevents any formatting to occur.
 *
 *  `indent_error' is returned if errors occur during formatting which
 *    do not prevent completion of the formatting, but which appear to be
 *    manifested by incorrect code (i.e, code which wouldn't compile).
 *
 *  `indent_punt' is returned if formatting of a file is halted because of
 *    an error with the file which prevents completion of formatting.  If more
 *    than one input file was specified, indent continues to the next file.
 *
 *  `indent_fatal' is returned if a serious internal problem occurs and
 *    the entire indent process is terminated, even if all specified files
 *    have not been processed. */

typedef enum exit_values
{
  total_success = 0,
  invocation_error = 1,
  indent_error = 2,
  indent_punt = 3,
  indent_fatal = 4,
  system_error = 5
} exit_values_ty;

typedef unsigned char BOOLEAN;

#define false 0
#define true  1

#define DEFAULT_RIGHT_MARGIN 78

#define DEFAULT_RIGHT_COMMENT_MARGIN 78

/* Name of input file.  */
extern char *in_name;

extern char *in_prog;           /* pointer to the null-terminated input
                                   program */

/* Point to the position in the input program which we are currently looking
   at.  */
extern char *in_prog_pos;

/* Point to the start of the current line.  */
extern char *cur_line;

/* Size of the input program, not including the ' \n\0' we add at the end */
extern unsigned long in_prog_size;

extern char *labbuf;            /* buffer for label */
extern char *s_lab;             /* start ... */
extern char *e_lab;             /* .. and end of stored label */
extern char *l_lab;             /* limit of label buffer */

extern char *codebuf;           /* buffer for code section */
extern char *s_code;            /* start ... */
extern char *s_code_corresponds_to;     /* If set, start of corresponding
                                           code in token buffer... */
extern char *e_code;            /* .. and end of stored code */
extern char *l_code;            /* limit of code section */

extern char *combuf;            /* buffer for comments */
extern char *s_com;             /* start ... */
extern char *e_com;             /* ... and end of stored comments */
extern char *l_com;             /* limit of comment buffer */

extern char *buf_ptr;           /* ptr to next character to be taken from
                                   in_buffer */
extern char *buf_end;           /* ptr to first after last char in in_buffer */

extern int break_line;          /* Whether or not we should break the line. */

/* pointer to the token that lexi() has just found */
extern char *token;

/* points to the first char after the end of token */
extern char *token_end;

extern int squest;
extern file_buffer_ty *current_input;

/* Used to keep track of buffers.  */
typedef struct buf
{
  char *ptr;                    /* points to the start of the buffer */
  char *end;                    /* points to the character beyond the last
                                   one (e.g. is equal to ptr if the buffer is
                                   empty).  */
  int size;                     /* how many chars are currently allocated.  */
  int len;                      /* how many chars we're actually using. */
  int start_column;             /* corresponding column of first character
                                   in the buffer. */
  int column;                   /* Column we were in when we switched buffers. */
} buf_ty;

/* Buffer in which to save a comment which occurs between an if(), while(),
 * etc., and the statement following it.  Note: the fact that we point into
 * this buffer, and that we might realloc() it (via the need_chars macro) is
 * a bad thing (since when the buffer is realloc'd its address might change,
 * making any pointers into it point to garbage), but since the filling of
 * the buffer (hence the need_chars) and the using of the buffer (where
 * buf_ptr points into it) occur at different times, we can get away with it
 * (it would not be trivial to fix).  */

extern buf_ty save_com;

extern char *bp_save;           /* saved value of buf_ptr when taking input
                                   from save_com */
extern char *be_save;           /* similarly saved value of buf_end */


extern int pointer_as_binop;
extern int n_real_blanklines;
extern int prefix_blankline_requested;
extern codes_ty prefix_blankline_requested_code;      /* The code that caused
                                                           the blank line to be
                                                           requested */
extern int postfix_blankline_requested;
extern codes_ty postfix_blankline_requested_code;     /* The code that caused
                                                         * the blank line to be
                                                         * requested */
extern int break_comma;         /* when true and not in parens, break after a
                                 * comma */

/*
 * This structure stores all the user options that come from (e.g.)
 * command line flags.
 */
typedef struct user_options_st
{
    int verbose;     /* when true, non-essential error messages are printed */
    int use_tabs;    /* does indent convert tabs to spaces or not */
    int tabsize;     /* The number of columns a tab character generates. */
    int use_stdout;  /* Where does output go. */
    int space_sp_semicolon; /* If true, a space is inserted between if, while, or for, and a semicolon
                             * for example while (*p++ == ' ') ; */
    int swallow_optional_blanklines;
    int star_comment_cont;   /* true if comment continuation lines should have stars at the beginning of each line. */
    int struct_brace_indent; /* Indentation level to be used for a '{' directly following a struct, union or enum */
    int space_after_while;   /* Put a space after `while' */
    int space_after_if;      /* Put a space after `if' */
    int space_after_for;     /* Put a space after `for' */
    int procnames_start_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) */
    int parentheses_space;   /* If true, parentheses will look like: ( foo ) rather than (foo) */
    int preserve_mtime;      /* True when the modification time of the files should  be preserved. */
    int paren_indent;        /* set to the indentation per open parens */
    int proc_calls_space;    /* If true, procedure calls look like: foo (bar) rather than foo(bar) */
    int leave_preproc_space; /* if true, leave the spaces between  '#' and preprocessor commands. */
    int force_preproc_width; /* if this is >0, this becomes the preproc indent-level */
    int lineup_to_parens;    /* if true, continued code within parens will be lined up to the open paren */
    int honour_newlines;     /* True when positions at which we read a newline in the input file, should get
                              * a high priority to break long lines at. */
    int format_comments; /* If any comments are to be reformatted */
    int format_col1_comments; /* If comments which start in column 1 are to be magically reformatted */
    int extra_expression_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 */
    int ljust_decl;          /* true if declarations should be left justified */
    int cast_space;          /* If true, casts look like: (char *) bar rather than (char *)bar */
    int cuddle_else;         /* true if else should cuddle up to '}' */
    int cuddle_do_while;     /* true if '}' should cuddle up to while in do loop */
    int comment_delimiter_on_blankline;
    int blank_after_sizeof; /* true iff a blank should always be inserted after sizeof */
    int break_function_decl_args;    /* true if declarations should have args on new lines */
    int break_function_decl_args_end; /* true if declarations should have
                                       * ")" after args on new lines */
    int leave_comma;         /* if true, never break declarations after commas */
    int break_before_boolean_operator;       /* True when we prefer to break a long line
                                              * before a '&&' or '||', instead of behind it.
                                              */
    int blanklines_before_blockcomments;
    int blanklines_after_declarations;
    int blanklines_after_procs;
    int blanklines_after_declarations_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
                                                      */
    int blanklines_around_conditional_compilation;
    int comment_max_col;
    int max_col;             /* the maximum allowable line length */
    int label_offset;        /* offset of labels */
    int ind_size; /* The size of one indentation level in spaces.  */
    int indent_parameters; /* Number of spaces to indent parameters.  */
    int decl_indent;         /* column to indent declared identifiers to */
    int unindent_displace;   /* comments not to the right of code will be
                              * placed this many indentation levels to the
                              * left of code */
    int else_endif_col; /* The column in which comments to the right of #else and #endif should start. */
    int case_indent;         /* The distance to indent case labels from the switch statement */
    int continuation_indent; /* set to the indentation between the edge of code and continuation lines in spaces */
    int decl_com_ind;        /* the column in which comments after declarations should be put */
    int case_brace_indent;   /* Indentation level to be used for a '{'
                              * directly following a case label. */
    int c_plus_plus; /* True if we're handling C++ code. */
    int com_ind;             /* the column in which comments to the right of code should start */
    int braces_on_struct_decl_line; /* when true, brace should be on same line as the struct declaration */
    int braces_on_func_def_line; /* when true, brace should be on same line as the function definition */
    int btype_2; /* when true, brace should be on same line as if, while, etc */
    int brace_indent; /* number of spaces to indent braces from the suround if, while, etc. in -bl
                       * (bype_2 == 0) code */
    int expect_output_file;  /* Means "-o" was specified. */
} user_options_ty;

extern user_options_ty settings;

/* True if there is an embedded comment on this code line */
extern int embedded_comment_on_line;

extern int else_or_endif;
extern int di_stack_alloc;
extern int *di_stack;

extern int else_or_endif; /* True if a #else or #endif has been encountered.  */

extern int     code_lines;          /* count of lines with code */

extern int     out_lines;           /* the number of lines written, set by
                                 * dump_line */
extern int     com_lines;           /* the number of lines with comments, set by
                                 * dump_line */


extern BOOLEAN had_eof;             /* set to true when input is exhausted */
extern int     line_no;             /* the current input line number. */



extern int use_stdinout; /* Nonzero if we should use standard input/output when files are not
                          * explicitly specified.  */

/* This structure contains information relating to the state of parsing the
 * code.  The difference is that the state is saved on #if and restored on
 * #else.  */

typedef struct parser_state
{
    struct parser_state * next;
    codes_ty              last_token;

    /* This is the parsers stack, and the current allocated size.  */
    codes_ty            * p_stack;
    int                   p_stack_size;

    /* This stack stores indentation levels 
     * Currently allocated size is stored in p_stack_size.  */

    int                 * il;

    /* If the last token was an ident and is a reserved word,
     * remember the type. */

    rwcodes_ty            last_rw;

    /* also, remember its depth in parentheses */

    int                   last_rw_depth;

    /* Used to store case stmt indentation levels.  */
    /* Currently allocated size is stored in p_stack_size.  */
    int                  *cstk;

    /* Pointer to the top of stack of the p_stack, il and cstk arrays. */
    int                   tos;

    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 the comment
                                    * closing delimiter */

    int                   cast_mask; /* indicates which close parens close off
                                      * casts */
    /* A bit for each paren level, set if the open paren was in a context which
       indicates that this pair of parentheses is not a cast.  */
    int                   noncast_mask;

    int                   sizeof_mask; /* indicates which close parens close off
                                        * sizeof''s */
    int                   block_init;  /* set to 1 if inside a block initialization
                                        * set to 2 if inside an enum declaration */
    int block_init_level;         /* The level of brace nesting in an
                                   * initialization (0 in an enum decl) */
    int last_nl;                  /* this is true if the last thing scanned was
                                   * a newline */
    int last_saw_nl;              /* this is true if the last non white space
                                   * scanned was a newline */
    int saw_double_colon;         /* set when we see a ::, reset at first semi-
                                   * colon or left brace */
    int broken_at_non_nl;         /* true when a line was broken at a place
                                   * where there was no newline in the input file */
    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 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 dec_nest;                 /* current nesting level for structure or
                                   * init */
    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 in spaces to which ind_level
                                   * should be set after the current line is
                                   * printed */
    BOOLEAN in_decl;              /* set to true when we are in a declaration
                                   * statement.  The processing of braces is then
                                   * slightly different */
    BOOLEAN in_closing_br_while;  /* set to true when we are parsing
                                   * closing while of do {} while
                                   * statement*/
    int in_stmt;                  /* set to 1 while in a stmt */
    int in_parameter_declaration;
    int ind_level;                /* the current indentation level in spaces */
    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 p_l_follow;               /* used to remember how to indent following
                                   * statement */
    int paren_level;              /* parenthesization level. used to indent
                                   * within stmts */
    int paren_depth;              /* Depth of paren nesting anywhere. */
    
    /* Column positions of paren at each level.  If positive, it contains just
     * the number of characters of code on the line up to and including the
     * right parenthesis character.  If negative, it contains the opposite of
     * the actual level of indentation in characters (that is, the indentation
     * of the line has been added to the number of characters and the sign has
     * been reversed to indicate that this has been done).  */
    short *paren_indents;         /* column positions of each paren */
    int paren_indents_size;       /* Currently allocated size.  */

    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 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.) */
    bb_code_ty can_break;         /* set when a break is ok before the following
                                   * token (is automatically implied by
                                   * `want_blank'. */
    int its_a_keyword;
    int sizeof_keyword;
    char *procname;               /* The name of the current procedure */
    char *procname_end;           /* One char past the last one in procname */
    char *classname;              /* The name of the current C++ class */
    char *classname_end;          /* One char past the last one in classname */
    int just_saw_decl;
    int matching_brace_on_same_line;      /* Set to a value >= 0 if the the
                                             current '}' has a matching '{'
                                             on the same input line */
} parser_state_ty;

/* All manipulations of the parser state occur at the top of stack (tos). A
 * stack is kept for conditional compilation (unrelated to the p_stack, il, &
 * cstk stacks)--it is implemented as a linked list via the next field. */

extern parser_state_ty *parser_state_tos;

extern int output_line_length (void);

#endif /* INDENT_INDENT_H */
io.c (text/x-csrc, 15.4 KB)
/* Copyright (c) 1999, 2000 Carlo Wood.  All rights reserved.
 * Copyright (c) 1994 Joseph Arceneaux.  All rights reserved.
 * Copyright (c) 1992 Free Software Foundation, Inc.  All rights reserved.
 *
 * 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.
 *
 * HISTORY
 * 2002-01-17 D.Ingamells Add a final newline if not present in file.
 */

#include "sys.h"

#include <ctype.h>
#include <stdlib.h>
#if defined (HAVE_UNISTD_H)
   #include <unistd.h>
#endif
#include <string.h>

#ifdef VMS
   #include <file.h>
   #include <types.h>
   #include <stat.h>
#else /* not VMS */
   #include <sys/types.h>
   #include <sys/stat.h>
   /* POSIX says that <fcntl.h> should exist.  Some systems might need to use
    * <sys/fcntl.h> or <sys/file.h> instead.  */
   #include <fcntl.h>
   #if defined (_WIN32) && !defined (__CYGWIN__)
      #include <io.h>
   #endif
#endif /* not VMS */

#include "indent.h"
#include "io.h"
#include "globs.h"
#include "output.h"

RCSTAG_CC ("$Id: io.c,v 1.50 2002/08/04 17:08:41 david Exp $");

/* number of levels a label is placed to left of code */
#define LABEL_OFFSET 2

/******************************************************************************/
/* Stuff that needs to be shared with the rest of indent. Documented in
 * indent.h.
 */

char          * in_prog_pos    = NULL;  /* used in output.c        io.c indent.c */
char          * buf_ptr        = NULL;  /* used in output.c lexi.c io.c indent.c comments.c */
char          * buf_end        = NULL;  /* used in output.c lexi.c io.c indent.c comments.c */
BOOLEAN         had_eof        = false; /* used in output.c        io.c          comments.c parse.c */
char          * cur_line       = NULL;  /* used in output.c        io.c */

/******************************************************************************/

char * skip_horiz_space(const char * p)
{
    while ((*p == ' ') || (*p == TAB))
    {
        p++;
    }

    return (char *)p;
}

/******************************************************************************/

void skip_buffered_space(void)
{
    while ((*buf_ptr == ' ') ||
           (*buf_ptr == TAB))
    {
        buf_ptr++;
        
        if (buf_ptr >= buf_end)
        {
            fill_buffer ();
        }
    }
}

/******************************************************************************/

static BOOLEAN is_comment_start(const char * p)
{
    BOOLEAN ret;
    
    if ((*p == '/') && ((*(p + 1) == '*') ||
                        (*(p + 1) == '/')))
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    
    return ret;
}

/******************************************************************************/

int count_columns (
    int column,
    char *bp,
    int stop_char)
{
    while (*bp != stop_char && *bp != NULL_CHAR)
    {
        switch (*bp++)
        {
        case EOL:
        case '\f':           /* form feed */
            column = 1;
            break;
        case TAB:
            column += settings.tabsize - (column - 1) % settings.tabsize;
            break;
        case 010:           /* backspace */
            --column;
            break;
#ifdef COLOR_DEBUG
        case '\e':          /* ANSI color */
            while (*bp++ != 'm')
            {
            }
                
            break;
#endif
        default:
            ++column;
            break;
        }
    }

    return column;
}


#ifdef VMS
/******************************************************************************/
/* Folks say VMS requires its own read routine.  Then again, some folks
 * say it doesn't.  Different folks have also sent me conflicting versions
 * of this function.  Who's right?
 *
 * Anyway, this version was sent by [email protected] and modified
 * slightly by me. */

static int vms_read (
    int    file_desc,
    char * buffer,
    int    nbytes)
{
    char * bufp;
    int    nread;
    int    nleft;

    bufp = buffer;
    nread = 0;
    nleft = nbytes;

    nread = read (file_desc, bufp, nleft);
    
    while (nread > 0)
    {
        bufp += nread;
        nleft -= nread;
        if (nleft < 0)
        {
            fatal (_("Internal buffering error"), 0);
        }
        
        nread = read (file_desc, bufp, nleft);
    }

    return nbytes - nleft;
}
#endif /* VMS */

/******************************************************************************/
/* Return the column we are at in the input line. */

int current_column (void)
{
    char *p;
    int column;

    /* Use save_com.size here instead of save_com.end, because save_com is
     * already emptied at this point. */
  
    if ((buf_ptr >= save_com.ptr) && (buf_ptr <= save_com.ptr + save_com.len))
    {
        p = save_com.ptr;
        column = save_com.start_column;
    }
    else
    {
        p = cur_line;
        column = 1;
    }

    while (p < buf_ptr)
    {
        switch (*p)
        {
            case EOL:
            case 014:           /* form feed */
                column = 1;
                break;

            case TAB:
                column += settings.tabsize - (column - 1) % settings.tabsize;
                break;

            case '\b':          /* backspace */
                column--;
                break;

            default:
                column++;
                break;
        }

        p++;
    }

    return column;
}

/******************************************************************************/
/* Return the column in which we should place the code in s_code. */

int compute_code_target (
    int paren_targ)
{
    int target_col;

    if (buf_break_used)
    {
        return prev_target_col_break;
    }

    if (parser_state_tos->procname[0] &&
        (s_code_corresponds_to == parser_state_tos->procname))
    {
        target_col = 1;
        
        if (!parser_state_tos->paren_level)
        {
            return target_col;
        }
    }
    else
    {
        target_col = parser_state_tos->ind_level + 1;
    }

    if (!parser_state_tos->paren_level)
    {
        if (parser_state_tos->ind_stmt)
        {
            target_col += settings.continuation_indent;
        }
        
        return target_col;
    }

    if (!settings.lineup_to_parens)
    {
        return target_col + settings.continuation_indent +
                (settings.paren_indent * (parser_state_tos->paren_level - 1));
    }

    return paren_targ;
}

/******************************************************************************/
int compute_label_target (void)
{
    /* maybe there should be some option to tell indent where to put public:,
     * private: etc. ? */
    
    if (*s_lab == '#')
    {
        return 1;
    }
    
    if (parser_state_tos->pcase)
    {
        return parser_state_tos->cstk[parser_state_tos->tos] + 1;
    }
    
    if (settings.c_plus_plus && parser_state_tos->in_decl)
    {
        /* FIXME: does this belong here at all? */
        return 1;
    }
    else if (settings.label_offset)
    {
        return settings.label_offset;
    } 
    else
    {
        return parser_state_tos->ind_level - LABEL_OFFSET + 1;
    }
}

/******************************************************************************/
/* VMS defines it's own read routine, `vms_read' */
#ifndef INDENT_SYS_READ
#define INDENT_SYS_READ read
#endif

/* Read file FILENAME into a `fileptr' structure, and return a pointer to
   that structure. */

file_buffer_ty * read_file (
    char        * filename,
    struct stat * file_stats)
{
    static file_buffer_ty fileptr;
    
    /*
     * size is required to be unsigned for MSDOS,
     * in order to read files larger than 32767
     * bytes in a 16-bit world...
     */
  
    unsigned int size;

    int          namelen = strlen(filename);
    int          fd      = open(filename, O_RDONLY, 0777);

    if (fd < 0)
    {
        fatal (_("Can't open input file %s"), filename);
    }

    if (fstat(fd, file_stats) < 0)
    {
        fatal (_("Can't stat input file %s"), filename);
    }

    if (file_stats->st_size == 0)
    {
        ERROR (_("Warning: Zero-length file %s"), filename, 0);
    }

#if !defined(__DJGPP__)
    if (sizeof (int) == 2)      /* Old MSDOS */
    {
        if ((file_stats->st_size < 0) || (file_stats->st_size > (0xffff - 1)))
        {
            fatal (_("File %s is too big to read"), filename);
        }
    }
    else
#endif
    {
        if (file_stats->st_size < 0)
        {
            fatal (_("System problem reading file %s"), filename);
        }
    }

    fileptr.size = file_stats->st_size;
    
    if (fileptr.data != 0)
    {
        fileptr.data = (char *) xrealloc (fileptr.data,
                                          (unsigned) file_stats->st_size + 2); /* add 1 for '\0' and 1 for
                                                                                * potential final added
                                                                                * newline. */
    }
    else
    {
        fileptr.data = (char *) xmalloc ((unsigned) file_stats->st_size + 2); /* add 1 for '\0' and 1 for
                                                                               * potential final added
                                                                               * newline. */
    }

    size = INDENT_SYS_READ (fd, fileptr.data, fileptr.size);
    
    if (size == (unsigned int) -1)
    {
        fatal (_("Error reading input file %s"), filename);
    }
    
    if (close (fd) < 0)
    {
        fatal (_("Error closeing input file %s"), filename);
    }
    

    /* Apparently, the DOS stores files using CR-LF for newlines, but
     * then the DOS `read' changes them into '\n'.  Thus, the size of the
     * file on disc is larger than what is read into memory.  Thanks, Bill. */
    
    if (size < fileptr.size)
    {
        fileptr.size = size;
    }

    if (fileptr.name != NULL)
    {
        fileptr.name = (char *) xrealloc (fileptr.name, (unsigned) namelen + 1);
    }
    else
    {
        fileptr.name = (char *) xmalloc (namelen + 1);
    }
    
    (void)strncpy(fileptr.name, filename, namelen);
    fileptr.name[namelen] = EOS;

    if (fileptr.data[fileptr.size - 1] != EOL)
    {
        fileptr.data[fileptr.size] = EOL;
        fileptr.size++;
    }
    
    fileptr.data[fileptr.size] = EOS;

    return &fileptr;
}

/* This should come from stdio.h and be some system-optimal number */
#ifndef BUFSIZ
#define BUFSIZ 1024
#endif

/******************************************************************************/
/* Suck the standard input into a file_buffer structure, and
   return a pointer to that structure. */

file_buffer_ty * read_stdin (void)
{
    static file_buffer_ty stdinptr;

    unsigned int          size = 15 * BUFSIZ;
    int                   ch;
    char                * p = NULL;

    if (stdinptr.data != 0)
    {
        free (stdinptr.data);
    }

    stdinptr.data = (char *) xmalloc (size + 1);
    stdinptr.size = 0;
    
    p = stdinptr.data;
    
    do
    {
        while (stdinptr.size < size)
        {
            ch = getc (stdin);
            
            if (ch == EOF)
            {
                break;
            }

            *p++ = ch;
            stdinptr.size++;
        }

        if (ch != EOF)
        {
            size += (2 * BUFSIZ);
            stdinptr.data = xrealloc (stdinptr.data, (unsigned) size);
            p = stdinptr.data + stdinptr.size;
        }
    } while (ch != EOF);

    stdinptr.name = "Standard Input";

    stdinptr.data[stdinptr.size] = EOS;

    return &stdinptr;
}

/******************************************************************************/
/* Advance `buf_ptr' so that it points to the next line of input.
 *
 * If the next input line contains an indent control comment turning
 * off formatting (a comment, C or C++, beginning with *INDENT-OFF*),
 * disable indenting by calling inhibit_indenting() which will cause
 * `dump_line ()' to simply print out all input lines without formatting
 * until it finds a corresponding comment containing *INDENT-0N* which
 * re-enables formatting.
 *
 * Note that if this is a C comment we do not look for the closing
 * delimiter.  Note also that older version of this program also
 * skipped lines containing *INDENT** which represented errors
 * generated by indent in some previous formatting.  This version does
 * not recognize such lines. */

void fill_buffer (void)
{
    char    * p = NULL;
    BOOLEAN   finished_a_line = false;

    /* indent() may be saving the text between "if (...)" and the following
     * statement.  To do so, it uses another buffer (`save_com').  Switch
     * back to the previous buffer here. */
    
    if (bp_save != 0)
    {
        buf_ptr = bp_save;
        buf_end = be_save;
        bp_save = be_save = 0;

        /* only return if there is really something in this buffer */
        
        if (buf_ptr < buf_end)
        {
            return;
        }
    }

    if (*in_prog_pos == EOS)
    {
        cur_line = buf_ptr = in_prog_pos;
        had_eof = true;
        return;
    }

    /* Here if we know there are chars to read.  The file is
     * NULL-terminated, so we can always look one character ahead
     * safely. */
    
    p = cur_line = in_prog_pos;
    finished_a_line = false;
    
    do
    {
        p = skip_horiz_space(p);

        /* If we are looking at the beginning of a comment, see
         * if it turns off formatting with off-on directives. */
        
        if (is_comment_start(p))
        {
            p += 2;
            
            p = skip_horiz_space(p);
            
            /* Skip all lines between the indent off and on directives. */
            
            if (strncmp (p, "*INDENT-OFF*", 12) == 0)
            {
                inhibit_indenting(true);
            }
        }

        while ((*p != EOS) && *p != EOL)
        {
            p++;
        }

        /* Here for newline -- finish up unless formatting is off */
        
        if (*p == EOL)
        {
            finished_a_line = true;
            in_prog_pos = p + 1;
        }
        
        /* Here for embedded NULLs */
        
        else if ((unsigned int) (p - current_input->data) < current_input->size)
        {
            WARNING (_("Warning: File %s contains NULL-characters\n"), current_input->name, 0);
            p++;
        }
        
        /* Here for EOF with no terminating newline char. */
        else
        {
            in_prog_pos = p;
            finished_a_line = true;
        }
    } while (!finished_a_line);

    buf_ptr = cur_line;
    buf_end = in_prog_pos;
    
    if (buf_break && ((buf_break->offset >= e_code - s_code) || (buf_break->offset <= 0)))
    {
        clear_buf_break_list ();
    }
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.