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 | |