📄 astyle_main.cpp
字号:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 <algorithm>#include <iostream>#include <fstream>#include <sstream>#include <cstdlib>#include <ctime>// includes for recursive getFileNames() function#ifdef _WIN32#include <windows.h>#else#include <dirent.h>#include <errno.h>#include <sys/stat.h>#ifdef __VMS#include <unixlib.h>#include <rms.h>#include <ssdef.h>#include <stsdef.h>#include <lib$routines.h>#include <starlet.h>#endif /* __VMS */#endif#ifdef ASTYLE_JNI#include <jni.h>// ASTYLE_LIB must be defined for ASTYLE_JNI#ifndef ASTYLE_LIB#define ASTYLE_LIB#endif// Java variablesJNIEnv* g_env;jobject g_obj;jmethodID g_mid;#endif#ifndef ASTYLE_LIB // for console build only#if defined(_MSC_VER) || defined(__DMC__)#include <sys/utime.h>#include <sys/stat.h>#else#include <utime.h>#include <sys/stat.h>#endif // end compiler checks#endif // end ASTYLE_LIB// for G++ implementation of string.compare:#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#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)))// astyle declarationsvoid error(const char *why, const char* what);void getFileNames(const string &directory, const string &wildcard, vector<string> &filename);void importOptions(istream &in, vector<string> &optionsVector);void isOptionError(const string &arg, const string &errorInfo);bool isParamOption(const string &arg, const char *option);bool isParamOption(const string &arg, const char *option1, const char *option2);bool parseOption(astyle::ASFormatter &formatter, const string &arg, const string &errorInfo);template<typename ITER>bool parseOptions(astyle::ASFormatter &formatter, const ITER &optionsBegin, const ITER &optionsEnd, const string &errorInfo);// astyle console declarationsbool formatFile(const string &fileName, astyle::ASFormatter &formatter);string getCurrentDirectory(const string &fileName);bool isPathExclued(const string &subPath);void preserveFileDate(const char *oldFileName, const char *newFileName);void printHelp();void standardizePath(string &path, bool removeBeginningSeparator=false);bool stringEndsWith(const string &str, const string &suffix);int wildcmp(const char *wild, const char *data);// astyle ASTYLE_LIB declarationstypedef void (STDCALL *fpError)(int, char*); // pointer to callback error handlertypedef char* (STDCALL *fpAlloc)(unsigned long); // pointer to callback memory allocationextern "C" EXPORT char* STDCALL AStyleMain(const char*, const char*, fpError, fpAlloc);extern "C" EXPORT const char* STDCALL AStyleGetVersion (void);// astyle ASTYLE_JNI declarations#ifdef ASTYLE_JNIvoid STDCALL javaErrorHandler(int errorNumber, char* errorMessage);char* STDCALL javaMemoryAlloc(unsigned long memoryNeeded);// the following function names are constructed from method names in the calling java programextern "C" EXPORT jstring STDCALL Java_AStyleInterface_GetVersion(JNIEnv* env, jclass);extern "C" EXPORT jstring STDCALL Java_AStyleInterface_AStyleMain (JNIEnv* env, jobject obj, jstring textInJava, jstring optionsJava);#endifusing namespace astyle;const char* _version = "1.22";#ifdef _WIN32char g_fileSeparator = '\\'; // file separatorbool g_isCaseSensitive = false;#elsechar g_fileSeparator = '/'; // file separatorbool g_isCaseSensitive = true;#endif#ifdef ASTYLE_LIB// GUI variablesstringstream *_err = NULL;#else// console variablesostream *_err = &cerr;bool g_isRecursive = false;bool g_hasWildcard = false;bool g_noBackup = false;bool g_preserveDate = false;bool g_isVerbose = false;bool g_isQuiet = false;bool g_optionsFileRequired = false;string g_origSuffix = ".orig";vector<string> g_excludeVector; // exclude from wildcard hitsvector<bool> g_excludeHitsVector; // exclude flags for eror reportingsize_t g_mainDirectoryLength; // main directory name can be excluded for displays// stringstream g_msg; // info messages are not printed until a file is readint _CRT_glob = 0; // turn off MinGW automatic file globbing#ifdef __VMSstring g_tempSuffix = "_tmp";#elsestring g_tempSuffix = ".tmp";#endif /* __VMS */#endifbool g_modeManuallySet = false;// typename will be istringstream for GUI and istream otherwisetemplate<typename T>class ASStreamIterator : public ASSourceIterator{ public: // function declarations ASStreamIterator(T *in); virtual ~ASStreamIterator(); string nextLine(); string peekNextLine(); void peekReset(); void saveLastInputLine(); // inline functions bool compareToInputBuffer(const string &nextLine) const { return nextLine == prevBuffer; } const char* getOutputEOL() const { return outputEOL; } bool hasMoreLines() const { return !inStream->eof(); } private: T * inStream; // pointer to the input stream string buffer; // current input line string prevBuffer; // previous input line int eolWindows; // number of Windows line endings (CRLF) int eolLinux; // number of Linux line endings (LF) int eolMacOld; // number of old Mac line endings (CR) char outputEOL[4]; // output end of line char int peekStart; // starting position for peekNextLine()};template<typename T>ASStreamIterator<T>::ASStreamIterator(T *in){ inStream = in; buffer.reserve(200); eolWindows = eolLinux = eolMacOld = 0; peekStart = 0;}template<typename T>ASStreamIterator<T>::~ASStreamIterator(){}// save the last input line after input has reached EOFtemplate<typename T>void ASStreamIterator<T>::saveLastInputLine(){ assert(inStream->eof()); prevBuffer = buffer;}/** * 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(){ // verify that the current position is correct assert (peekStart == 0); // save the previous record for output comparison prevBuffer = buffer; // read the next record buffer.clear(); char ch; inStream->get(ch); while (!inStream->eof() && ch != '\n' && ch != '\r') { buffer.append(1, ch); inStream->get(ch); } if (inStream->eof()) { return buffer; } int peekCh = inStream->peek(); // find input end-of-line characters if (!inStream->eof()) { if (ch == '\r') // CR+LF is windows otherwise Mac OS 9 { if (peekCh == '\n') { inStream->get(); eolWindows++; } else eolMacOld++; } else // LF is Linux, allow for improbable LF/CR { if (peekCh == '\r') { inStream->get(); eolWindows++; } else eolLinux++; } } else { inStream->clear(); } // set output end of line characters 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;}// save the current position and get the next line// this can be called for multiple reads// when finished peeking you MUST call peekReset()template<typename T>string ASStreamIterator<T>::peekNextLine(){ assert (hasMoreLines()); string nextLine; char ch; if (peekStart == 0) peekStart = inStream->tellg(); // read the next record inStream->get(ch); while (!inStream->eof() && ch != '\n' && ch != '\r') { nextLine.append(1, ch); inStream->get(ch); } if (inStream->eof()) { return nextLine; } int peekCh = inStream->peek(); // remove end-of-line characters if (!inStream->eof()) { if (peekCh == '\n' || peekCh == '\r') inStream->get(); } return nextLine;}// reset current position and EOF for peekNextLine()template<typename T>void ASStreamIterator<T>::peekReset(){ assert(peekStart != 0); inStream->clear(); inStream->seekg(peekStart); peekStart = 0;}/** * parse the options vector * ITER can be either a fileOptionsVector (options file) or an optionsVector (command line) * * @return true if no errors, false if errors */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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -