home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / asty1153.zip / astyle_main.cpp < prev    next >
C/C++ Source or Header  |  2002-03-07  |  27KB  |  833 lines

  1. /*
  2.  * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
  3.  *
  4.  * astyle_main.cpp
  5.  * Copyright (c) 1998,1999,2000 Tal Davidson (davidsont@bigfoot.com). All rights reserved.
  6.  *
  7.  * This file is a part of "Artistic Style" - an indentater and reformatter
  8.  * of C, C++, C# and Java source files.
  9.  *
  10.  * The "Artistic Style" project, including all files needed to compile it,
  11.  * is free software; you can redistribute it and/or use it and/or modify it
  12.  * under the terms of the GNU General Public License as published 
  13.  * by the Free Software Foundation; either version 2 of the License, 
  14.  * or (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  19.  *
  20.  * You should have received a copy of the GNU General Public
  21.  * License along with this program.
  22.  *
  23.  */
  24.  
  25. #include "compiler_defines.h"
  26. #include "astyle.h"
  27.  
  28. #include <iostream>
  29. #include <fstream>
  30. #include <string>
  31. #include <stdio.h>
  32.  
  33.  
  34. #define IS_OPTION(arg,op)          ((arg).compare(op)==0)
  35. #define IS_OPTIONS(arg,a,b)        (IS_OPTION((arg),(a)) || IS_OPTION((arg),(b)))
  36.  
  37. #define IS_PARAM_OPTION(arg,op)    ((arg).COMPARE(0, strlen(op) , string(op))==0)
  38. #define IS_PARAM_OPTIONS(arg,a,b)  (IS_PARAM_OPTION((arg),(a)) || IS_PARAM_OPTION((arg),(b)))
  39.  
  40. #define GET_PARAM(arg,op)          ((arg).substr(strlen(op)))
  41. #define GET_PARAMS(arg,a,b)        (IS_PARAM_OPTION((arg),(a)) ? GET_PARAM((arg),(a)) : GET_PARAM((arg),(b)))
  42.  
  43.  
  44. #ifdef USES_NAMESPACE
  45. using namespace std;
  46. using namespace astyle;
  47. #endif
  48.  
  49. // default options:
  50. ostream *_err = &cerr;
  51. string _suffix = ".orig";
  52. bool _modeManuallySet;
  53.  
  54. const string _version = "1.15.3";
  55.  
  56.  
  57. class ASStreamIterator :
  58.             public ASSourceIterator
  59. {
  60.     public:
  61.         ASStreamIterator(istream *in);
  62.         virtual ~ASStreamIterator();
  63.         bool hasMoreLines() const;
  64.         string nextLine();
  65.  
  66.     private:
  67.         istream * inStream;
  68.         char buffer[2048];
  69. };
  70.  
  71. ASStreamIterator::ASStreamIterator(istream *in)
  72. {
  73.     inStream = in;
  74. }
  75.  
  76. ASStreamIterator::~ASStreamIterator()
  77. {
  78.     delete inStream;
  79. }
  80.  
  81.  
  82. bool ASStreamIterator::hasMoreLines() const
  83. {
  84.     if (*inStream)
  85.         return true;
  86.     else
  87.         return false;
  88. }
  89.  
  90. /*
  91. string ASStreamIterator::nextLine()
  92. {
  93.    char theInChar;
  94.    char peekedChar;
  95.    int  theBufferPosn = 0;
  96.  
  97.    //
  98.    // treat '\n', '\r', '\n\r' and '\r\n' as an endline.
  99.    //
  100.    while (theBufferPosn < 2047 && inStream->get(theInChar))
  101.    // while not eof
  102.    {
  103.       if (theInChar != '\n' && theInChar != '\r')
  104.       {
  105.      buffer[theBufferPosn] = theInChar;
  106.          theBufferPosn++;
  107.       }
  108.       else
  109.       {
  110.     peekedChar = inStream->peek();
  111.     if (peekedChar != theInChar && (peekedChar == '\r' || peekedChar == '\n') )
  112.          {
  113.             inStream->get(theInChar);
  114.          }
  115.          break;
  116.       }
  117.    }
  118.    buffer[theBufferPosn] = '\0';
  119.  
  120.    return string(buffer);
  121. }
  122. */
  123.  
  124.  
  125. string ASStreamIterator::nextLine()
  126. {
  127.     char *srcPtr;
  128.     char *filterPtr;
  129.  
  130.     inStream->getline(buffer, 2047);
  131.     srcPtr = filterPtr = buffer;
  132.  
  133.     while (*srcPtr != 0)
  134.     {
  135.         if (*srcPtr != '\r')
  136.             *filterPtr++ = *srcPtr;
  137.         srcPtr++;
  138.     }
  139.     *filterPtr = 0;
  140.  
  141.     return string(buffer);
  142. }
  143.  
  144.  
  145.  
  146. void error(const char *why, const char* what)
  147. {
  148.     (*_err) << why << ' ' << what <<'\n';
  149.     exit(1);
  150. }
  151.  
  152.  
  153.  
  154. template<class ITER>
  155. bool parseOptions(ASFormatter &formatter,
  156.                   const ITER &optionsBegin,
  157.                   const ITER &optionsEnd,
  158.                   const string &errorInfo)
  159. {
  160.     ITER option;
  161.     bool ok = true;
  162.     string arg, subArg;
  163.  
  164.     for (option = optionsBegin; option != optionsEnd; ++option)
  165.     {
  166.         arg = *option; //string(*option);
  167.  
  168.         if (arg.COMPARE(0, 2, string("--")) == 0)
  169.             ok &= parseOption(formatter, arg.substr(2), errorInfo);
  170.         else if (arg[0] == '-')
  171.         {
  172.             int i;
  173.  
  174.             for (i=1; i < arg.length(); ++i)
  175.             {
  176.                 if (isalpha(arg[i]) && i > 1)
  177.                 {
  178.                     ok &= parseOption(formatter, subArg, errorInfo);
  179.                     subArg = "";
  180.                 }
  181.                 subArg.append(1, arg[i]);
  182.             }
  183.             ok &= parseOption(formatter, subArg, errorInfo);
  184.             subArg = "";
  185.         }
  186.         else
  187.         {
  188.             ok &= parseOption(formatter, arg, errorInfo);
  189.             subArg = "";
  190.         }
  191.     }
  192.  
  193.     return ok;
  194. }
  195.  
  196. void manuallySetJavaStyle(ASFormatter &formatter)
  197. {
  198.     formatter.setJavaStyle();
  199.     _modeManuallySet = true;
  200. }
  201.  
  202. void manuallySetCStyle(ASFormatter &formatter)
  203. {
  204.     formatter.setCStyle();
  205.     _modeManuallySet = true;
  206. }
  207.  
  208.  
  209. bool parseOption(ASFormatter &formatter, const string &arg, const string &errorInfo)
  210. {
  211.     if ( IS_PARAM_OPTION(arg, "suffix=") )
  212.     {
  213.         string suffixParam = GET_PARAM(arg, "suffix=");
  214.         if (suffixParam.length() > 0)
  215.             _suffix = suffixParam;
  216.     }
  217.     else if ( IS_OPTION(arg ,"style=ansi") )
  218.     {
  219.         formatter.setBracketIndent(false);
  220.         formatter.setSpaceIndentation(4);
  221.         formatter.setBracketFormatMode(BREAK_MODE);
  222.         formatter.setClassIndent(false);
  223.         formatter.setSwitchIndent(false);
  224.         formatter.setNamespaceIndent(false);
  225.     }
  226.     else if ( IS_OPTION(arg ,"style=gnu") )
  227.     {
  228.         formatter.setBlockIndent(true);
  229.         formatter.setSpaceIndentation(2);
  230.         formatter.setBracketFormatMode(BREAK_MODE);
  231.         formatter.setClassIndent(false);
  232.         formatter.setSwitchIndent(false);
  233.         formatter.setNamespaceIndent(false);
  234.     }
  235.     else if ( IS_OPTION(arg ,"style=java") )
  236.     {
  237.         manuallySetJavaStyle(formatter);
  238.         formatter.setBracketIndent(false);
  239.         formatter.setSpaceIndentation(4);
  240.         formatter.setBracketFormatMode(ATTACH_MODE);
  241.         formatter.setSwitchIndent(false);
  242.     }
  243.     else if ( IS_OPTION(arg ,"style=kr") )
  244.     {
  245.         //manuallySetCStyle(formatter);
  246.         formatter.setBracketIndent(false);
  247.         formatter.setSpaceIndentation(4);
  248.         formatter.setBracketFormatMode(ATTACH_MODE);
  249.         formatter.setClassIndent(false);
  250.         formatter.setSwitchIndent(false);
  251.         formatter.setNamespaceIndent(false);
  252.     }
  253.     else if ( IS_OPTION(arg ,"style=linux") )
  254.     {
  255.         formatter.setBracketIndent(false);
  256.         formatter.setSpaceIndentation(8);
  257.         formatter.setBracketFormatMode(BDAC_MODE);
  258.         formatter.setClassIndent(false);
  259.         formatter.setSwitchIndent(false);
  260.         formatter.setNamespaceIndent(false);
  261.     }
  262.     else if ( IS_OPTIONS(arg ,"c", "mode=c") )
  263.     {
  264.         manuallySetCStyle(formatter);
  265.     }
  266.     else if ( IS_OPTIONS(arg ,"j", "mode=java") )
  267.     {
  268.         manuallySetJavaStyle(formatter);
  269.     }
  270.     else if ( IS_OPTIONS(arg, "t", "indent=tab=") )
  271.     {
  272.         int spaceNum = 4;
  273.         string spaceNumParam = GET_PARAMS(arg, "t", "indent=tab=");
  274.         if (spaceNumParam.length() > 0)
  275.             spaceNum = atoi(spaceNumParam.c_str());
  276.         formatter.setTabIndentation(spaceNum, false);
  277.     }
  278.     else if ( IS_OPTIONS(arg, "T", "force-indent=tab=") )
  279.     {
  280.         int spaceNum = 4;
  281.         string spaceNumParam = GET_PARAMS(arg, "T", "force-indent=tab=");
  282.         if (spaceNumParam.length() > 0)
  283.             spaceNum = atoi(spaceNumParam.c_str());
  284.         formatter.setTabIndentation(spaceNum, true);
  285.     }
  286.     else if ( IS_PARAM_OPTION(arg, "indent=tab") )
  287.     {
  288.         formatter.setTabIndentation(4);
  289.     }
  290.     else if ( IS_PARAM_OPTIONS(arg, "s", "indent=spaces=") )
  291.     {
  292.         int spaceNum = 4;
  293.         string spaceNumParam = GET_PARAMS(arg, "s", "indent=spaces=");
  294.         if (spaceNumParam.length() > 0)
  295.             spaceNum = atoi(spaceNumParam.c_str());
  296.         formatter.setSpaceIndentation(spaceNum);
  297.     }
  298.     else if ( IS_PARAM_OPTION(arg, "indent=spaces") )
  299.     {
  300.         formatter.setSpaceIndentation(4);
  301.     }
  302.     else if ( IS_PARAM_OPTIONS(arg, "m", "min-conditional-indent=") )
  303.     {
  304.         int minIndent = 0;
  305.         string minIndentParam = GET_PARAMS(arg, "m", "min-conditional-indent=");
  306.         if (minIndentParam.length() > 0)
  307.             minIndent = atoi(minIndentParam.c_str());
  308.         formatter.setMinConditionalIndentLength(minIndent);
  309.     }
  310.     else if ( IS_PARAM_OPTIONS(arg, "M", "max-instatement-indent=") )
  311.     {
  312.         int maxIndent = 40;
  313.         string maxIndentParam = GET_PARAMS(arg, "M", "max-instatement-indent=");
  314.         if (maxIndentParam.length() > 0)
  315.             maxIndent = atoi(maxIndentParam.c_str());
  316.         formatter.setMaxInStatementIndentLength(maxIndent);
  317.     }
  318.     else if ( IS_OPTIONS(arg, "B", "indent-brackets") )
  319.     {
  320.         formatter.setBracketIndent(true);
  321.     }
  322.     else if ( IS_OPTIONS(arg, "G", "indent-blocks") )
  323.     {
  324.         formatter.setBlockIndent(true);
  325.     }
  326.     else if ( IS_OPTIONS(arg, "N", "indent-namespaces") )
  327.     {
  328.         formatter.setNamespaceIndent(true);
  329.     }
  330.     else if ( IS_OPTIONS(arg, "C", "indent-classes") )
  331.     {
  332.         formatter.setClassIndent(true);
  333.     }
  334.     else if ( IS_OPTIONS(arg, "S", "indent-switches") )
  335.     {
  336.         formatter.setSwitchIndent(true);
  337.     }
  338.     else if ( IS_OPTIONS(arg, "K", "indent-cases") )
  339.     {
  340.         formatter.setCaseIndent(true);
  341.     }
  342.     else if ( IS_OPTIONS(arg, "L", "indent-labels") )
  343.     {
  344.         formatter.setLabelIndent(true);
  345.     }
  346.     else if ( IS_OPTION(arg, "brackets=break-closing-headers") )
  347.     {
  348.         formatter.setBreakClosingHeaderBracketsMode(true);
  349.     }
  350.     else if ( IS_OPTIONS(arg, "b", "brackets=break") )
  351.     {
  352.         formatter.setBracketFormatMode(BREAK_MODE);
  353.     }
  354.     else if ( IS_OPTIONS(arg, "a", "brackets=attach") )
  355.     {
  356.         formatter.setBracketFormatMode(ATTACH_MODE);
  357.     }
  358.     else if ( IS_OPTIONS(arg, "l", "brackets=linux") )
  359.     {
  360.         formatter.setBracketFormatMode(BDAC_MODE);
  361.     }
  362.     else if ( IS_OPTIONS(arg, "O", "one-line=keep-blocks") )
  363.     {
  364.         formatter.setBreakOneLineBlocksMode(false);
  365.     }
  366.     else if ( IS_OPTIONS(arg, "o", "one-line=keep-statements") )
  367.     {
  368.         formatter.setSingleStatementsMode(false);
  369.     }
  370.     else if ( IS_OPTION(arg, "pad=paren") )
  371.     {
  372.         formatter.setParenthesisPaddingMode(true);
  373.     }
  374.     else if ( IS_OPTIONS(arg, "P", "pad=all") )
  375.     {
  376.         formatter.setOperatorPaddingMode(true);
  377.         formatter.setParenthesisPaddingMode(true);
  378.     }
  379.     else if ( IS_OPTIONS(arg, "p", "pad=oper") )
  380.     {
  381.         formatter.setOperatorPaddingMode(true);
  382.     }
  383.     else if ( IS_OPTIONS(arg, "E", "fill-empty-lines") )
  384.     {
  385.         formatter.setEmptyLineFill(true);
  386.     }
  387.     else if (IS_OPTION(arg, "indent-preprocessor"))
  388.     {
  389.         formatter.setPreprocessorIndent(true);
  390.     }
  391.     else if (IS_OPTION(arg, "convert-tabs"))
  392.     {
  393.         formatter.setTabSpaceConversionMode(true);
  394.     }
  395.     else if (IS_OPTION(arg, "break-blocks=all"))
  396.     {
  397.         formatter.setBreakBlocksMode(true);
  398.         formatter.setBreakClosingHeaderBlocksMode(true);
  399.     }
  400.     else if (IS_OPTION(arg, "break-blocks"))
  401.     {
  402.         formatter.setBreakBlocksMode(true);
  403.     }
  404.     else if (IS_OPTION(arg, "break-elseifs"))
  405.     {
  406.         formatter.setBreakElseIfsMode(true);
  407.     }
  408.     else if ( IS_OPTIONS(arg, "X", "errors-to-standard-output") )
  409.     {
  410.         _err = &cout;
  411.     }
  412.     else if ( IS_OPTIONS(arg ,"v", "version") )
  413.     {
  414.         (*_err) << "Artistic Style " << _version << endl;
  415.         exit(1);
  416.     }
  417.     else
  418.     {
  419.         (*_err) << errorInfo << arg << endl;
  420.         return false; // unknown option
  421.     }
  422.  
  423.  
  424.  
  425.     return true; //o.k.
  426. }
  427.  
  428.  
  429.  
  430. void importOptions(istream &in, vector<string> &optionsVector)
  431. {
  432.     char ch;
  433.     string currentToken;
  434.  
  435.     while (in)
  436.     {
  437.         currentToken = "";
  438.         do
  439.         {
  440.             in.get(ch);
  441.  
  442.             // treat '#' as line comments
  443.             if (ch == '#')
  444.                 while (in)
  445.                 {
  446.                     in.get(ch);
  447.                     if (ch == '\n')
  448.                         break;
  449.                 }
  450.  
  451.             // break options on spaces, tabs or new-lines
  452.             if (ch == ' ' || ch == '\t' || ch == '\n')
  453.                 break;
  454.             else
  455.                 currentToken.append(1, ch);
  456.  
  457.         }
  458.         while (in);
  459.  
  460.         if (currentToken.length() != 0)
  461.             optionsVector.push_back(currentToken);
  462.     }
  463. }
  464.  
  465. bool stringEndsWith(const string &str, const string &suffix)
  466. {
  467.     int strIndex = str.length() - 1;
  468.     int suffixIndex = suffix.length() - 1;
  469.  
  470.     while (strIndex >= 0 && suffixIndex >= 0)
  471.     {
  472.         if (tolower(str[strIndex]) != tolower(suffix[suffixIndex]))
  473.             return false;
  474.  
  475.         --strIndex;
  476.         --suffixIndex;
  477.     }
  478.  
  479.     return true;
  480. }
  481.  
  482. void printHelp()
  483. {
  484.     (*_err) << endl;
  485.     (*_err) << "Artistic Style " << _version << "   (http://www.bigfoot.com/~davidsont/astyle)\n";
  486.     (*_err) << "                       (created by Tal Davidson, davidsont@bigfoot.com)\n";
  487.     (*_err) << endl;
  488.     (*_err) << "Usage  :  astyle [options] < Original > Beautified\n";
  489.     (*_err) << "          astyle [options] Foo.cpp Bar.cpp  [...]\n";
  490.     (*_err) << endl;
  491.     (*_err) << "When indenting a specific file, the resulting indented file RETAINS the\n";
  492.     (*_err) << "original file-name. The original pre-indented file is renamed, with a\n";
  493.     (*_err) << "suffix of \".orig\" added to the original filename.\n";
  494.     (*_err) << endl;
  495.     (*_err) << "By default, astyle is set up to indent C/C++/C# files, with 4 spaces per\n" ;
  496.     (*_err) << "indent, a maximal indentation of 40 spaces inside continuous statements,\n";
  497.     (*_err) << "and NO formatting.\n";
  498.     (*_err) << endl;
  499.     (*_err) << "Option's Format:\n";
  500.     (*_err) << "----------------\n";
  501.     (*_err) << "    Long options (starting with '--') must be written one at a time.\n";
  502.     (*_err) << "    Short options (starting with '-') may be appended together.\n";
  503.     (*_err) << "    Thus, -bps4 is the same as -b -p -s4.\n";
  504.     (*_err) << endl;
  505.     (*_err) << "Predefined Styling options:\n";
  506.     (*_err) << "--------------------\n";
  507.     (*_err) << "    --style=ansi\n";
  508.     (*_err) << "    ANSI style formatting/indenting.\n";
  509.     (*_err) << endl;
  510.     (*_err) << "    --style=kr\n";
  511.     (*_err) << "    Kernighan&Ritchie style formatting/indenting.\n";
  512.     (*_err) << endl;
  513.     (*_err) << "    --style=gnu\n";
  514.     (*_err) << "    GNU style formatting/indenting.\n";
  515.     (*_err) << endl;
  516.     (*_err) << "    --style=java\n";
  517.     (*_err) << "    Java mode, with standard java style formatting/indenting.\n";
  518.     (*_err) << endl;
  519.     (*_err) << "    --style=linux\n";
  520.     (*_err) << "    Linux mode (i.e. 8 spaces per indent, break definition-block\n";
  521.     (*_err) << "    brackets but attach command-block brackets.\n";
  522.     (*_err) << endl;
  523.     (*_err) << "Indentation options:\n";
  524.     (*_err) << "--------------------\n";
  525.     (*_err) << "    -c   OR   --mode=c\n";
  526.     (*_err) << "    Indent a C, C++ or C# source file (default)\n";
  527.     (*_err) << endl;
  528.     (*_err) << "    -j   OR   --mode=java\n";
  529.     (*_err) << "    Indent a Java(TM) source file\n";
  530.     (*_err) << endl;
  531.     (*_err) << "    -s   OR   -s#   OR   --indent=spaces=#\n";
  532.     (*_err) << "    Indent using # spaces per indent. Not specifying #\n" ;
  533.     (*_err) << "    will result in a default of 4 spacec per indent.\n" ;
  534.     (*_err) << endl;
  535.     (*_err) << "    -t   OR   -t#   OR   --indent=tab=#\n";
  536.     (*_err) << "    Indent using tab characters, assuming that each\n";
  537.     (*_err) << "    tab is # spaces long. Not specifying # will result\n";
  538.     (*_err) << "    in a default assumption of 4 spaces per tab.\n" ;
  539.     (*_err) << endl;
  540.     (*_err) << "    -T#   OR   --force-indent=tab=#";
  541.     (*_err) << "    Indent using tab characters, assuming that each\n";
  542.     (*_err) << "    tab is # spaces long. Force tabs to be used in areas\n";
  543.     (*_err) << "    Astyle would prefer to use spaces.\n" ;
  544.     (*_err) << endl;
  545.     (*_err) << "    -C   OR   --indent-classes\n";
  546.     (*_err) << "    Indent 'class' blocks, so that the inner 'public:',\n";
  547.     (*_err) << "    'protected:' and 'private: headers are indented in\n";
  548.     (*_err) << "    relation to the class block.\n";
  549.     (*_err) << endl;
  550.     (*_err) << "    -S   OR   --indent-switches\n";
  551.     (*_err) << "    Indent 'switch' blocks, so that the inner 'case XXX:'\n";
  552.     (*_err) << "    headers are indented in relation to the switch block.\n";
  553.     (*_err) << endl;
  554.     (*_err) << "    -K   OR   --indent-cases\n";
  555.     (*_err) << "    Indent 'case XXX:' lines, so that they are flush with\n";
  556.     (*_err) << "    their bodies..\n";
  557.     (*_err) << endl;
  558.     (*_err) << "    -N   OR   --indent-namespaces\n";
  559.     (*_err) << "    Indent the contents of namespace blocks.\n";
  560.     (*_err) << endl;
  561.     (*_err) << "    -B   OR   --indent-brackets\n";
  562.     (*_err) << "    Add extra indentation to '{' and '}' block brackets.\n";
  563.     (*_err) << endl;
  564.     (*_err) << "    -G   OR   --indent-blocks\n";
  565.     (*_err) << "    Add extra indentation entire blocks (including brackets).\n";
  566.     (*_err) << endl;
  567.     (*_err) << "    -L   OR   --indent-labels\n";
  568.     (*_err) << "    Indent labels so that they appear one indent less than\n";
  569.     (*_err) << "    the current indentation level, rather than being\n";
  570.     (*_err) << "    flushed completely to the left (which is the default).\n";
  571.     (*_err) << endl;
  572.     (*_err) << "    -m#  OR  --min-conditional-indent=#\n";
  573.     (*_err) << "    Indent a minimal # spaces in a continuous conditional\n";
  574.     (*_err) << "    belonging to a conditional header.\n";
  575.     (*_err) << endl;
  576.     (*_err) << "    -M#  OR  --max-instatement-indent=#\n";
  577.     (*_err) << "    Indent a maximal # spaces in a continuous statement,\n";
  578.     (*_err) << "    relatively to the previous line.\n";
  579.     (*_err) << endl;
  580.     (*_err) << "    -E  OR  --fill-empty-lines\n";
  581.     (*_err) << "    Fill empty lines with the white space of their\n";
  582.     (*_err) << "    previous lines.\n";
  583.     (*_err) << endl;
  584.     (*_err) << "    --indent-preprocessor\n";
  585.     (*_err) << "    Indent multi-line #define statements\n";
  586.     (*_err) << endl;
  587.     (*_err) << "Formatting options:\n";
  588.     (*_err) << "-------------------\n";
  589.     (*_err) << "    -b  OR  --brackets=break\n";
  590.     (*_err) << "    Break brackets from pre-block code (i.e. ANSI C/C++ style).\n";
  591.     (*_err) << endl;
  592.     (*_err) << "    -a  OR  --brackets=attach\n";
  593.     (*_err) << "    Attach brackets to pre-block code (i.e. Java/K&R style).\n";
  594.     (*_err) << endl;
  595.     (*_err) << "    -l  OR  --brackets=linux\n";
  596.     (*_err) << "    Break definition-block brackets and attach command-block\n";
  597.     (*_err) << "    brackets.\n";
  598.     (*_err) << endl;
  599.     (*_err) << "    --brackets=break-closing-headers\n";
  600.     (*_err) << "    Break brackets before closing headers (e.g. 'else', 'catch', ..).\n";
  601.     (*_err) << "    Should be appended to --brackets=attach or --brackets=linux.\n";
  602.     (*_err) << endl;
  603.     (*_err) << "    -o   OR  --one-line=keep-statements\n";
  604.     (*_err) << "    Don't break lines containing multiple statements into\n";
  605.     (*_err) << "    multiple single-statement lines.\n";
  606.     (*_err) << endl;
  607.     (*_err) << "    -O   OR  --one-line=keep-blocks\n";
  608.     (*_err) << "    Don't break blocks residing completely on one line\n";
  609.     (*_err) << endl;
  610.     (*_err) << "    -p   OR  --pad=oper\n";
  611.     (*_err) << "    Insert space paddings around operators only.\n";
  612.     (*_err) << endl;
  613.     (*_err) << "    --pad=paren\n";
  614.     (*_err) << "    Insert space paddings around parenthesies only.\n";
  615.     (*_err) << endl;
  616.     (*_err) << "    -P   OR  --pad=all\n";
  617.     (*_err) << "    Insert space paddings around operators AND parenthesies.\n";
  618.     (*_err) << endl;
  619.     (*_err) << "    --convert-tabs\n";
  620.     (*_err) << "    Convert tabs to spaces.\n";
  621.     (*_err) << endl;
  622.     (*_err) << "    --break-blocks\n";
  623.     (*_err) << "    Insert empty lines around unrelated blocks, labels, classes, ...\n";
  624.     (*_err) << endl;
  625.     (*_err) << "    --break-blocks=all\n";
  626.     (*_err) << "    Like --break-blocks, except also insert empty lines \n";
  627.     (*_err) << "    around closing headers (e.g. 'else', 'catch', ...).\n";
  628.     (*_err) << endl;
  629.     (*_err) << "    --break-elseifs\n";
  630.     (*_err) << "    Break 'else if()' statements into two different lines.\n";
  631.     (*_err) << endl;
  632.     (*_err) << "Other options:\n";
  633.     (*_err) << "-------------\n";
  634.     (*_err) << "    --suffix=####\n";
  635.     (*_err) << "    Append the suffix #### instead of '.orig' to original filename.\n";
  636.     (*_err) << endl;
  637.     (*_err) << "    -X   OR  --errors-to-standard-output\n";
  638.     (*_err) << "    Print errors and help information to standard-output rather than\n";
  639.     (*_err) << "    to standard-error.\n";
  640.     (*_err) << endl;
  641.     (*_err) << "    -v   OR   --version\n";
  642.     (*_err) << "    Print version number\n";
  643.     (*_err) << endl;
  644.     (*_err) << "    -h   OR   -?   OR   --help\n";
  645.     (*_err) << "    Print this help message\n";
  646.     (*_err) << endl;
  647.     (*_err) << "Default options file:\n";
  648.     (*_err) << "---------------------\n";
  649.     (*_err) << "    Artistic Style looks for a default options file in the\n";
  650.     (*_err) << "    following order:\n";
  651.     (*_err) << "    1. The contents of the ARTISTIC_STYLE_OPTIONS environment\n";
  652.     (*_err) << "       variable if it exists.\n";
  653.     (*_err) << "    2. The file called .astylerc in the directory pointed to by the\n";
  654.     (*_err) << "       HOME environment variable ( i.e. $HOME/.astylerc ).\n";
  655.     (*_err) << "    3. The file called .astylerc in the directory pointed to by the\n";
  656.     (*_err) << "       HOMEPATH environment variable ( i.e. %HOMEPATH%\\.astylerc ).\n";
  657.     (*_err) << "    If a default options file is found, the options in this file\n";
  658.     (*_err) << "    will be parsed BEFORE the command-line options.\n";
  659.     (*_err) << "    Options within the default option file may be written without\n";
  660.     (*_err) << "    the preliminary '-' or '--'.\n";
  661.     (*_err) << endl;
  662. }
  663.  
  664. int main(int argc, char *argv[])
  665. {
  666.     ASFormatter formatter;
  667.     vector<string> fileNameVector;
  668.     vector<string> optionsVector;
  669.     string optionsFileName = "";
  670.     string arg;
  671.     bool ok = true;
  672.     bool shouldPrintHelp = false;
  673.     bool shouldParseOptionsFile = true;
  674.  
  675.     _err = &cerr;
  676.     _suffix = ".orig";
  677.     _modeManuallySet = false;
  678.  
  679.     // manage flags
  680.     for (int i=1; i<argc; i++)
  681.     {
  682.         arg = string(argv[i]);
  683.  
  684.         if ( IS_PARAM_OPTION(arg ,"--options=none") )
  685.         {
  686.             shouldParseOptionsFile = false;
  687.         }
  688.         else if ( IS_PARAM_OPTION(arg ,"--options=") )
  689.         {
  690.             optionsFileName = GET_PARAM(arg, "--options=");
  691.         }
  692.         else if ( IS_OPTION(arg, "-h")
  693.                   || IS_OPTION(arg, "--help")
  694.                   || IS_OPTION(arg, "-?") )
  695.         {
  696.             shouldPrintHelp = true;
  697.         }
  698.         else if (arg[0] == '-')
  699.         {
  700.             optionsVector.push_back(arg);
  701.         }
  702.         else // file-name
  703.         {
  704.             fileNameVector.push_back(arg);
  705.         }
  706.     }
  707.  
  708.     // parse options file
  709.     if (shouldParseOptionsFile)
  710.     {
  711.         if (optionsFileName.compare("") == 0)
  712.         {
  713.             char* env = getenv("ARTISTIC_STYLE_OPTIONS");
  714.             if (env != NULL)
  715.                 optionsFileName = string(env);
  716.         }
  717.         if (optionsFileName.compare("") == 0)
  718.         {
  719.             char* env = getenv("HOME");
  720.             if (env != NULL)
  721.                 optionsFileName = string(env) + string("/.astylerc");
  722.         }
  723.         if (optionsFileName.compare("") == 0)
  724.         {
  725.             char* env = getenv("HOMEPATH");
  726.             if (env != NULL)
  727.                 optionsFileName = string(env) + string("/.astylerc");
  728.         }
  729.  
  730.         if (optionsFileName.compare("") != 0)
  731.         {
  732.             ifstream optionsIn(optionsFileName.c_str());
  733.             if (optionsIn)
  734.             {
  735.                 vector<string> fileOptionsVector;
  736.                 importOptions(optionsIn, fileOptionsVector);
  737.                 ok = parseOptions(formatter,
  738.                                   fileOptionsVector.begin(),
  739.                                   fileOptionsVector.end(),
  740.                                   string("Unknown option in default options file: "));
  741.             }
  742.  
  743.             optionsIn.close();
  744.             if (!ok)
  745.             {
  746.                 (*_err) << "For help on options, type 'astyle -h' " << endl;
  747.             }
  748.         }
  749.     }
  750.  
  751.     // parse options from command line
  752.  
  753.     ok = parseOptions(formatter,
  754.                       optionsVector.begin(),
  755.                       optionsVector.end(),
  756.                       string("Unknown command line option: "));
  757.     if (!ok)
  758.     {
  759.         (*_err) << "For help on options, type 'astyle -h' " << endl;
  760.         exit(1);
  761.     }
  762.  
  763.     if (shouldPrintHelp)
  764.     {
  765.         printHelp();
  766.         exit(1);
  767.     }
  768.  
  769.     // if no files have been given, use cin for input and cout for output
  770.     if (fileNameVector.empty())
  771.     {
  772.         formatter.init( new ASStreamIterator(&cin) );
  773.  
  774.         while (formatter.hasMoreLines() )
  775.         {
  776.             cout << formatter.nextLine();
  777.             if (formatter.hasMoreLines())
  778.                 cout << endl;
  779.         }
  780.         cout.flush();
  781.     }
  782.     else
  783.     {
  784.         // indent the given files
  785.         for (int i=0; i<fileNameVector.size(); i++)
  786.         {
  787.             string originalFileName = fileNameVector[i];
  788.             string inFileName = originalFileName + _suffix;
  789.  
  790.             remove(inFileName.c_str());
  791.  
  792.             if ( rename(originalFileName.c_str(), inFileName.c_str()) < 0)
  793.                 error("Could not rename ", string(originalFileName + " to " + inFileName).c_str());
  794.  
  795.             ifstream in(inFileName.c_str());
  796.             if (!in)
  797.                 error("Could not open input file", inFileName.c_str());
  798.  
  799.             ofstream out(originalFileName.c_str());
  800.             if (!out)
  801.                 error("Could not open output file", originalFileName.c_str());
  802.  
  803.             // Unless a specific language mode has been, set the language mode
  804.             // according to the file's suffix.
  805.             if (!_modeManuallySet)
  806.             {
  807.                 if (stringEndsWith(originalFileName, string(".java")))
  808.                 {
  809.                     formatter.setJavaStyle();
  810.                 }
  811.                 else
  812.                 {
  813.                     formatter.setCStyle();
  814.                 }
  815.             }
  816.  
  817.             formatter.init( new ASStreamIterator(&in) );
  818.             while (formatter.hasMoreLines() )
  819.             {
  820.                 out << formatter.nextLine();
  821.                 if (formatter.hasMoreLines())
  822.                     out << endl;
  823.             }
  824.  
  825.             out.flush();
  826.             out.close();
  827.  
  828.             in.close();
  829.         }
  830.     }
  831.     return 0;
  832. }
  833.