1 // ASResource.cpp
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 //-----------------------------------------------------------------------------
7 // headers
8 //-----------------------------------------------------------------------------
9 
10 #include "astyle/astyle.h"
11 #include <algorithm>
12 
13 //-----------------------------------------------------------------------------
14 // astyle namespace
15 //-----------------------------------------------------------------------------
16 
17 namespace astyle {
18 //
19 const string ASResource::_AS_EXCEPT = string("__except");
20 const string ASResource::_AS_FINALLY = string("__finally");
21 const string ASResource::_AS_TRY = string("__try");
22 const string ASResource::AS_ADD = string("add");
23 const string ASResource::AS_AUTO = string("auto");
24 const string ASResource::AS_AUTORELEASEPOOL = string("autoreleasepool");
25 const string ASResource::AS_CASE = string("case");
26 const string ASResource::AS_CATCH = string("catch");
27 const string ASResource::AS_CLASS = string("class");
28 const string ASResource::AS_CONST = string("const");
29 const string ASResource::AS_CONST_CAST = string("const_cast");
30 const string ASResource::AS_DEFAULT = string("default");
31 const string ASResource::AS_DELEGATE = string("delegate");
32 const string ASResource::AS_DELETE = string("delete");
33 const string ASResource::AS_DO = string("do");
34 const string ASResource::AS_DYNAMIC_CAST = string("dynamic_cast");
35 const string ASResource::AS_ELSE = string("else");
36 const string ASResource::AS_END = string("end");
37 const string ASResource::AS_ENUM = string("enum");
38 const string ASResource::AS_EXTERN = string("extern");
39 const string ASResource::AS_FINAL = string("final");
40 const string ASResource::AS_FINALLY = string("finally");
41 const string ASResource::AS_FIXED = string("fixed");
42 const string ASResource::AS_FOR = string("for");
43 const string ASResource::AS_FOREACH = string("foreach");
44 const string ASResource::AS_FOREVER = string("forever");
45 const string ASResource::AS_GET = string("get");
46 const string ASResource::AS_IF = string("if");
47 const string ASResource::AS_INTERFACE = string("interface");
48 const string ASResource::AS_INTERRUPT = string("interrupt");
49 const string ASResource::AS_LET = string("let");
50 const string ASResource::AS_LOCK = string("lock");
51 const string ASResource::AS_MODULE = string("module");	// CORBA IDL module definition
52 const string ASResource::AS_NAMESPACE = string("namespace");
53 const string ASResource::AS_NEW = string("new");
54 const string ASResource::AS_NOEXCEPT = string("noexcept");
55 const string ASResource::AS_NS_DURING = string("NS_DURING");
56 const string ASResource::AS_NS_HANDLER = string("NS_HANDLER");
57 const string ASResource::AS_OPERATOR = string("operator");
58 const string ASResource::AS_OVERRIDE = string("override");
59 const string ASResource::AS_PRIVATE = string("private");
60 const string ASResource::AS_PROTECTED = string("protected");
61 const string ASResource::AS_PUBLIC = string("public");
62 const string ASResource::AS_QFOREACH = string("Q_FOREACH");
63 const string ASResource::AS_QFOREVER = string("Q_FOREVER");
64 const string ASResource::AS_REINTERPRET_CAST = string("reinterpret_cast");
65 const string ASResource::AS_REMOVE = string("remove");
66 const string ASResource::AS_SEALED = string("sealed");
67 const string ASResource::AS_SELECTOR = string("selector");
68 const string ASResource::AS_SET = string("set");
69 const string ASResource::AS_STATIC = string("static");
70 const string ASResource::AS_STATIC_CAST = string("static_cast");
71 const string ASResource::AS_STRUCT = string("struct");
72 const string ASResource::AS_SWITCH = string("switch");
73 const string ASResource::AS_SYNCHRONIZED = string("synchronized");
74 const string ASResource::AS_TEMPLATE = string("template");
75 const string ASResource::AS_THROW = string("throw");
76 const string ASResource::AS_THROWS = string("throws");
77 const string ASResource::AS_TRY = string("try");
78 const string ASResource::AS_UNCHECKED = string("unchecked");
79 const string ASResource::AS_UNION = string("union");
80 const string ASResource::AS_UNSAFE = string("unsafe");
81 const string ASResource::AS_USING = string("using");
82 const string ASResource::AS_VOLATILE = string("volatile");
83 const string ASResource::AS_WHERE = string("where");
84 const string ASResource::AS_WHILE = string("while");
85 
86 const string ASResource::AS_ASM = string("asm");
87 const string ASResource::AS__ASM__ = string("__asm__");
88 const string ASResource::AS_MS_ASM = string("_asm");
89 const string ASResource::AS_MS__ASM = string("__asm");
90 
91 const string ASResource::AS_BAR_DEFINE = string("#define");
92 const string ASResource::AS_BAR_INCLUDE = string("#include");
93 const string ASResource::AS_BAR_IF = string("#if");
94 const string ASResource::AS_BAR_EL = string("#el");
95 const string ASResource::AS_BAR_ENDIF = string("#endif");
96 
97 const string ASResource::AS_OPEN_BRACE = string("{");
98 const string ASResource::AS_CLOSE_BRACE = string("}");
99 const string ASResource::AS_OPEN_LINE_COMMENT = string("//");
100 const string ASResource::AS_OPEN_COMMENT = string("/*");
101 const string ASResource::AS_CLOSE_COMMENT = string("*/");
102 
103 const string ASResource::AS_ASSIGN = string("=");
104 const string ASResource::AS_PLUS_ASSIGN = string("+=");
105 const string ASResource::AS_MINUS_ASSIGN = string("-=");
106 const string ASResource::AS_MULT_ASSIGN = string("*=");
107 const string ASResource::AS_DIV_ASSIGN = string("/=");
108 const string ASResource::AS_MOD_ASSIGN = string("%=");
109 const string ASResource::AS_OR_ASSIGN = string("|=");
110 const string ASResource::AS_AND_ASSIGN = string("&=");
111 const string ASResource::AS_XOR_ASSIGN = string("^=");
112 const string ASResource::AS_GR_GR_ASSIGN = string(">>=");
113 const string ASResource::AS_LS_LS_ASSIGN = string("<<=");
114 const string ASResource::AS_GR_GR_GR_ASSIGN = string(">>>=");
115 const string ASResource::AS_LS_LS_LS_ASSIGN = string("<<<=");
116 const string ASResource::AS_GCC_MIN_ASSIGN = string("<?");
117 const string ASResource::AS_GCC_MAX_ASSIGN = string(">?");
118 
119 const string ASResource::AS_RETURN = string("return");
120 const string ASResource::AS_CIN = string("cin");
121 const string ASResource::AS_COUT = string("cout");
122 const string ASResource::AS_CERR = string("cerr");
123 
124 const string ASResource::AS_EQUAL = string("==");
125 const string ASResource::AS_PLUS_PLUS = string("++");
126 const string ASResource::AS_MINUS_MINUS = string("--");
127 const string ASResource::AS_NOT_EQUAL = string("!=");
128 const string ASResource::AS_GR_EQUAL = string(">=");
129 const string ASResource::AS_GR_GR = string(">>");
130 const string ASResource::AS_GR_GR_GR = string(">>>");
131 const string ASResource::AS_LS_EQUAL = string("<=");
132 const string ASResource::AS_LS_LS = string("<<");
133 const string ASResource::AS_LS_LS_LS = string("<<<");
134 const string ASResource::AS_QUESTION_QUESTION = string("??");
135 const string ASResource::AS_LAMBDA = string("=>");            // C# lambda expression arrow
136 const string ASResource::AS_ARROW = string("->");
137 const string ASResource::AS_AND = string("&&");
138 const string ASResource::AS_OR = string("||");
139 const string ASResource::AS_SCOPE_RESOLUTION = string("::");
140 
141 const string ASResource::AS_PLUS = string("+");
142 const string ASResource::AS_MINUS = string("-");
143 const string ASResource::AS_MULT = string("*");
144 const string ASResource::AS_DIV = string("/");
145 const string ASResource::AS_MOD = string("%");
146 const string ASResource::AS_GR = string(">");
147 const string ASResource::AS_LS = string("<");
148 const string ASResource::AS_NOT = string("!");
149 const string ASResource::AS_BIT_OR = string("|");
150 const string ASResource::AS_BIT_AND = string("&");
151 const string ASResource::AS_BIT_NOT = string("~");
152 const string ASResource::AS_BIT_XOR = string("^");
153 const string ASResource::AS_QUESTION = string("?");
154 const string ASResource::AS_COLON = string(":");
155 const string ASResource::AS_COMMA = string(",");
156 const string ASResource::AS_SEMICOLON = string(";");
157 
158 /**
159  * Sort comparison function.
160  * Compares the length of the value of pointers in the vectors.
161  * The LONGEST strings will be first in the vector.
162  *
163  * @param a and b, the string pointers to be compared.
164  */
sortOnLength(const string * a,const string * b)165 bool sortOnLength(const string* a, const string* b)
166 {
167 	return (*a).length() > (*b).length();
168 }
169 
170 /**
171  * Sort comparison function.
172  * Compares the value of pointers in the vectors.
173  *
174  * @param a and b, the string pointers to be compared.
175  */
sortOnName(const string * a,const string * b)176 bool sortOnName(const string* a, const string* b)
177 {
178 	return *a < *b;
179 }
180 
181 /**
182  * Build the vector of assignment operators.
183  * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
184  *
185  * @param assignmentOperators   a reference to the vector to be built.
186  */
buildAssignmentOperators(vector<const string * > * assignmentOperators)187 void ASResource::buildAssignmentOperators(vector<const string*>* assignmentOperators)
188 {
189 	const size_t elements = 15;
190 	assignmentOperators->reserve(elements);
191 
192 	assignmentOperators->emplace_back(&AS_ASSIGN);
193 	assignmentOperators->emplace_back(&AS_PLUS_ASSIGN);
194 	assignmentOperators->emplace_back(&AS_MINUS_ASSIGN);
195 	assignmentOperators->emplace_back(&AS_MULT_ASSIGN);
196 	assignmentOperators->emplace_back(&AS_DIV_ASSIGN);
197 	assignmentOperators->emplace_back(&AS_MOD_ASSIGN);
198 	assignmentOperators->emplace_back(&AS_OR_ASSIGN);
199 	assignmentOperators->emplace_back(&AS_AND_ASSIGN);
200 	assignmentOperators->emplace_back(&AS_XOR_ASSIGN);
201 
202 	// Java
203 	assignmentOperators->emplace_back(&AS_GR_GR_GR_ASSIGN);
204 	assignmentOperators->emplace_back(&AS_GR_GR_ASSIGN);
205 	assignmentOperators->emplace_back(&AS_LS_LS_ASSIGN);
206 
207 	// Unknown
208 	assignmentOperators->emplace_back(&AS_LS_LS_LS_ASSIGN);
209 
210 	assert(assignmentOperators->size() < elements);
211 	sort(assignmentOperators->begin(), assignmentOperators->end(), sortOnLength);
212 }
213 
214 /**
215  * Build the vector of C++ cast operators.
216  * Used by ONLY ASFormatter.cpp
217  *
218  * @param castOperators     a reference to the vector to be built.
219  */
buildCastOperators(vector<const string * > * castOperators)220 void ASResource::buildCastOperators(vector<const string*>* castOperators)
221 {
222 	const size_t elements = 5;
223 	castOperators->reserve(elements);
224 
225 	castOperators->emplace_back(&AS_CONST_CAST);
226 	castOperators->emplace_back(&AS_DYNAMIC_CAST);
227 	castOperators->emplace_back(&AS_REINTERPRET_CAST);
228 	castOperators->emplace_back(&AS_STATIC_CAST);
229 
230 	assert(castOperators->size() < elements);
231 	sort(castOperators->begin(), castOperators->end(), sortOnName);
232 }
233 
234 /**
235  * Build the vector of header words.
236  * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
237  *
238  * @param headers       a reference to the vector to be built.
239  */
buildHeaders(vector<const string * > * headers,int fileType,bool beautifier)240 void ASResource::buildHeaders(vector<const string*>* headers, int fileType, bool beautifier)
241 {
242 	const size_t elements = 25;
243 	headers->reserve(elements);
244 
245 	headers->emplace_back(&AS_IF);
246 	headers->emplace_back(&AS_ELSE);
247 	headers->emplace_back(&AS_FOR);
248 	headers->emplace_back(&AS_WHILE);
249 	headers->emplace_back(&AS_DO);
250 	headers->emplace_back(&AS_SWITCH);
251 	headers->emplace_back(&AS_CASE);
252 	headers->emplace_back(&AS_DEFAULT);
253 	headers->emplace_back(&AS_TRY);
254 	headers->emplace_back(&AS_CATCH);
255 	headers->emplace_back(&AS_QFOREACH);		// QT
256 	headers->emplace_back(&AS_QFOREVER);		// QT
257 	headers->emplace_back(&AS_FOREACH);		// QT & C#
258 	headers->emplace_back(&AS_FOREVER);		// Qt & Boost
259 
260 	if (fileType == C_TYPE)
261 	{
262 		headers->emplace_back(&_AS_TRY);		// __try
263 		headers->emplace_back(&_AS_FINALLY);	// __finally
264 		headers->emplace_back(&_AS_EXCEPT);	// __except
265 	}
266 	if (fileType == JAVA_TYPE)
267 	{
268 		headers->emplace_back(&AS_FINALLY);
269 		headers->emplace_back(&AS_SYNCHRONIZED);
270 	}
271 
272 	if (fileType == SHARP_TYPE)
273 	{
274 		headers->emplace_back(&AS_FINALLY);
275 		headers->emplace_back(&AS_LOCK);
276 		headers->emplace_back(&AS_FIXED);
277 		headers->emplace_back(&AS_GET);
278 		headers->emplace_back(&AS_SET);
279 		headers->emplace_back(&AS_ADD);
280 		headers->emplace_back(&AS_REMOVE);
281 		headers->emplace_back(&AS_USING);
282 	}
283 
284 	if (beautifier)
285 	{
286 		if (fileType == C_TYPE)
287 		{
288 			headers->emplace_back(&AS_TEMPLATE);
289 		}
290 
291 		if (fileType == JAVA_TYPE)
292 		{
293 			headers->emplace_back(&AS_STATIC);         // for static constructor
294 		}
295 	}
296 
297 	assert(headers->size() < elements);
298 	sort(headers->begin(), headers->end(), sortOnName);
299 }
300 
301 /**
302  * Build the vector of indentable headers.
303  * Used by ONLY ASBeautifier.cpp
304  *
305  * @param indentableHeaders     a reference to the vector to be built.
306  */
buildIndentableHeaders(vector<const string * > * indentableHeaders)307 void ASResource::buildIndentableHeaders(vector<const string*>* indentableHeaders)
308 {
309 	indentableHeaders->emplace_back(&AS_RETURN);
310 
311 //	sort(indentableHeaders->begin(), indentableHeaders->end(), sortOnName);
312 }
313 
314 /**
315 * Build the vector of indentable macros pairs.
316 * Initialized by ASFormatter, used by ONLY ASEnhancer.cpp
317 *
318 * @param indentableMacros       a reference to the vector to be built.
319 */
buildIndentableMacros(vector<const pair<const string,const string> * > * indentableMacros)320 void ASResource::buildIndentableMacros(vector<const pair<const string, const string>* >* indentableMacros)
321 {
322 	const size_t elements = 10;
323 	indentableMacros->reserve(elements);
324 
325 	// the pairs must be retained in memory because of pair pointers
326 	using macro_pair = pair<const string, const string>;
327 	static const macro_pair macros[] =
328 	{
329 		// wxWidgets
330 		macro_pair("BEGIN_EVENT_TABLE",   "END_EVENT_TABLE"),
331 		macro_pair("wxBEGIN_EVENT_TABLE", "wxEND_EVENT_TABLE"),
332 		// MFC
333 		macro_pair("BEGIN_DISPATCH_MAP",  "END_DISPATCH_MAP"),
334 		macro_pair("BEGIN_EVENT_MAP",     "END_EVENT_MAP"),
335 		macro_pair("BEGIN_MESSAGE_MAP",   "END_MESSAGE_MAP"),
336 		macro_pair("BEGIN_PROPPAGEIDS",   "END_PROPPAGEIDS"),
337 	};
338 
339 	for (const macro_pair& macro : macros)
340 		indentableMacros->emplace_back(&macro);
341 
342 	assert(indentableMacros->size() < elements);
343 }
344 
345 /**
346  * Build the vector of non-assignment operators.
347  * Used by ONLY ASBeautifier.cpp
348  *
349  * @param nonAssignmentOperators       a reference to the vector to be built.
350  */
buildNonAssignmentOperators(vector<const string * > * nonAssignmentOperators)351 void ASResource::buildNonAssignmentOperators(vector<const string*>* nonAssignmentOperators)
352 {
353 	const size_t elements = 15;
354 	nonAssignmentOperators->reserve(elements);
355 
356 	nonAssignmentOperators->emplace_back(&AS_EQUAL);
357 	nonAssignmentOperators->emplace_back(&AS_PLUS_PLUS);
358 	nonAssignmentOperators->emplace_back(&AS_MINUS_MINUS);
359 	nonAssignmentOperators->emplace_back(&AS_NOT_EQUAL);
360 	nonAssignmentOperators->emplace_back(&AS_GR_EQUAL);
361 	nonAssignmentOperators->emplace_back(&AS_GR_GR_GR);
362 	nonAssignmentOperators->emplace_back(&AS_GR_GR);
363 	nonAssignmentOperators->emplace_back(&AS_LS_EQUAL);
364 	nonAssignmentOperators->emplace_back(&AS_LS_LS_LS);
365 	nonAssignmentOperators->emplace_back(&AS_LS_LS);
366 	nonAssignmentOperators->emplace_back(&AS_ARROW);
367 	nonAssignmentOperators->emplace_back(&AS_AND);
368 	nonAssignmentOperators->emplace_back(&AS_OR);
369 	nonAssignmentOperators->emplace_back(&AS_LAMBDA);
370 
371 	assert(nonAssignmentOperators->size() < elements);
372 	sort(nonAssignmentOperators->begin(), nonAssignmentOperators->end(), sortOnLength);
373 }
374 
375 /**
376  * Build the vector of header non-paren headers.
377  * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
378  * NOTE: Non-paren headers should also be included in the headers vector.
379  *
380  * @param nonParenHeaders       a reference to the vector to be built.
381  */
buildNonParenHeaders(vector<const string * > * nonParenHeaders,int fileType,bool beautifier)382 void ASResource::buildNonParenHeaders(vector<const string*>* nonParenHeaders, int fileType, bool beautifier)
383 {
384 	const size_t elements = 20;
385 	nonParenHeaders->reserve(elements);
386 
387 	nonParenHeaders->emplace_back(&AS_ELSE);
388 	nonParenHeaders->emplace_back(&AS_DO);
389 	nonParenHeaders->emplace_back(&AS_TRY);
390 	nonParenHeaders->emplace_back(&AS_CATCH);		// can be paren or non-paren
391 	nonParenHeaders->emplace_back(&AS_CASE);		// can be paren or non-paren
392 	nonParenHeaders->emplace_back(&AS_DEFAULT);
393 	nonParenHeaders->emplace_back(&AS_QFOREVER);	// QT
394 	nonParenHeaders->emplace_back(&AS_FOREVER);	// Boost
395 
396 	if (fileType == C_TYPE)
397 	{
398 		nonParenHeaders->emplace_back(&_AS_TRY);		// __try
399 		nonParenHeaders->emplace_back(&_AS_FINALLY);	// __finally
400 	}
401 	if (fileType == JAVA_TYPE)
402 	{
403 		nonParenHeaders->emplace_back(&AS_FINALLY);
404 	}
405 
406 	if (fileType == SHARP_TYPE)
407 	{
408 		nonParenHeaders->emplace_back(&AS_FINALLY);
409 		nonParenHeaders->emplace_back(&AS_GET);
410 		nonParenHeaders->emplace_back(&AS_SET);
411 		nonParenHeaders->emplace_back(&AS_ADD);
412 		nonParenHeaders->emplace_back(&AS_REMOVE);
413 	}
414 
415 	if (beautifier)
416 	{
417 		if (fileType == C_TYPE)
418 		{
419 			nonParenHeaders->emplace_back(&AS_TEMPLATE);
420 		}
421 		if (fileType == JAVA_TYPE)
422 		{
423 			nonParenHeaders->emplace_back(&AS_STATIC);
424 		}
425 	}
426 
427 	assert(nonParenHeaders->size() < elements);
428 	sort(nonParenHeaders->begin(), nonParenHeaders->end(), sortOnName);
429 }
430 
431 /**
432  * Build the vector of operators.
433  * Used by ONLY ASFormatter.cpp
434  *
435  * @param operators             a reference to the vector to be built.
436  */
buildOperators(vector<const string * > * operators,int fileType)437 void ASResource::buildOperators(vector<const string*>* operators, int fileType)
438 {
439 	const size_t elements = 50;
440 	operators->reserve(elements);
441 
442 	operators->emplace_back(&AS_PLUS_ASSIGN);
443 	operators->emplace_back(&AS_MINUS_ASSIGN);
444 	operators->emplace_back(&AS_MULT_ASSIGN);
445 	operators->emplace_back(&AS_DIV_ASSIGN);
446 	operators->emplace_back(&AS_MOD_ASSIGN);
447 	operators->emplace_back(&AS_OR_ASSIGN);
448 	operators->emplace_back(&AS_AND_ASSIGN);
449 	operators->emplace_back(&AS_XOR_ASSIGN);
450 	operators->emplace_back(&AS_EQUAL);
451 	operators->emplace_back(&AS_PLUS_PLUS);
452 	operators->emplace_back(&AS_MINUS_MINUS);
453 	operators->emplace_back(&AS_NOT_EQUAL);
454 	operators->emplace_back(&AS_GR_EQUAL);
455 	operators->emplace_back(&AS_GR_GR_GR_ASSIGN);
456 	operators->emplace_back(&AS_GR_GR_ASSIGN);
457 	operators->emplace_back(&AS_GR_GR_GR);
458 	operators->emplace_back(&AS_GR_GR);
459 	operators->emplace_back(&AS_LS_EQUAL);
460 	operators->emplace_back(&AS_LS_LS_LS_ASSIGN);
461 	operators->emplace_back(&AS_LS_LS_ASSIGN);
462 	operators->emplace_back(&AS_LS_LS_LS);
463 	operators->emplace_back(&AS_LS_LS);
464 	operators->emplace_back(&AS_QUESTION_QUESTION);
465 	operators->emplace_back(&AS_LAMBDA);
466 	operators->emplace_back(&AS_ARROW);
467 	operators->emplace_back(&AS_AND);
468 	operators->emplace_back(&AS_OR);
469 	operators->emplace_back(&AS_SCOPE_RESOLUTION);
470 	operators->emplace_back(&AS_PLUS);
471 	operators->emplace_back(&AS_MINUS);
472 	operators->emplace_back(&AS_MULT);
473 	operators->emplace_back(&AS_DIV);
474 	operators->emplace_back(&AS_MOD);
475 	operators->emplace_back(&AS_QUESTION);
476 	operators->emplace_back(&AS_COLON);
477 	operators->emplace_back(&AS_ASSIGN);
478 	operators->emplace_back(&AS_LS);
479 	operators->emplace_back(&AS_GR);
480 	operators->emplace_back(&AS_NOT);
481 	operators->emplace_back(&AS_BIT_OR);
482 	operators->emplace_back(&AS_BIT_AND);
483 	operators->emplace_back(&AS_BIT_NOT);
484 	operators->emplace_back(&AS_BIT_XOR);
485 	if (fileType == C_TYPE)
486 	{
487 		operators->emplace_back(&AS_GCC_MIN_ASSIGN);
488 		operators->emplace_back(&AS_GCC_MAX_ASSIGN);
489 	}
490 
491 	assert(operators->size() < elements);
492 	sort(operators->begin(), operators->end(), sortOnLength);
493 }
494 
495 /**
496  * Build the vector of pre-block statements.
497  * Used by ONLY ASBeautifier.cpp
498  * NOTE: Cannot be both a header and a preBlockStatement.
499  *
500  * @param preBlockStatements        a reference to the vector to be built.
501  */
buildPreBlockStatements(vector<const string * > * preBlockStatements,int fileType)502 void ASResource::buildPreBlockStatements(vector<const string*>* preBlockStatements, int fileType)
503 {
504 	const size_t elements = 10;
505 	preBlockStatements->reserve(elements);
506 
507 	preBlockStatements->emplace_back(&AS_CLASS);
508 	if (fileType == C_TYPE)
509 	{
510 		preBlockStatements->emplace_back(&AS_STRUCT);
511 		preBlockStatements->emplace_back(&AS_UNION);
512 		preBlockStatements->emplace_back(&AS_NAMESPACE);
513 		preBlockStatements->emplace_back(&AS_MODULE);     // for CORBA IDL
514 		preBlockStatements->emplace_back(&AS_INTERFACE);  // for CORBA IDL
515 	}
516 	if (fileType == JAVA_TYPE)
517 	{
518 		preBlockStatements->emplace_back(&AS_INTERFACE);
519 		preBlockStatements->emplace_back(&AS_THROWS);
520 	}
521 	if (fileType == SHARP_TYPE)
522 	{
523 		preBlockStatements->emplace_back(&AS_INTERFACE);
524 		preBlockStatements->emplace_back(&AS_NAMESPACE);
525 		preBlockStatements->emplace_back(&AS_WHERE);
526 		preBlockStatements->emplace_back(&AS_STRUCT);
527 	}
528 
529 	assert(preBlockStatements->size() < elements);
530 	sort(preBlockStatements->begin(), preBlockStatements->end(), sortOnName);
531 }
532 
533 /**
534  * Build the vector of pre-command headers.
535  * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
536  * NOTE: Cannot be both a header and a preCommandHeader.
537  *
538  * A preCommandHeader is in a function definition between
539  * the closing paren and the opening brace.
540  * e.g. in "void foo() const {}", "const" is a preCommandHeader.
541  */
buildPreCommandHeaders(vector<const string * > * preCommandHeaders,int fileType)542 void ASResource::buildPreCommandHeaders(vector<const string*>* preCommandHeaders, int fileType)
543 {
544 	const size_t elements = 10;
545 	preCommandHeaders->reserve(elements);
546 
547 	if (fileType == C_TYPE)
548 	{
549 		preCommandHeaders->emplace_back(&AS_CONST);
550 		preCommandHeaders->emplace_back(&AS_FINAL);
551 		preCommandHeaders->emplace_back(&AS_INTERRUPT);
552 		preCommandHeaders->emplace_back(&AS_NOEXCEPT);
553 		preCommandHeaders->emplace_back(&AS_OVERRIDE);
554 		preCommandHeaders->emplace_back(&AS_VOLATILE);
555 		preCommandHeaders->emplace_back(&AS_SEALED);			// Visual C only
556 		preCommandHeaders->emplace_back(&AS_AUTORELEASEPOOL);	// Obj-C only
557 	}
558 
559 	if (fileType == JAVA_TYPE)
560 	{
561 		preCommandHeaders->emplace_back(&AS_THROWS);
562 	}
563 
564 	if (fileType == SHARP_TYPE)
565 	{
566 		preCommandHeaders->emplace_back(&AS_WHERE);
567 	}
568 
569 	assert(preCommandHeaders->size() < elements);
570 	sort(preCommandHeaders->begin(), preCommandHeaders->end(), sortOnName);
571 }
572 
573 /**
574  * Build the vector of pre-definition headers.
575  * Used by ONLY ASFormatter.cpp
576  * NOTE: Do NOT add 'enum' here. It is an array type brace.
577  * NOTE: Do NOT add 'extern' here. Do not want an extra indent.
578  *
579  * @param preDefinitionHeaders      a reference to the vector to be built.
580  */
buildPreDefinitionHeaders(vector<const string * > * preDefinitionHeaders,int fileType)581 void ASResource::buildPreDefinitionHeaders(vector<const string*>* preDefinitionHeaders, int fileType)
582 {
583 	const size_t elements = 10;
584 	preDefinitionHeaders->reserve(elements);
585 
586 	preDefinitionHeaders->emplace_back(&AS_CLASS);
587 	if (fileType == C_TYPE)
588 	{
589 		preDefinitionHeaders->emplace_back(&AS_STRUCT);
590 		preDefinitionHeaders->emplace_back(&AS_UNION);
591 		preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
592 		preDefinitionHeaders->emplace_back(&AS_MODULE);     // for CORBA IDL
593 		preDefinitionHeaders->emplace_back(&AS_INTERFACE);  // for CORBA IDL
594 	}
595 	if (fileType == JAVA_TYPE)
596 	{
597 		preDefinitionHeaders->emplace_back(&AS_INTERFACE);
598 	}
599 	if (fileType == SHARP_TYPE)
600 	{
601 		preDefinitionHeaders->emplace_back(&AS_STRUCT);
602 		preDefinitionHeaders->emplace_back(&AS_INTERFACE);
603 		preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
604 	}
605 
606 	assert(preDefinitionHeaders->size() < elements);
607 	sort(preDefinitionHeaders->begin(), preDefinitionHeaders->end(), sortOnName);
608 }
609 
610 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
611  *                             ASBase Functions
612  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
613 
614 // check if a specific line position contains a header.
findHeader(const string & line,int i,const vector<const string * > * possibleHeaders) const615 const string* ASBase::findHeader(const string& line, int i,
616                                  const vector<const string*>* possibleHeaders) const
617 {
618 	assert(isCharPotentialHeader(line, i));
619 	// check the word
620 	size_t maxHeaders = possibleHeaders->size();
621 	for (size_t p = 0; p < maxHeaders; p++)
622 	{
623 		const string* header = (*possibleHeaders)[p];
624 		const size_t wordEnd = i + header->length();
625 		if (wordEnd > line.length())
626 			continue;
627 		int result = (line.compare(i, header->length(), *header));
628 		if (result > 0)
629 			continue;
630 		if (result < 0)
631 			break;
632 		// check that this is not part of a longer word
633 		if (wordEnd == line.length())
634 			return header;
635 		if (isLegalNameChar(line[wordEnd]))
636 			continue;
637 		const char peekChar = peekNextChar(line, wordEnd - 1);
638 		// is not a header if part of a definition
639 		if (peekChar == ',' || peekChar == ')')
640 			break;
641 		// the following accessor definitions are NOT headers
642 		// goto default; is NOT a header
643 		// default(int) keyword in C# is NOT a header
644 		if ((header == &AS_GET
645 		        || header == &AS_SET
646 		        || header == &AS_DEFAULT)
647 		        && (peekChar == ';' || peekChar == '(' || peekChar == '='))
648 			break;
649 		return header;
650 	}
651 	return nullptr;
652 }
653 
654 // check if a specific line position contains a keyword.
findKeyword(const string & line,int i,const string & keyword) const655 bool ASBase::findKeyword(const string& line, int i, const string& keyword) const
656 {
657 	assert(isCharPotentialHeader(line, i));
658 	// check the word
659 	const size_t keywordLength = keyword.length();
660 	const size_t wordEnd = i + keywordLength;
661 	if (wordEnd > line.length())
662 		return false;
663 	if (line.compare(i, keywordLength, keyword) != 0)
664 		return false;
665 	// check that this is not part of a longer word
666 	if (wordEnd == line.length())
667 		return true;
668 	if (isLegalNameChar(line[wordEnd]))
669 		return false;
670 	// is not a keyword if part of a definition
671 	const char peekChar = peekNextChar(line, (int) wordEnd - 1);
672 	if (peekChar == ',' || peekChar == ')')
673 		return false;
674 	return true;
675 }
676 
677 // check if a specific line position contains an operator.
findOperator(const string & line,int i,const vector<const string * > * possibleOperators) const678 const string* ASBase::findOperator(const string& line, int i,
679                                    const vector<const string*>* possibleOperators) const
680 {
681 	assert(isCharPotentialOperator(line[i]));
682 	// find the operator in the vector
683 	// the vector contains the LONGEST operators first
684 	// must loop thru the entire vector
685 	size_t maxOperators = possibleOperators->size();
686 	for (size_t p = 0; p < maxOperators; p++)
687 	{
688 		const size_t wordEnd = i + (*(*possibleOperators)[p]).length();
689 		if (wordEnd > line.length())
690 			continue;
691 		if (line.compare(i, (*(*possibleOperators)[p]).length(), *(*possibleOperators)[p]) == 0)
692 			return (*possibleOperators)[p];
693 	}
694 	return nullptr;
695 }
696 
697 // get the current word on a line
698 // index must point to the beginning of the word
getCurrentWord(const string & line,size_t index) const699 string ASBase::getCurrentWord(const string& line, size_t index) const
700 {
701 	assert(isCharPotentialHeader(line, index));
702 	size_t lineLength = line.length();
703 	size_t i;
704 	for (i = index; i < lineLength; i++)
705 	{
706 		if (!isLegalNameChar(line[i]))
707 			break;
708 	}
709 	return line.substr(index, i - index);
710 }
711 
712 // check if a specific character can be used in a legal variable/method/class name
isLegalNameChar(char ch) const713 bool ASBase::isLegalNameChar(char ch) const
714 {
715 	if (isWhiteSpace(ch))
716 		return false;
717 	if ((unsigned char) ch > 127)
718 		return false;
719 	return (isalnum((unsigned char) ch)
720 	        || ch == '.' || ch == '_'
721 	        || (isJavaStyle() && ch == '$')
722 	        || (isSharpStyle() && ch == '@'));  // may be used as a prefix
723 }
724 
725 // check if a specific character can be part of a header
isCharPotentialHeader(const string & line,size_t i) const726 bool ASBase::isCharPotentialHeader(const string& line, size_t i) const
727 {
728 	assert(!isWhiteSpace(line[i]));
729 	char prevCh = ' ';
730 	if (i > 0)
731 		prevCh = line[i - 1];
732 	if (i > 1 && line[i - 2] == '\\')
733 		prevCh = ' ';
734 	if (!isLegalNameChar(prevCh) && isLegalNameChar(line[i]))
735 		return true;
736 	return false;
737 }
738 
739 // check if a specific character can be part of an operator
isCharPotentialOperator(char ch) const740 bool ASBase::isCharPotentialOperator(char ch) const
741 {
742 	assert(!isWhiteSpace(ch));
743 	if ((unsigned) ch > 127)
744 		return false;
745 	return (ispunct((unsigned char) ch)
746 	        && ch != '{' && ch != '}'
747 	        && ch != '(' && ch != ')'
748 	        && ch != '[' && ch != ']'
749 	        && ch != ';' && ch != ','
750 	        && ch != '#' && ch != '\\'
751 	        && ch != '\'' && ch != '\"');
752 }
753 
754 // check if a specific character is a digit
755 // NOTE: Visual C isdigit() gives assert error if char > 256
isDigit(char ch) const756 bool ASBase::isDigit(char ch) const
757 {
758 	return (ch >= '0' && ch <= '9');
759 }
760 
761 // check if a specific character is a digit separator
isDigitSeparator(const string & line,int i) const762 bool ASBase::isDigitSeparator(const string& line, int i) const
763 {
764 	assert(line[i] == '\'');
765 	// casting to (unsigned char) eliminates negative characters
766 	// will get a "Debug Assertion Failed" if not cast
767 	bool foundDigitSeparator = i > 0
768 	                           && isxdigit((unsigned char) line[i - 1])
769 	                           && i < (int) line.length() - 1
770 	                           && isxdigit((unsigned char) line[i + 1]);
771 	return foundDigitSeparator;
772 }
773 
774 // peek at the next unread character.
peekNextChar(const string & line,int i) const775 char ASBase::peekNextChar(const string& line, int i) const
776 {
777 	char ch = ' ';
778 	size_t peekNum = line.find_first_not_of(" \t", i + 1);
779 	if (peekNum == string::npos)
780 		return ch;
781 	ch = line[peekNum];
782 	return ch;
783 }
784 
785 }   // end namespace astyle
786