| 1 | // astyle_main.h |
| 2 | // Copyright (c) 2018 by Jim Pattee <jimp03@email.com>. |
| 3 | // This code is licensed under the MIT License. |
| 4 | // License.md describes the conditions under which this software may be distributed. |
| 5 | |
| 6 | #ifndef ASTYLE_MAIN_H |
| 7 | #define ASTYLE_MAIN_H |
| 8 | |
| 9 | //---------------------------------------------------------------------------- |
| 10 | // headers |
| 11 | //---------------------------------------------------------------------------- |
| 12 | |
| 13 | #include "astyle.h" |
| 14 | |
| 15 | #include <ctime> |
| 16 | #include <sstream> |
| 17 | |
| 18 | #if defined(__BORLANDC__) && __BORLANDC__ < 0x0650 |
| 19 | // Embarcadero needs this for the following utime.h |
| 20 | // otherwise "struct utimbuf" gets an error on time_t |
| 21 | // 0x0650 for C++Builder XE3 |
| 22 | using std::time_t; |
| 23 | #endif |
| 24 | |
| 25 | #if defined(_MSC_VER) |
| 26 | #include <sys/stat.h> |
| 27 | #include <sys/utime.h> |
| 28 | #else |
| 29 | #include <sys/stat.h> |
| 30 | #include <utime.h> |
| 31 | #endif // end compiler checks |
| 32 | |
| 33 | #ifdef ASTYLE_JNI |
| 34 | #include <jni.h> |
| 35 | #ifndef ASTYLE_LIB // ASTYLE_LIB must be defined for ASTYLE_JNI |
| 36 | #define ASTYLE_LIB |
| 37 | #endif |
| 38 | #endif // ASTYLE_JNI |
| 39 | |
| 40 | #ifndef ASTYLE_LIB |
| 41 | // for console build only |
| 42 | #include "ASLocalizer.h" |
| 43 | #define _(a) localizer.settext(a) |
| 44 | #endif // ASTYLE_LIB |
| 45 | |
| 46 | //----------------------------------------------------------------------------- |
| 47 | // declarations |
| 48 | //----------------------------------------------------------------------------- |
| 49 | |
| 50 | // for getenv and localtime |
| 51 | #if defined(_MSC_VER) |
| 52 | #pragma warning(disable: 4996) // secure version deprecation warnings |
| 53 | #endif |
| 54 | |
| 55 | #ifdef __clang__ |
| 56 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" // getenv, localtime |
| 57 | #pragma clang diagnostic ignored "-Wmissing-braces" |
| 58 | #endif |
| 59 | |
| 60 | #ifdef ASTYLE_LIB |
| 61 | // define STDCALL and EXPORT for Windows |
| 62 | // MINGW defines STDCALL in Windows.h (actually windef.h) |
| 63 | // EXPORT has no value if ASTYLE_NO_EXPORT is defined |
| 64 | #ifdef _WIN32 |
| 65 | #ifndef STDCALL |
| 66 | #define STDCALL __stdcall |
| 67 | #endif |
| 68 | // define this to prevent compiler warning and error messages |
| 69 | #ifdef ASTYLE_NO_EXPORT |
| 70 | #define EXPORT |
| 71 | #else |
| 72 | #define EXPORT __declspec(dllexport) |
| 73 | #endif |
| 74 | // define STDCALL and EXPORT for non-Windows |
| 75 | // visibility attribute allows "-fvisibility=hidden" compiler option |
| 76 | #else |
| 77 | #define STDCALL |
| 78 | #if __GNUC__ >= 4 |
| 79 | #define EXPORT __attribute__ ((visibility ("default"))) |
| 80 | #else |
| 81 | #define EXPORT |
| 82 | #endif |
| 83 | #endif // #ifdef _WIN32 |
| 84 | // define pointers to callback error handler and memory allocation |
| 85 | typedef void (STDCALL* fpError)(int errorNumber, const char* errorMessage); |
| 86 | typedef char* (STDCALL* fpAlloc)(unsigned long memoryNeeded); |
| 87 | #endif // #ifdef ASTYLE_LIB |
| 88 | |
| 89 | //---------------------------------------------------------------------------- |
| 90 | // astyle namespace |
| 91 | //---------------------------------------------------------------------------- |
| 92 | |
| 93 | namespace astyle { |
| 94 | // |
| 95 | //---------------------------------------------------------------------------- |
| 96 | // ASStreamIterator class |
| 97 | // typename will be stringstream for AStyle |
| 98 | // it could be istream for plug-ins |
| 99 | // ASSourceIterator is an inherited abstract class defined in astyle.h |
| 100 | //---------------------------------------------------------------------------- |
| 101 | |
| 102 | template<typename T> |
| 103 | class ASStreamIterator : public ASSourceIterator |
| 104 | { |
| 105 | public: |
| 106 | bool checkForEmptyLine; |
| 107 | |
| 108 | public: // function declarations |
| 109 | explicit ASStreamIterator(T* in); |
| 110 | ~ASStreamIterator() override; |
| 111 | bool getLineEndChange(int lineEndFormat) const; |
| 112 | int getStreamLength() const override; |
| 113 | string nextLine(bool emptyLineWasDeleted) override; |
| 114 | string peekNextLine() override; |
| 115 | void peekReset() override; |
| 116 | void saveLastInputLine(); |
| 117 | streamoff tellg() override; |
| 118 | |
| 119 | private: |
| 120 | T* inStream; // pointer to the input stream |
| 121 | string buffer; // current input line |
| 122 | string prevBuffer; // previous input line |
| 123 | string outputEOL; // next output end of line char |
| 124 | int eolWindows; // number of Windows line endings, CRLF |
| 125 | int eolLinux; // number of Linux line endings, LF |
| 126 | int eolMacOld; // number of old Mac line endings. CR |
| 127 | streamoff streamLength; // length of the input file stream |
| 128 | streamoff peekStart; // starting position for peekNextLine |
| 129 | bool prevLineDeleted; // the previous input line was deleted |
| 130 | |
| 131 | public: // inline functions |
| 132 | bool compareToInputBuffer(const string& nextLine_) const |
| 133 | { return (nextLine_ == prevBuffer); } |
| 134 | const string& getOutputEOL() const { return outputEOL; } |
| 135 | streamoff getPeekStart() const override { return peekStart; } |
| 136 | bool hasMoreLines() const override { return !inStream->eof(); } |
| 137 | }; |
| 138 | |
| 139 | //---------------------------------------------------------------------------- |
| 140 | // ASEncoding class for utf8/16 conversions |
| 141 | // used by both console and library builds |
| 142 | //---------------------------------------------------------------------------- |
| 143 | |
| 144 | class ASEncoding |
| 145 | { |
| 146 | private: |
| 147 | using utf16 = char16_t; // 16 bits unsigned |
| 148 | using utf8 = unsigned char; // 8 bits |
| 149 | using ubyte = unsigned char; // 8 bits |
| 150 | enum { SURROGATE_LEAD_FIRST = 0xD800 }; |
| 151 | enum { SURROGATE_LEAD_LAST = 0xDBFF }; |
| 152 | enum { SURROGATE_TRAIL_FIRST = 0xDC00 }; |
| 153 | enum { SURROGATE_TRAIL_LAST = 0xDFFF }; |
| 154 | enum { SURROGATE_FIRST_VALUE = 0x10000 }; |
| 155 | enum eState { eStart, eSecondOf4Bytes, ePenultimate, eFinal }; |
| 156 | |
| 157 | public: |
| 158 | bool getBigEndian() const; |
| 159 | int swap16bit(int value) const; |
| 160 | size_t utf16len(const utf16* utf16In) const; |
| 161 | size_t utf8LengthFromUtf16(const char* utf16In, size_t inLen, bool isBigEndian) const; |
| 162 | size_t utf8ToUtf16(char* utf8In, size_t inLen, bool isBigEndian, char* utf16Out) const; |
| 163 | size_t utf16LengthFromUtf8(const char* utf8In, size_t len) const; |
| 164 | size_t utf16ToUtf8(char* utf16In, size_t inLen, bool isBigEndian, |
| 165 | bool firstBlock, char* utf8Out) const; |
| 166 | }; |
| 167 | |
| 168 | //---------------------------------------------------------------------------- |
| 169 | // ASOptions class for options processing |
| 170 | // used by both console and library builds |
| 171 | //---------------------------------------------------------------------------- |
| 172 | class ASConsole; |
| 173 | |
| 174 | class ASOptions |
| 175 | { |
| 176 | public: |
| 177 | #ifdef ASTYLE_LIB |
| 178 | ASOptions(ASFormatter& formatterArg); |
| 179 | #else |
| 180 | ASOptions(ASFormatter& formatterArg, ASConsole& consoleArg); |
| 181 | #endif |
| 182 | string getOptionErrors() const; |
| 183 | void importOptions(stringstream& in, vector<string>& optionsVector); |
| 184 | bool parseOptions(vector<string>& optionsVector, const string& errorInfo); |
| 185 | |
| 186 | private: |
| 187 | // variables |
| 188 | ASFormatter& formatter; |
| 189 | stringstream optionErrors; // option error messages |
| 190 | #ifndef ASTYLE_LIB |
| 191 | ASConsole& console; // DO NOT USE for ASTYLE_LIB |
| 192 | #endif |
| 193 | |
| 194 | // functions |
| 195 | string getParam(const string& arg, const char* op); |
| 196 | string getParam(const string& arg, const char* op1, const char* op2); |
| 197 | bool isOption(const string& arg, const char* op); |
| 198 | bool isOption(const string& arg, const char* op1, const char* op2); |
| 199 | void isOptionError(const string& arg, const string& errorInfo); |
| 200 | bool isParamOption(const string& arg, const char* option); |
| 201 | bool isParamOption(const string& arg, const char* option1, const char* option2); |
| 202 | void parseOption(const string& arg, const string& errorInfo); |
| 203 | bool parseOptionContinued(const string& arg, const string& errorInfo); |
| 204 | }; |
| 205 | |
| 206 | #ifndef ASTYLE_LIB |
| 207 | |
| 208 | //---------------------------------------------------------------------------- |
| 209 | // ASConsole class for console build |
| 210 | //---------------------------------------------------------------------------- |
| 211 | |
| 212 | class ASConsole |
| 213 | { |
| 214 | private: // variables |
| 215 | ASFormatter& formatter; // reference to the ASFormatter object |
| 216 | ASEncoding encode; // file encoding conversion |
| 217 | ASLocalizer localizer; // language translation |
| 218 | ostream* errorStream; // direct error messages to cerr or cout |
| 219 | // command line options |
| 220 | bool isRecursive; // recursive option |
| 221 | bool isDryRun; // dry-run option |
| 222 | bool noBackup; // suffix=none option |
| 223 | bool preserveDate; // preserve-date option |
| 224 | bool isVerbose; // verbose option |
| 225 | bool isQuiet; // quiet option |
| 226 | bool isFormattedOnly; // formatted lines only option |
| 227 | bool ignoreExcludeErrors; // don't abort on unmatched excludes |
| 228 | bool ignoreExcludeErrorsDisplay; // don't display unmatched excludes |
| 229 | bool useAscii; // ascii option |
| 230 | // other variables |
| 231 | bool bypassBrowserOpen; // don't open the browser on html options |
| 232 | bool hasWildcard; // file name includes a wildcard |
| 233 | size_t mainDirectoryLength; // directory length to be excluded in displays |
| 234 | bool filesAreIdentical; // input and output files are identical |
| 235 | int filesFormatted; // number of files formatted |
| 236 | int filesUnchanged; // number of files unchanged |
| 237 | bool lineEndsMixed; // output has mixed line ends |
| 238 | int linesOut; // number of output lines |
| 239 | |
| 240 | string outputEOL; // current line end |
| 241 | string prevEOL; // previous line end |
| 242 | string astyleExePath; // absolute executable path and name from argv[0] |
| 243 | string optionFileName; // file path and name of the options file |
| 244 | string origSuffix; // suffix= option |
| 245 | string projectOptionFileName; // file path and name of the project options file |
| 246 | string stdPathIn; // path to input from stdin= |
| 247 | string stdPathOut; // path to output from stdout= |
| 248 | string targetDirectory; // path to the directory being processed |
| 249 | string targetFilename; // file name being processed |
| 250 | |
| 251 | vector<string> excludeVector; // exclude from wildcard hits |
| 252 | vector<bool> excludeHitsVector; // exclude flags for error reporting |
| 253 | vector<string> fileNameVector; // file paths and names from the command line |
| 254 | vector<string> optionsVector; // options from the command line |
| 255 | vector<string> projectOptionsVector;// project options from the project options file |
| 256 | vector<string> fileOptionsVector; // options from the options file |
| 257 | vector<string> fileName; // files to be processed including path |
| 258 | |
| 259 | public: // functions |
| 260 | explicit ASConsole(ASFormatter& formatterArg); |
| 261 | ASConsole(const ASConsole&) = delete; |
| 262 | ASConsole& operator=(ASConsole const&) = delete; |
| 263 | void convertLineEnds(ostringstream& out, int lineEnd); |
| 264 | FileEncoding detectEncoding(const char* data, size_t dataSize) const; |
| 265 | void error() const; |
| 266 | void error(const char* why, const char* what) const; |
| 267 | void formatCinToCout(); |
| 268 | vector<string> getArgvOptions(int argc, char** argv); |
| 269 | bool fileExists(const char* file) const; |
| 270 | bool fileNameVectorIsEmpty() const; |
| 271 | ostream* getErrorStream() const; |
| 272 | bool getFilesAreIdentical() const; |
| 273 | int getFilesFormatted() const; |
| 274 | bool getIgnoreExcludeErrors() const; |
| 275 | bool getIgnoreExcludeErrorsDisplay() const; |
| 276 | bool getIsDryRun() const; |
| 277 | bool getIsFormattedOnly() const; |
| 278 | bool getIsQuiet() const; |
| 279 | bool getIsRecursive() const; |
| 280 | bool getIsVerbose() const; |
| 281 | bool getLineEndsMixed() const; |
| 282 | bool getNoBackup() const; |
| 283 | bool getPreserveDate() const; |
| 284 | string getLanguageID() const; |
| 285 | string getNumberFormat(int num, size_t lcid = 0) const; |
| 286 | string getNumberFormat(int num, const char* groupingArg, const char* separator) const; |
| 287 | string getOptionFileName() const; |
| 288 | string getOrigSuffix() const; |
| 289 | string getProjectOptionFileName() const; |
| 290 | string getStdPathIn() const; |
| 291 | string getStdPathOut() const; |
| 292 | void getTargetFilenames(string& targetFilename_, vector<string>& targetFilenameVector) const; |
| 293 | void processFiles(); |
| 294 | void processOptions(const vector<string>& argvOptions); |
| 295 | void setBypassBrowserOpen(bool state); |
| 296 | void setErrorStream(ostream* errStreamPtr); |
| 297 | void setIgnoreExcludeErrors(bool state); |
| 298 | void setIgnoreExcludeErrorsAndDisplay(bool state); |
| 299 | void setIsDryRun(bool state); |
| 300 | void setIsFormattedOnly(bool state); |
| 301 | void setIsQuiet(bool state); |
| 302 | void setIsRecursive(bool state); |
| 303 | void setIsVerbose(bool state); |
| 304 | void setNoBackup(bool state); |
| 305 | void setOptionFileName(const string& name); |
| 306 | void setOrigSuffix(const string& suffix); |
| 307 | void setPreserveDate(bool state); |
| 308 | void setProjectOptionFileName(const string& optfilepath); |
| 309 | void setStdPathIn(const string& path); |
| 310 | void setStdPathOut(const string& path); |
| 311 | void standardizePath(string& path, bool removeBeginningSeparator = false) const; |
| 312 | bool stringEndsWith(const string& str, const string& suffix) const; |
| 313 | void updateExcludeVector(const string& suffixParam); |
| 314 | vector<string> getExcludeVector() const; |
| 315 | vector<bool> getExcludeHitsVector() const; |
| 316 | vector<string> getFileNameVector() const; |
| 317 | vector<string> getOptionsVector() const; |
| 318 | vector<string> getProjectOptionsVector() const; |
| 319 | vector<string> getFileOptionsVector() const; |
| 320 | vector<string> getFileName() const; |
| 321 | |
| 322 | private: // functions |
| 323 | void correctMixedLineEnds(ostringstream& out); |
| 324 | void formatFile(const string& fileName_); |
| 325 | string getParentDirectory(const string& absPath) const; |
| 326 | string findProjectOptionFilePath(const string& fileName_) const; |
| 327 | string getCurrentDirectory(const string& fileName_) const; |
| 328 | void getFileNames(const string& directory, const vector<string>& wildcards); |
| 329 | void getFilePaths(const string& filePath); |
| 330 | string getFullPathName(const string& relativePath) const; |
| 331 | string getHtmlInstallPrefix() const; |
| 332 | string getParam(const string& arg, const char* op); |
| 333 | bool isHomeOrInvalidAbsPath(const string& absPath) const; |
| 334 | void initializeOutputEOL(LineEndFormat lineEndFormat); |
| 335 | bool isOption(const string& arg, const char* op); |
| 336 | bool isOption(const string& arg, const char* a, const char* b); |
| 337 | bool isParamOption(const string& arg, const char* option); |
| 338 | bool isPathExclued(const string& subPath); |
| 339 | void launchDefaultBrowser(const char* filePathIn = nullptr) const; |
| 340 | void printHelp() const; |
| 341 | void printMsg(const char* msg, const string& data) const; |
| 342 | void printSeparatingLine() const; |
| 343 | void () const; |
| 344 | void printVerboseStats(clock_t startTime) const; |
| 345 | FileEncoding readFile(const string& fileName_, stringstream& in) const; |
| 346 | void removeFile(const char* fileName_, const char* errMsg) const; |
| 347 | void renameFile(const char* oldFileName, const char* newFileName, const char* errMsg) const; |
| 348 | void setOutputEOL(LineEndFormat lineEndFormat, const string& currentEOL); |
| 349 | void sleep(int seconds) const; |
| 350 | int waitForRemove(const char* newFileName) const; |
| 351 | int wildcmp(const char* wild, const char* data) const; |
| 352 | void writeFile(const string& fileName_, FileEncoding encoding, ostringstream& out) const; |
| 353 | #ifdef _WIN32 |
| 354 | void displayLastError(); |
| 355 | #endif |
| 356 | }; |
| 357 | #else // ASTYLE_LIB |
| 358 | |
| 359 | //---------------------------------------------------------------------------- |
| 360 | // ASLibrary class for library build |
| 361 | //---------------------------------------------------------------------------- |
| 362 | |
| 363 | class ASLibrary |
| 364 | { |
| 365 | public: |
| 366 | ASLibrary() = default; |
| 367 | virtual ~ASLibrary() = default; |
| 368 | // virtual functions are mocked in testing |
| 369 | char16_t* formatUtf16(const char16_t*, const char16_t*, fpError, fpAlloc) const; |
| 370 | virtual char16_t* convertUtf8ToUtf16(const char* utf8In, fpAlloc fpMemoryAlloc) const; |
| 371 | virtual char* convertUtf16ToUtf8(const char16_t* utf16In) const; |
| 372 | |
| 373 | private: |
| 374 | static char* STDCALL tempMemoryAllocation(unsigned long memoryNeeded); |
| 375 | |
| 376 | private: |
| 377 | ASEncoding encode; // file encoding conversion |
| 378 | }; |
| 379 | |
| 380 | #endif // ASTYLE_LIB |
| 381 | |
| 382 | //---------------------------------------------------------------------------- |
| 383 | |
| 384 | } // end of namespace astyle |
| 385 | |
| 386 | //---------------------------------------------------------------------------- |
| 387 | // declarations for java native interface (JNI) build |
| 388 | // they are called externally and are NOT part of the namespace |
| 389 | //---------------------------------------------------------------------------- |
| 390 | #ifdef ASTYLE_JNI |
| 391 | void STDCALL javaErrorHandler(int errorNumber, const char* errorMessage); |
| 392 | char* STDCALL javaMemoryAlloc(unsigned long memoryNeeded); |
| 393 | // the following function names are constructed from method names in the calling java program |
| 394 | extern "C" EXPORT |
| 395 | jstring STDCALL Java_AStyleInterface_AStyleGetVersion(JNIEnv* env, jclass); |
| 396 | extern "C" EXPORT |
| 397 | jstring STDCALL Java_AStyleInterface_AStyleMain(JNIEnv* env, |
| 398 | jobject obj, |
| 399 | jstring textInJava, |
| 400 | jstring optionsJava); |
| 401 | #endif // ASTYLE_JNI |
| 402 | |
| 403 | //---------------------------------------------------------------------------- |
| 404 | // declarations for UTF-16 interface |
| 405 | // they are called externally and are NOT part of the namespace |
| 406 | //---------------------------------------------------------------------------- |
| 407 | #ifdef ASTYLE_LIB |
| 408 | extern "C" EXPORT |
| 409 | char16_t* STDCALL AStyleMainUtf16(const char16_t* pSourceIn, |
| 410 | const char16_t* pOptions, |
| 411 | fpError fpErrorHandler, |
| 412 | fpAlloc fpMemoryAlloc); |
| 413 | #endif // ASTYLE_LIB |
| 414 | |
| 415 | //----------------------------------------------------------------------------- |
| 416 | // declarations for standard DLL interface |
| 417 | // they are called externally and are NOT part of the namespace |
| 418 | //----------------------------------------------------------------------------- |
| 419 | #ifdef ASTYLE_LIB |
| 420 | extern "C" EXPORT char* STDCALL AStyleMain(const char* pSourceIn, |
| 421 | const char* pOptions, |
| 422 | fpError fpErrorHandler, |
| 423 | fpAlloc fpMemoryAlloc); |
| 424 | extern "C" EXPORT const char* STDCALL AStyleGetVersion(void); |
| 425 | #endif // ASTYLE_LIB |
| 426 | |
| 427 | //----------------------------------------------------------------------------- |
| 428 | |
| 429 | #endif // closes ASTYLE_MAIN_H |
| 430 | |