mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
1138 lines
33 KiB
C++
1138 lines
33 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* astyle_main.cpp
|
|
*
|
|
* This file is a part of "Artistic Style" - an indentation and
|
|
* reformatting tool for C, C++, C# and Java source files.
|
|
* http://astyle.sourceforge.net
|
|
*
|
|
* The "Artistic Style" project, including all files needed to
|
|
* compile it, is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this project; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*/
|
|
|
|
#include "astyle.h"
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <cstdlib>
|
|
#include <ctime>
|
|
|
|
#ifndef ASTYLE_LIB // for console build only
|
|
#if defined(_MSC_VER) || defined(__DMC__)
|
|
#include <sys/utime.h>
|
|
#include <sys/stat.h>
|
|
//#define utimbuf _utimbuf
|
|
//#define utime _utime
|
|
#else
|
|
#include <utime.h>
|
|
#include <sys/stat.h>
|
|
#endif // end compiler checks
|
|
#endif // end ASTYLE_LIB
|
|
|
|
// for G++ implementation of string.compare:
|
|
// compare((str), (place), (length)) instead of compare(place, length, str)
|
|
#if defined(__GNUC__) && __GNUC__ < 3
|
|
#error - Use GNU C compiler release 3 or higher
|
|
#endif
|
|
|
|
// for namespace problem in version 5.0
|
|
#if defined(_MSC_VER) && _MSC_VER < 1200 // check for V6.0
|
|
#error - Use Microsoft compiler version 6 or higher
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#define STDCALL __stdcall
|
|
#define EXPORT __declspec(dllexport)
|
|
#else
|
|
#define STDCALL
|
|
#define EXPORT
|
|
#endif
|
|
|
|
#define IS_OPTION(arg,op) ((arg).compare(op)==0)
|
|
#define IS_OPTIONS(arg,a,b) (IS_OPTION((arg),(a)) || IS_OPTION((arg),(b)))
|
|
|
|
#define GET_PARAM(arg,op) ((arg).substr(strlen(op)))
|
|
#define GET_PARAMS(arg,a,b) (isParamOption((arg),(a)) ? GET_PARAM((arg),(a)) : GET_PARAM((arg),(b)))
|
|
|
|
using namespace astyle;
|
|
|
|
const char* _version = "1.21";
|
|
|
|
// some compilers want this declared
|
|
bool parseOption(ASFormatter &formatter, const string &arg, const string &errorInfo);
|
|
|
|
#ifdef ASTYLE_LIB
|
|
// GUI function pointers
|
|
typedef void (STDCALL *fpError)(int, char*); // pointer to callback error handler
|
|
typedef char* (STDCALL *fpAlloc)(unsigned long); // pointer to callback memory allocation
|
|
// GUI variables
|
|
stringstream *_err = NULL;
|
|
#else
|
|
// console variables
|
|
ostream *_err = &cerr;
|
|
bool _purgeOrigIn = false;
|
|
bool _preserveDate = false;
|
|
string _suffix = ".orig";
|
|
stringstream _msg; // info messages are not printed until a file is read
|
|
#endif
|
|
bool _modeManuallySet = false;
|
|
|
|
|
|
// typename will be istringstream for GUI and istream otherwise
|
|
template<typename T>
|
|
class ASStreamIterator :
|
|
public ASSourceIterator
|
|
{
|
|
public:
|
|
ASStreamIterator(T *in);
|
|
virtual ~ASStreamIterator();
|
|
bool hasMoreLines() const;
|
|
string nextLine();
|
|
|
|
private:
|
|
T * inStream;
|
|
string buffer;
|
|
bool inStreamEOF;
|
|
};
|
|
|
|
template<typename T>
|
|
ASStreamIterator<T>::ASStreamIterator(T *in)
|
|
{
|
|
inStream = in;
|
|
buffer.reserve(200);
|
|
inStreamEOF = false;
|
|
}
|
|
|
|
|
|
template<typename T>
|
|
ASStreamIterator<T>::~ASStreamIterator()
|
|
{
|
|
}
|
|
|
|
|
|
template<typename T>
|
|
bool ASStreamIterator<T>::hasMoreLines() const
|
|
{
|
|
return !inStreamEOF;
|
|
}
|
|
|
|
|
|
/**
|
|
* read the input stream, delete any end of line characters,
|
|
* and build a string that contains the input line.
|
|
*
|
|
* @return string containing the next input line minus any end of line characters
|
|
*/
|
|
template<typename T>
|
|
string ASStreamIterator<T>::nextLine()
|
|
{
|
|
char ch;
|
|
char LF = '\n';
|
|
char CR = '\r';
|
|
inStream->get(ch);
|
|
buffer.clear();
|
|
|
|
while (!inStream->eof() && ch != LF && ch != CR)
|
|
{
|
|
buffer.append(1, ch);
|
|
inStream->get(ch);
|
|
}
|
|
|
|
if (inStream->eof())
|
|
{
|
|
inStreamEOF = true;
|
|
return buffer;
|
|
}
|
|
|
|
int peekch = inStream->peek();
|
|
|
|
if (ch == CR) // CR+LF is windows otherwise Mac OS 9
|
|
{
|
|
if (peekch == LF)
|
|
{
|
|
inStream->get();
|
|
eolWindows++;
|
|
}
|
|
else
|
|
eolMacOld++;
|
|
}
|
|
else // LF is Linux, allow for improbable LF/CR
|
|
{
|
|
if (peekch == CR)
|
|
{
|
|
inStream->get();
|
|
eolWindows++;
|
|
}
|
|
else
|
|
eolLinux++;
|
|
}
|
|
|
|
// set output end of line character
|
|
if (eolWindows >= eolLinux)
|
|
if (eolWindows >= eolMacOld)
|
|
strcpy(outputEOL, "\r\n"); // Windows (CR+LF)
|
|
else
|
|
strcpy(outputEOL, "\r"); // MacOld (CR)
|
|
else
|
|
if (eolLinux >= eolMacOld)
|
|
strcpy(outputEOL, "\n"); // Linux (LF)
|
|
else
|
|
strcpy(outputEOL, "\r"); // MacOld (CR)
|
|
|
|
return buffer;
|
|
}
|
|
|
|
|
|
template<typename ITER>
|
|
bool parseOptions(ASFormatter &formatter,
|
|
const ITER &optionsBegin,
|
|
const ITER &optionsEnd,
|
|
const string &errorInfo)
|
|
{
|
|
ITER option;
|
|
bool ok = true;
|
|
string arg, subArg;
|
|
|
|
for (option = optionsBegin; option != optionsEnd; ++option)
|
|
{
|
|
arg = *option;
|
|
|
|
if (arg.compare(0, 2, "--") == 0)
|
|
ok &= parseOption(formatter, arg.substr(2), errorInfo);
|
|
else if (arg[0] == '-')
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 1; i < arg.length(); ++i)
|
|
{
|
|
if (isalpha(arg[i]) && i > 1)
|
|
{
|
|
ok &= parseOption(formatter, subArg, errorInfo);
|
|
subArg = "";
|
|
}
|
|
subArg.append(1, arg[i]);
|
|
}
|
|
ok &= parseOption(formatter, subArg, errorInfo);
|
|
subArg = "";
|
|
}
|
|
else
|
|
{
|
|
ok &= parseOption(formatter, arg, errorInfo);
|
|
subArg = "";
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void importOptions(istream &in, vector<string> &optionsVector)
|
|
{
|
|
char ch;
|
|
string currentToken;
|
|
|
|
while (in)
|
|
{
|
|
currentToken = "";
|
|
do
|
|
{
|
|
in.get(ch);
|
|
if (in.eof())
|
|
break;
|
|
// treat '#' as line comments
|
|
if (ch == '#')
|
|
while (in)
|
|
{
|
|
in.get(ch);
|
|
if (ch == '\n')
|
|
break;
|
|
}
|
|
|
|
// break options on spaces, tabs or new-lines
|
|
if (in.eof() || ch == ' ' || ch == '\t' || ch == '\n')
|
|
break;
|
|
else
|
|
currentToken.append(1, ch);
|
|
|
|
}
|
|
while (in);
|
|
|
|
if (currentToken.length() != 0)
|
|
optionsVector.push_back(currentToken);
|
|
}
|
|
}
|
|
|
|
bool isParamOption(const string &arg, const char *option)
|
|
{
|
|
bool retVal = arg.compare(0, strlen(option), option) == 0;
|
|
// if comparing for short option, 2nd char of arg must be numeric
|
|
if (retVal && strlen(option) == 1 && arg.length() > 1)
|
|
if (!isdigit(arg[1]))
|
|
retVal = false;
|
|
return retVal;
|
|
}
|
|
|
|
void isOptionError(const string &arg, const string &errorInfo)
|
|
{
|
|
#ifdef ASTYLE_LIB
|
|
if (_err->str().length() == 0)
|
|
{
|
|
(*_err) << errorInfo << endl; // need main error message
|
|
(*_err) << arg; // output the option in error
|
|
}
|
|
else
|
|
(*_err) << endl << arg; // put endl after previous option
|
|
#else
|
|
if (errorInfo.length() > 0) // to avoid a compiler warning
|
|
(*_err) << "Error in param: " << arg << endl;
|
|
#endif
|
|
}
|
|
|
|
bool isParamOption(const string &arg, const char *option1, const char *option2)
|
|
{
|
|
return isParamOption(arg, option1) || isParamOption(arg, option2);
|
|
}
|
|
|
|
|
|
bool parseOption(ASFormatter &formatter, const string &arg, const string &errorInfo)
|
|
{
|
|
if ( IS_OPTION(arg, "style=ansi") )
|
|
{
|
|
formatter.setSpaceIndentation(4);
|
|
formatter.setBracketFormatMode(BREAK_MODE);
|
|
formatter.setBracketIndent(false);
|
|
formatter.setClassIndent(false);
|
|
formatter.setSwitchIndent(false);
|
|
formatter.setNamespaceIndent(false);
|
|
}
|
|
else if ( IS_OPTION(arg, "style=gnu") )
|
|
{
|
|
formatter.setSpaceIndentation(2);
|
|
formatter.setBracketFormatMode(BREAK_MODE);
|
|
formatter.setBlockIndent(true);
|
|
formatter.setClassIndent(false);
|
|
formatter.setSwitchIndent(false);
|
|
formatter.setNamespaceIndent(false);
|
|
}
|
|
else if ( IS_OPTION(arg, "style=java") )
|
|
{
|
|
// formatter.setJavaStyle();
|
|
// _modeManuallySet = true;
|
|
formatter.setSpaceIndentation(4);
|
|
formatter.setBracketFormatMode(ATTACH_MODE);
|
|
formatter.setBracketIndent(false);
|
|
formatter.setSwitchIndent(false);
|
|
}
|
|
else if ( IS_OPTION(arg, "style=kr") )
|
|
{
|
|
//manuallySetCStyle(formatter);
|
|
formatter.setSpaceIndentation(4);
|
|
formatter.setBracketFormatMode(ATTACH_MODE);
|
|
formatter.setBracketIndent(false);
|
|
formatter.setClassIndent(false);
|
|
formatter.setSwitchIndent(false);
|
|
formatter.setNamespaceIndent(false);
|
|
}
|
|
else if ( IS_OPTION(arg, "style=linux") )
|
|
{
|
|
formatter.setSpaceIndentation(8);
|
|
formatter.setBracketFormatMode(BDAC_MODE);
|
|
formatter.setBracketIndent(false);
|
|
formatter.setClassIndent(false);
|
|
formatter.setSwitchIndent(false);
|
|
formatter.setNamespaceIndent(false);
|
|
}
|
|
// must check for mode=cs before mode=c !!!
|
|
else if ( IS_OPTION(arg, "mode=cs") )
|
|
{
|
|
formatter.setSharpStyle();
|
|
_modeManuallySet = true;
|
|
}
|
|
else if ( IS_OPTION(arg, "mode=c") )
|
|
{
|
|
formatter.setCStyle();
|
|
_modeManuallySet = true;
|
|
}
|
|
else if ( IS_OPTION(arg, "mode=java") )
|
|
{
|
|
formatter.setJavaStyle();
|
|
_modeManuallySet = true;
|
|
}
|
|
else if ( isParamOption(arg, "t", "indent=tab=") )
|
|
{
|
|
int spaceNum = 4;
|
|
string spaceNumParam = GET_PARAMS(arg, "t", "indent=tab=");
|
|
if (spaceNumParam.length() > 0)
|
|
spaceNum = atoi(spaceNumParam.c_str());
|
|
if (spaceNum < 2 || spaceNum > 20)
|
|
isOptionError(arg, errorInfo);
|
|
else
|
|
formatter.setTabIndentation(spaceNum, false);
|
|
}
|
|
else if ( isParamOption(arg, "T", "force-indent=tab=") )
|
|
{
|
|
int spaceNum = 4;
|
|
string spaceNumParam = GET_PARAMS(arg, "T", "force-indent=tab=");
|
|
if (spaceNumParam.length() > 0)
|
|
spaceNum = atoi(spaceNumParam.c_str());
|
|
if (spaceNum < 2 || spaceNum > 20)
|
|
isOptionError(arg, errorInfo);
|
|
else
|
|
formatter.setTabIndentation(spaceNum, true);
|
|
}
|
|
else if ( IS_OPTION(arg, "indent=tab") )
|
|
{
|
|
formatter.setTabIndentation(4);
|
|
}
|
|
else if ( isParamOption(arg, "s", "indent=spaces=") )
|
|
{
|
|
int spaceNum = 4;
|
|
string spaceNumParam = GET_PARAMS(arg, "s", "indent=spaces=");
|
|
if (spaceNumParam.length() > 0)
|
|
spaceNum = atoi(spaceNumParam.c_str());
|
|
if (spaceNum < 2 || spaceNum > 20)
|
|
isOptionError(arg, errorInfo);
|
|
else
|
|
formatter.setSpaceIndentation(spaceNum);
|
|
}
|
|
else if ( IS_OPTION(arg, "indent=spaces") )
|
|
{
|
|
formatter.setSpaceIndentation(4);
|
|
}
|
|
else if ( isParamOption(arg, "m", "min-conditional-indent=") )
|
|
{
|
|
int minIndent = 8;
|
|
string minIndentParam = GET_PARAMS(arg, "m", "min-conditional-indent=");
|
|
if (minIndentParam.length() > 0)
|
|
minIndent = atoi(minIndentParam.c_str());
|
|
if (minIndent > 40)
|
|
isOptionError(arg, errorInfo);
|
|
else
|
|
formatter.setMinConditionalIndentLength(minIndent);
|
|
}
|
|
else if ( isParamOption(arg, "M", "max-instatement-indent=") )
|
|
{
|
|
int maxIndent = 40;
|
|
string maxIndentParam = GET_PARAMS(arg, "M", "max-instatement-indent=");
|
|
if (maxIndentParam.length() > 0)
|
|
maxIndent = atoi(maxIndentParam.c_str());
|
|
if (maxIndent > 80)
|
|
isOptionError(arg, errorInfo);
|
|
else
|
|
formatter.setMaxInStatementIndentLength(maxIndent);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "B", "indent-brackets") )
|
|
{
|
|
formatter.setBracketIndent(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "G", "indent-blocks") )
|
|
{
|
|
formatter.setBlockIndent(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "N", "indent-namespaces") )
|
|
{
|
|
formatter.setNamespaceIndent(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "C", "indent-classes") )
|
|
{
|
|
formatter.setClassIndent(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "S", "indent-switches") )
|
|
{
|
|
formatter.setSwitchIndent(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "K", "indent-cases") )
|
|
{
|
|
formatter.setCaseIndent(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "L", "indent-labels") )
|
|
{
|
|
formatter.setLabelIndent(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "y", "brackets=break-closing") )
|
|
{
|
|
formatter.setBreakClosingHeaderBracketsMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "b", "brackets=break") )
|
|
{
|
|
formatter.setBracketFormatMode(BREAK_MODE);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "a", "brackets=attach") )
|
|
{
|
|
formatter.setBracketFormatMode(ATTACH_MODE);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "l", "brackets=linux") )
|
|
{
|
|
formatter.setBracketFormatMode(BDAC_MODE);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "O", "one-line=keep-blocks") )
|
|
{
|
|
formatter.setBreakOneLineBlocksMode(false);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "o", "one-line=keep-statements") )
|
|
{
|
|
formatter.setSingleStatementsMode(false);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "P", "pad=paren") )
|
|
{
|
|
formatter.setParensOutsidePaddingMode(true);
|
|
formatter.setParensInsidePaddingMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "d", "pad=paren-out") )
|
|
{
|
|
formatter.setParensOutsidePaddingMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "D", "pad=paren-in") )
|
|
{
|
|
formatter.setParensInsidePaddingMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "U", "unpad=paren") )
|
|
{
|
|
formatter.setParensUnPaddingMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "p", "pad=oper") )
|
|
{
|
|
formatter.setOperatorPaddingMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "E", "fill-empty-lines") )
|
|
{
|
|
formatter.setEmptyLineFill(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "w", "indent-preprocessor") )
|
|
{
|
|
formatter.setPreprocessorIndent(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "V", "convert-tabs") )
|
|
{
|
|
formatter.setTabSpaceConversionMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "F", "break-blocks=all") )
|
|
{
|
|
formatter.setBreakBlocksMode(true);
|
|
formatter.setBreakClosingHeaderBlocksMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "f", "break-blocks") )
|
|
{
|
|
formatter.setBreakBlocksMode(true);
|
|
}
|
|
else if ( IS_OPTIONS(arg, "e", "break-elseifs") )
|
|
{
|
|
formatter.setBreakElseIfsMode(true);
|
|
}
|
|
#ifdef ASTYLE_LIB
|
|
// End of options used by GUI
|
|
else
|
|
isOptionError(arg, errorInfo);
|
|
#else
|
|
// Options used by only console
|
|
else if ( IS_OPTIONS(arg, "n", "suffix=none") )
|
|
{
|
|
_purgeOrigIn = true;
|
|
}
|
|
else if ( isParamOption(arg, "suffix=") )
|
|
{
|
|
string suffixParam = GET_PARAM(arg, "suffix=");
|
|
if (suffixParam.length() > 0)
|
|
{
|
|
_suffix = suffixParam;
|
|
// if (_suffix[0] != '.')
|
|
// _suffix = '.' + _suffix;
|
|
}
|
|
}
|
|
else if ( IS_OPTIONS(arg, "Z", "preserve-date") )
|
|
{
|
|
_preserveDate =true;
|
|
}
|
|
else if ( IS_OPTIONS(arg, "X", "errors-to-stdout") )
|
|
{
|
|
_err = &cout;
|
|
}
|
|
else if ( IS_OPTIONS(arg, "v", "version") )
|
|
{
|
|
(*_err) << "Artistic Style " << _version << endl;
|
|
exit(0);
|
|
}
|
|
else
|
|
{
|
|
(*_err) << errorInfo << arg << endl;
|
|
return false; // unknown option
|
|
}
|
|
#endif
|
|
// End of parseOption function
|
|
return true; //o.k.
|
|
}
|
|
|
|
|
|
#ifdef ASTYLE_LIB
|
|
// ************************* GUI functions *****************************************************
|
|
/*
|
|
* IMPORTANT VC DLL linker must have the parameter /EXPORT:AStyleMain=_AStyleMain@16
|
|
* /EXPORT:AStyleGetVersion=_AStyleGetVersion@0
|
|
* For Dll only - "warning C4702: unreachable code" in the <vector> header
|
|
* is caused by using the Optimization options.
|
|
* /O2 Maximize speed
|
|
* /O1 Minimize size
|
|
* /Ob2 Inline Expansion
|
|
* This is a bug in the Microsoft compiler. The program runs about twice as fast
|
|
* with the options set. There haven't been any problems so far.
|
|
*/
|
|
extern "C" EXPORT char* STDCALL
|
|
AStyleMain(const char* pSourceIn, // pointer to the source to be formatted
|
|
const char* pOptions, // pointer to AStyle options, separated by \n
|
|
fpError fpErrorHandler, // pointer to error handler function
|
|
fpAlloc fpMemoryAlloc) // pointer to memory allocation function
|
|
{
|
|
if (fpErrorHandler == NULL) // cannot display a message if no error handler
|
|
return NULL;
|
|
|
|
if (pSourceIn == NULL)
|
|
{
|
|
fpErrorHandler(101, "No pointer to source input");
|
|
return NULL;
|
|
}
|
|
if (pOptions == NULL)
|
|
{
|
|
fpErrorHandler(102, "No pointer to AStyle options");
|
|
return NULL;
|
|
}
|
|
if (fpMemoryAlloc == NULL)
|
|
{
|
|
fpErrorHandler(103, "No pointer to memory allocation function");
|
|
return NULL;
|
|
}
|
|
|
|
ASFormatter formatter;
|
|
|
|
string arg;
|
|
vector<string> optionsVector;
|
|
istringstream opt(pOptions);
|
|
_err = new stringstream;
|
|
_modeManuallySet = false;
|
|
|
|
importOptions(opt, optionsVector);
|
|
|
|
parseOptions(formatter,
|
|
optionsVector.begin(),
|
|
optionsVector.end(),
|
|
"Unknown Artistic Style options\n"
|
|
"The following options were not processed:");
|
|
|
|
if (_err->str().length() > 0)
|
|
fpErrorHandler(210, (char*) _err->str().c_str());
|
|
|
|
delete _err;
|
|
_err = NULL;
|
|
|
|
istringstream in(pSourceIn);
|
|
ASStreamIterator<istringstream> streamIterator(&in);
|
|
ostringstream out;
|
|
formatter.init(&streamIterator);
|
|
|
|
while (formatter.hasMoreLines())
|
|
{
|
|
out << formatter.nextLine();
|
|
out << streamIterator.outputEOL;
|
|
}
|
|
|
|
unsigned long textSizeOut = out.str().length();
|
|
char* pTextOut = fpMemoryAlloc(textSizeOut + 1); // call memory allocation function
|
|
// pTextOut = NULL; // for testing
|
|
if (pTextOut == NULL)
|
|
{
|
|
fpErrorHandler(110, "Allocation failure on output");
|
|
return NULL;
|
|
}
|
|
|
|
strcpy(pTextOut, out.str().c_str());
|
|
|
|
return pTextOut;
|
|
}
|
|
|
|
extern "C" EXPORT const char* STDCALL AStyleGetVersion (void)
|
|
{
|
|
return _version;
|
|
}
|
|
|
|
#else
|
|
|
|
void preserveFileDate(const char *oldFileName, const char *newFileName)
|
|
{
|
|
struct stat stBuf;
|
|
bool statErr = false;
|
|
if (stat (oldFileName, &stBuf) == -1)
|
|
statErr = true;
|
|
else
|
|
{
|
|
struct utimbuf outBuf;
|
|
outBuf.actime = stBuf.st_atime;
|
|
// add 1 so RCS will recoginze a change
|
|
outBuf.modtime = stBuf.st_mtime + 1;
|
|
if (utime (newFileName, &outBuf) == -1)
|
|
statErr = true;
|
|
}
|
|
if (statErr)
|
|
(*_err) << " Could not preserve file date" << endl;
|
|
}
|
|
|
|
bool stringEndsWith(const string &str, const string &suffix)
|
|
{
|
|
int strIndex = (int) str.length() - 1;
|
|
int suffixIndex = (int) suffix.length() - 1;
|
|
|
|
while (strIndex >= 0 && suffixIndex >= 0)
|
|
{
|
|
if (tolower(str[strIndex]) != tolower(suffix[suffixIndex]))
|
|
return false;
|
|
|
|
--strIndex;
|
|
--suffixIndex;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void error(const char *why, const char* what)
|
|
{
|
|
(*_err) << why << ' ' << what << '\n' << endl;
|
|
exit(1);
|
|
}
|
|
|
|
|
|
void printHelp()
|
|
{
|
|
(*_err) << endl;
|
|
(*_err) << " Artistic Style " << _version << endl;
|
|
(*_err) << " Maintained by: Jim Pattee\n";
|
|
(*_err) << " Original Author: Tal Davidson\n";
|
|
(*_err) << endl;
|
|
(*_err) << "Usage : astyle [options] Source1.cpp Source2.cpp [...]\n";
|
|
(*_err) << " astyle [options] < Original > Beautified\n";
|
|
(*_err) << endl;
|
|
(*_err) << "When indenting a specific file, the resulting indented file RETAINS the\n";
|
|
(*_err) << "original file-name. The original pre-indented file is renamed, with a\n";
|
|
(*_err) << "suffix of \".orig\" added to the original filename.\n";
|
|
(*_err) << endl;
|
|
(*_err) << "By default, astyle is set up to indent C/C++/C#/Java files, with 4 spaces\n";
|
|
(*_err) << "per indent, a maximal indentation of 40 spaces inside continuous statements,\n";
|
|
(*_err) << "and NO formatting.\n";
|
|
(*_err) << endl;
|
|
(*_err) << "Option's Format:\n";
|
|
(*_err) << "----------------\n";
|
|
(*_err) << " Long options (starting with '--') must be written one at a time.\n";
|
|
(*_err) << " Short options (starting with '-') may be appended together.\n";
|
|
(*_err) << " Thus, -bps4 is the same as -b -p -s4.\n";
|
|
(*_err) << endl;
|
|
(*_err) << "Predefined Style Options:\n";
|
|
(*_err) << "-------------------------\n";
|
|
(*_err) << " --style=ansi\n";
|
|
(*_err) << " ANSI style formatting/indenting.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --style=gnu\n";
|
|
(*_err) << " GNU style formatting/indenting.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --style=kr\n";
|
|
(*_err) << " Kernighan&Ritchie style formatting/indenting.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --style=linux\n";
|
|
(*_err) << " Linux mode (8 spaces per indent, break definition-block\n";
|
|
(*_err) << " brackets but attach command-block brackets).\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --style=java\n";
|
|
(*_err) << " Java mode, with standard java style formatting/indenting.\n";
|
|
(*_err) << endl;
|
|
(*_err) << "Tab and Bracket Options:\n";
|
|
(*_err) << "------------------------\n";
|
|
(*_err) << " default indent option\n";
|
|
(*_err) << " If no indentation option is set,\n";
|
|
(*_err) << " the default option of 4 spaces will be used.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent=spaces=# OR -s#\n";
|
|
(*_err) << " Indent using # spaces per indent. Not specifying #\n";
|
|
(*_err) << " will result in a default of 4 spaces per indent.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent=tab OR --indent=tab=# OR -t OR -t#\n";
|
|
(*_err) << " Indent using tab characters, assuming that each\n";
|
|
(*_err) << " tab is # spaces long. Not specifying # will result\n";
|
|
(*_err) << " in a default assumption of 4 spaces per tab.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --force-indent=tab=# OR -T#\n";
|
|
(*_err) << " Indent using tab characters, assuming that each\n";
|
|
(*_err) << " tab is # spaces long. Force tabs to be used in areas\n";
|
|
(*_err) << " Astyle would prefer to use spaces.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " default brackets option\n";
|
|
(*_err) << " If no brackets option is set,\n";
|
|
(*_err) << " the brackets will not be changed.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --brackets=break OR -b\n";
|
|
(*_err) << " Break brackets from pre-block code (i.e. ANSI C/C++ style).\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --brackets=attach OR -a\n";
|
|
(*_err) << " Attach brackets to pre-block code (i.e. Java/K&R style).\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --brackets=linux OR -l\n";
|
|
(*_err) << " Break definition-block brackets and attach command-block\n";
|
|
(*_err) << " brackets.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --brackets=break-closing OR -y\n";
|
|
(*_err) << " Break brackets before closing headers (e.g. 'else', 'catch', ...).\n";
|
|
(*_err) << " Should be appended to --brackets=attach or --brackets=linux.\n";
|
|
(*_err) << endl;
|
|
(*_err) << "Indentation options:\n";
|
|
(*_err) << "--------------------\n";
|
|
(*_err) << " --indent-classes OR -C\n";
|
|
(*_err) << " Indent 'class' blocks, so that the inner 'public:',\n";
|
|
(*_err) << " 'protected:' and 'private: headers are indented in\n";
|
|
(*_err) << " relation to the class block.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent-switches OR -S\n";
|
|
(*_err) << " Indent 'switch' blocks, so that the inner 'case XXX:'\n";
|
|
(*_err) << " headers are indented in relation to the switch block.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent-cases OR -K\n";
|
|
(*_err) << " Indent case blocks from the 'case XXX:' headers.\n";
|
|
(*_err) << " Case statements not enclosed in blocks are NOT indented.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent-brackets OR -B\n";
|
|
(*_err) << " Add extra indentation to '{' and '}' block brackets.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent-blocks OR -G\n";
|
|
(*_err) << " Add extra indentation entire blocks (including brackets).\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent-namespaces OR -N\n";
|
|
(*_err) << " Indent the contents of namespace blocks.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent-labels OR -L\n";
|
|
(*_err) << " Indent labels so that they appear one indent less than\n";
|
|
(*_err) << " the current indentation level, rather than being\n";
|
|
(*_err) << " flushed completely to the left (which is the default).\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --indent-preprocessor OR -w\n";
|
|
(*_err) << " Indent multi-line #define statements.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --max-instatement-indent=# OR -M#\n";
|
|
(*_err) << " Indent a maximal # spaces in a continuous statement,\n";
|
|
(*_err) << " relative to the previous line.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --min-conditional-indent=# OR -m#\n";
|
|
(*_err) << " Indent a minimal # spaces in a continuous conditional\n";
|
|
(*_err) << " belonging to a conditional header.\n";
|
|
(*_err) << endl;
|
|
(*_err) << "Formatting options:\n";
|
|
(*_err) << "-------------------\n";
|
|
(*_err) << " --break-blocks OR -f\n";
|
|
(*_err) << " Insert empty lines around unrelated blocks, labels, classes, ...\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --break-blocks=all OR -F\n";
|
|
(*_err) << " Like --break-blocks, except also insert empty lines \n";
|
|
(*_err) << " around closing headers (e.g. 'else', 'catch', ...).\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --break-elseifs OR -e\n";
|
|
(*_err) << " Break 'else if()' statements into two different lines.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --pad=oper OR -p\n";
|
|
(*_err) << " Insert space paddings around operators.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --pad=paren OR -P\n";
|
|
(*_err) << " Insert space padding around parenthesis on both the outside\n";
|
|
(*_err) << " and the inside.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --pad=paren-out OR -d\n";
|
|
(*_err) << " Insert space padding around parenthesis on the outside only.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --pad=paren-in OR -D\n";
|
|
(*_err) << " Insert space padding around parenthesis on the inside only.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --unpad=paren OR -U\n";
|
|
(*_err) << " Remove unnecessary space padding around parenthesis. This\n";
|
|
(*_err) << " can be used in combination with the 'pad' options above.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --one-line=keep-statements OR -o\n";
|
|
(*_err) << " Don't break lines containing multiple statements into\n";
|
|
(*_err) << " multiple single-statement lines.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --one-line=keep-blocks OR -O\n";
|
|
(*_err) << " Don't break blocks residing completely on one line.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --convert-tabs OR -V\n";
|
|
(*_err) << " Convert tabs to spaces.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --fill-empty-lines OR -E\n";
|
|
(*_err) << " Fill empty lines with the white space of their\n";
|
|
(*_err) << " previous lines.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --mode=c OR -c\n";
|
|
(*_err) << " Indent a C, C++ or C# source file (this is the default).\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --mode=java OR -j\n";
|
|
(*_err) << " Indent a Java(TM) source file.\n";
|
|
(*_err) << endl;
|
|
(*_err) << "Other options:\n";
|
|
(*_err) << "--------------\n";
|
|
(*_err) << " --suffix=####\n";
|
|
(*_err) << " Append the suffix #### instead of '.orig' to original filename.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --suffix=none OR -n\n";
|
|
(*_err) << " Do not retain a backup of the original file.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --options=####\n";
|
|
(*_err) << " Specify an options file #### to read and use.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --options=none\n";
|
|
(*_err) << " Disable the default options file.\n";
|
|
(*_err) << " Only the command-line parameters will be used.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --preserve-date OR -Z\n";
|
|
(*_err) << " The date and time modified will not be changed in the formatted file.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --errors-to-stdout OR -X\n";
|
|
(*_err) << " Print errors and help information to standard-output rather than\n";
|
|
(*_err) << " to standard-error.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --version OR -v\n";
|
|
(*_err) << " Print version number.\n";
|
|
(*_err) << endl;
|
|
(*_err) << " --help OR -h OR -?\n";
|
|
(*_err) << " Print this help message.\n";
|
|
(*_err) << endl;
|
|
(*_err) << "Default options file:\n";
|
|
(*_err) << "---------------------\n";
|
|
(*_err) << " Artistic Style looks for a default options file in the\n";
|
|
(*_err) << " following order:\n";
|
|
(*_err) << " 1. The contents of the ARTISTIC_STYLE_OPTIONS environment\n";
|
|
(*_err) << " variable if it exists.\n";
|
|
(*_err) << " 2. The file called .astylerc in the directory pointed to by the\n";
|
|
(*_err) << " HOME environment variable ( i.e. $HOME/.astylerc ).\n";
|
|
(*_err) << " 3. The file called astylerc in the directory pointed to by the\n";
|
|
(*_err) << " USERPROFILE environment variable ( i.e. %USERPROFILE%\\astylerc ).\n";
|
|
(*_err) << " If a default options file is found, the options in this file\n";
|
|
(*_err) << " will be parsed BEFORE the command-line options.\n";
|
|
(*_err) << " Long options within the default option file may be written without\n";
|
|
(*_err) << " the preliminary '--'.\n";
|
|
(*_err) << endl;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
ASFormatter formatter;
|
|
vector<string> fileNameVector;
|
|
vector<string> optionsVector;
|
|
string optionsFileName = "";
|
|
string arg;
|
|
bool ok = true;
|
|
bool shouldPrintHelp = false;
|
|
bool shouldParseOptionsFile = true;
|
|
|
|
_modeManuallySet = false;
|
|
|
|
_msg << "\nArtistic Style " << _version << endl;
|
|
// manage flags
|
|
for (int i = 1; i < argc; i++)
|
|
{
|
|
arg = string(argv[i]);
|
|
|
|
if ( IS_OPTION(arg, "--options=none") )
|
|
{
|
|
shouldParseOptionsFile = false;
|
|
}
|
|
else if ( isParamOption(arg, "--options=") )
|
|
{
|
|
optionsFileName = GET_PARAM(arg, "--options=");
|
|
}
|
|
else if ( IS_OPTION(arg, "-h")
|
|
|| IS_OPTION(arg, "--help")
|
|
|| IS_OPTION(arg, "-?") )
|
|
{
|
|
shouldPrintHelp = true;
|
|
}
|
|
else if (arg[0] == '-')
|
|
{
|
|
optionsVector.push_back(arg);
|
|
}
|
|
else // file-name
|
|
{
|
|
fileNameVector.push_back(arg);
|
|
}
|
|
}
|
|
|
|
// parse options file
|
|
if (shouldParseOptionsFile)
|
|
{
|
|
if (optionsFileName.compare("") == 0)
|
|
{
|
|
char* env = getenv("ARTISTIC_STYLE_OPTIONS");
|
|
if (env != NULL)
|
|
optionsFileName = string(env);
|
|
}
|
|
if (optionsFileName.compare("") == 0)
|
|
{
|
|
char* env = getenv("HOME");
|
|
if (env != NULL)
|
|
optionsFileName = string(env) + string("/.astylerc");
|
|
}
|
|
if (optionsFileName.compare("") == 0)
|
|
{
|
|
char* env = getenv("USERPROFILE");
|
|
if (env != NULL)
|
|
optionsFileName = string(env) + string("/astylerc");
|
|
}
|
|
|
|
if (optionsFileName.compare("") != 0)
|
|
{
|
|
ifstream optionsIn(optionsFileName.c_str());
|
|
if (optionsIn)
|
|
{
|
|
_msg << "Using default options file " << optionsFileName << endl;
|
|
vector<string> fileOptionsVector;
|
|
importOptions(optionsIn, fileOptionsVector);
|
|
ok = parseOptions(formatter,
|
|
fileOptionsVector.begin(),
|
|
fileOptionsVector.end(),
|
|
string("Unknown option in default options file: "));
|
|
}
|
|
|
|
optionsIn.close();
|
|
if (!ok)
|
|
{
|
|
(*_err) << "For help on options, type 'astyle -h' " << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
// parse options from command line
|
|
|
|
ok = parseOptions(formatter,
|
|
optionsVector.begin(),
|
|
optionsVector.end(),
|
|
string("Unknown command line option: "));
|
|
if (!ok)
|
|
{
|
|
(*_err) << "For help on options, type 'astyle -h' \n" << endl;
|
|
exit(1);
|
|
}
|
|
|
|
if (shouldPrintHelp)
|
|
{
|
|
printHelp();
|
|
exit(0);
|
|
}
|
|
|
|
// if no files have been given, use cin for input and cout for output
|
|
// this is used to format text for text editors like TextWrangler
|
|
// do NOT display any console messages when this branch is used
|
|
if (fileNameVector.empty())
|
|
{
|
|
ASStreamIterator<istream> streamIterator(&cin);
|
|
|
|
formatter.init(&streamIterator);
|
|
|
|
while (formatter.hasMoreLines())
|
|
{
|
|
cout << formatter.nextLine();
|
|
if (formatter.hasMoreLines())
|
|
cout << streamIterator.outputEOL;
|
|
}
|
|
cout.flush();
|
|
}
|
|
else
|
|
{
|
|
// indent the given files
|
|
cout << _msg.str().c_str();
|
|
clock_t startTime = clock();
|
|
for (size_t i = 0; i < fileNameVector.size(); i++)
|
|
{
|
|
string originalFileName = fileNameVector[i];
|
|
string inFileName = originalFileName + _suffix;
|
|
|
|
remove(inFileName.c_str()); // remove the old .orig if present
|
|
|
|
// check if the file is present before rename
|
|
ifstream inCheck(originalFileName.c_str());
|
|
if (!inCheck)
|
|
error("Could not open input file", originalFileName.c_str());
|
|
inCheck.close();
|
|
|
|
if (rename(originalFileName.c_str(), inFileName.c_str()) < 0)
|
|
error("Could not rename ", string(originalFileName + " to " + inFileName).c_str());
|
|
|
|
ifstream in(inFileName.c_str(), ios::binary);
|
|
if (!in)
|
|
error("Could not open input file", inFileName.c_str());
|
|
|
|
ofstream out(originalFileName.c_str(), ios::binary);
|
|
if (!out)
|
|
error("Could not open output file", originalFileName.c_str());
|
|
|
|
// Unless a specific language mode has been, set the language mode
|
|
// according to the file's suffix.
|
|
if (!_modeManuallySet)
|
|
{
|
|
if (stringEndsWith(originalFileName, string(".java")))
|
|
formatter.setJavaStyle();
|
|
else if (stringEndsWith(originalFileName, string(".cs")))
|
|
formatter.setSharpStyle();
|
|
else
|
|
formatter.setCStyle();
|
|
}
|
|
// display file formatting message and save the filename
|
|
cout << "formatting " << originalFileName.c_str() << endl;
|
|
size_t fname = originalFileName.find_last_of("/\\");
|
|
if (fname == string::npos)
|
|
fname = 0;
|
|
else
|
|
fname +=1;
|
|
formatter.fileName = originalFileName.substr(fname);
|
|
|
|
ASStreamIterator<istream> streamIterator(&in);
|
|
formatter.init(&streamIterator);
|
|
|
|
while (formatter.hasMoreLines())
|
|
{
|
|
out << formatter.nextLine();
|
|
// the last line does not get an eol
|
|
if (formatter.hasMoreLines())
|
|
out << streamIterator.outputEOL;
|
|
}
|
|
out.flush();
|
|
out.close();
|
|
in.close();
|
|
|
|
// change date modified to original file date
|
|
if (_preserveDate)
|
|
preserveFileDate(inFileName.c_str(), originalFileName.c_str());
|
|
|
|
if (_purgeOrigIn)
|
|
remove(inFileName.c_str());
|
|
}
|
|
// all files formatted
|
|
clock_t stopTime = clock();
|
|
float secs = (float) (stopTime - startTime) / CLOCKS_PER_SEC;
|
|
// show tenths of a second if time is less than 20 seconds
|
|
cout.precision(2);
|
|
if (secs >= 100 || (secs >= 10 && secs < 20))
|
|
cout.precision(3);
|
|
cout << "total time " << secs << " seconds" << endl;
|
|
cout.precision(0);
|
|
cout << endl;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
// ************************* end of console functions *****************************************
|