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
93namespace 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
102template<typename T>
103class ASStreamIterator : public ASSourceIterator
104{
105public:
106 bool checkForEmptyLine;
107
108public: // 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
119private:
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
131public: // 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
144class ASEncoding
145{
146private:
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
157public:
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//----------------------------------------------------------------------------
172class ASConsole;
173
174class ASOptions
175{
176public:
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
186private:
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
212class ASConsole
213{
214private: // 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
259public: // 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
322private: // 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 printVerboseHeader() 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
363class ASLibrary
364{
365public:
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
373private:
374 static char* STDCALL tempMemoryAllocation(unsigned long memoryNeeded);
375
376private:
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
391void STDCALL javaErrorHandler(int errorNumber, const char* errorMessage);
392char* STDCALL javaMemoryAlloc(unsigned long memoryNeeded);
393// the following function names are constructed from method names in the calling java program
394extern "C" EXPORT
395jstring STDCALL Java_AStyleInterface_AStyleGetVersion(JNIEnv* env, jclass);
396extern "C" EXPORT
397jstring 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
408extern "C" EXPORT
409char16_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
420extern "C" EXPORT char* STDCALL AStyleMain(const char* pSourceIn,
421 const char* pOptions,
422 fpError fpErrorHandler,
423 fpAlloc fpMemoryAlloc);
424extern "C" EXPORT const char* STDCALL AStyleGetVersion(void);
425#endif // ASTYLE_LIB
426
427//-----------------------------------------------------------------------------
428
429#endif // closes ASTYLE_MAIN_H
430