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