1 // ASResource.cpp
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 //-----------------------------------------------------------------------------
7 // headers
8 //-----------------------------------------------------------------------------
9 
10 #include "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 	static bool reserved = false;
191 	if (!reserved)
192 	{
193 		assignmentOperators->reserve(elements);
194 		reserved = true;
195 	}
196 
197 	assignmentOperators->emplace_back(&AS_ASSIGN);
198 	assignmentOperators->emplace_back(&AS_PLUS_ASSIGN);
199 	assignmentOperators->emplace_back(&AS_MINUS_ASSIGN);
200 	assignmentOperators->emplace_back(&AS_MULT_ASSIGN);
201 	assignmentOperators->emplace_back(&AS_DIV_ASSIGN);
202 	assignmentOperators->emplace_back(&AS_MOD_ASSIGN);
203 	assignmentOperators->emplace_back(&AS_OR_ASSIGN);
204 	assignmentOperators->emplace_back(&AS_AND_ASSIGN);
205 	assignmentOperators->emplace_back(&AS_XOR_ASSIGN);
206 
207 	// Java
208 	assignmentOperators->emplace_back(&AS_GR_GR_GR_ASSIGN);
209 	assignmentOperators->emplace_back(&AS_GR_GR_ASSIGN);
210 	assignmentOperators->emplace_back(&AS_LS_LS_ASSIGN);
211 
212 	// Unknown
213 	assignmentOperators->emplace_back(&AS_LS_LS_LS_ASSIGN);
214 
215 	assert(assignmentOperators->size() < elements);
216 	sort(assignmentOperators->begin(), assignmentOperators->end(), sortOnLength);
217 }
218 
219 /**
220  * Build the vector of C++ cast operators.
221  * Used by ONLY ASFormatter.cpp
222  *
223  * @param castOperators     a reference to the vector to be built.
224  */
buildCastOperators(vector<const string * > * castOperators)225 void ASResource::buildCastOperators(vector<const string*>* castOperators)
226 {
227 	const size_t elements = 5;
228 	static bool reserved = false;
229 	if (!reserved)
230 	{
231 		castOperators->reserve(elements);
232 		reserved = true;
233 	}
234 
235 	castOperators->emplace_back(&AS_CONST_CAST);
236 	castOperators->emplace_back(&AS_DYNAMIC_CAST);
237 	castOperators->emplace_back(&AS_REINTERPRET_CAST);
238 	castOperators->emplace_back(&AS_STATIC_CAST);
239 
240 	assert(castOperators->size() < elements);
241 	sort(castOperators->begin(), castOperators->end(), sortOnName);
242 }
243 
244 /**
245  * Build the vector of header words.
246  * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
247  *
248  * @param headers       a reference to the vector to be built.
249  */
buildHeaders(vector<const string * > * headers,int fileType,bool beautifier)250 void ASResource::buildHeaders(vector<const string*>* headers, int fileType, bool beautifier)
251 {
252 	const size_t elements = 25;
253 	static bool reserved = false;
254 	if (!reserved)
255 	{
256 		headers->reserve(elements);
257 		reserved = true;
258 	}
259 
260 	headers->emplace_back(&AS_IF);
261 	headers->emplace_back(&AS_ELSE);
262 	headers->emplace_back(&AS_FOR);
263 	headers->emplace_back(&AS_WHILE);
264 	headers->emplace_back(&AS_DO);
265 	headers->emplace_back(&AS_SWITCH);
266 	headers->emplace_back(&AS_CASE);
267 	headers->emplace_back(&AS_DEFAULT);
268 	headers->emplace_back(&AS_TRY);
269 	headers->emplace_back(&AS_CATCH);
270 	headers->emplace_back(&AS_QFOREACH);		// QT
271 	headers->emplace_back(&AS_QFOREVER);		// QT
272 	headers->emplace_back(&AS_FOREACH);		// QT & C#
273 	headers->emplace_back(&AS_FOREVER);		// Qt & Boost
274 
275 	if (fileType == C_TYPE)
276 	{
277 		headers->emplace_back(&_AS_TRY);		// __try
278 		headers->emplace_back(&_AS_FINALLY);	// __finally
279 		headers->emplace_back(&_AS_EXCEPT);	// __except
280 	}
281 	if (fileType == JAVA_TYPE)
282 	{
283 		headers->emplace_back(&AS_FINALLY);
284 		headers->emplace_back(&AS_SYNCHRONIZED);
285 	}
286 
287 	if (fileType == SHARP_TYPE)
288 	{
289 		headers->emplace_back(&AS_FINALLY);
290 		headers->emplace_back(&AS_LOCK);
291 		headers->emplace_back(&AS_FIXED);
292 		headers->emplace_back(&AS_GET);
293 		headers->emplace_back(&AS_SET);
294 		headers->emplace_back(&AS_ADD);
295 		headers->emplace_back(&AS_REMOVE);
296 		headers->emplace_back(&AS_USING);
297 	}
298 
299 	if (beautifier)
300 	{
301 		if (fileType == C_TYPE)
302 		{
303 			headers->emplace_back(&AS_TEMPLATE);
304 		}
305 
306 		if (fileType == JAVA_TYPE)
307 		{
308 			headers->emplace_back(&AS_STATIC);         // for static constructor
309 		}
310 	}
311 
312 	assert(headers->size() < elements);
313 	sort(headers->begin(), headers->end(), sortOnName);
314 }
315 
316 /**
317  * Build the vector of indentable headers.
318  * Used by ONLY ASBeautifier.cpp
319  *
320  * @param indentableHeaders     a reference to the vector to be built.
321  */
buildIndentableHeaders(vector<const string * > * indentableHeaders)322 void ASResource::buildIndentableHeaders(vector<const string*>* indentableHeaders)
323 {
324 	indentableHeaders->emplace_back(&AS_RETURN);
325 
326 //	sort(indentableHeaders->begin(), indentableHeaders->end(), sortOnName);
327 }
328 
329 /**
330 * Build the vector of indentable macros pairs.
331 * Initialized by ASFormatter, used by ONLY ASEnhancer.cpp
332 *
333 * @param indentableMacros       a reference to the vector to be built.
334 */
buildIndentableMacros(vector<const pair<const string,const string> * > * indentableMacros)335 void ASResource::buildIndentableMacros(vector<const pair<const string, const string>* >* indentableMacros)
336 {
337 	const size_t elements = 10;
338 	static bool reserved = false;
339 	if (!reserved)
340 	{
341 		indentableMacros->reserve(elements);
342 		reserved = true;
343 	}
344 
345 	// the pairs must be retained in memory because of pair pointers
346 	typedef pair<const string, const string> macro_pair;
347 	static const macro_pair macros[] =
348 	{
349 		// wxWidgets
350 		macro_pair("BEGIN_EVENT_TABLE",   "END_EVENT_TABLE"),
351 		macro_pair("wxBEGIN_EVENT_TABLE", "wxEND_EVENT_TABLE"),
352 		// MFC
353 		macro_pair("BEGIN_DISPATCH_MAP",  "END_DISPATCH_MAP"),
354 		macro_pair("BEGIN_EVENT_MAP",     "END_EVENT_MAP"),
355 		macro_pair("BEGIN_MESSAGE_MAP",   "END_MESSAGE_MAP"),
356 		macro_pair("BEGIN_PROPPAGEIDS",   "END_PROPPAGEIDS"),
357 	};
358 
359 	size_t entries = sizeof(macros) / sizeof(macros[0]);
360 	for (size_t i = 0; i < entries; i++)
361 		indentableMacros->emplace_back(&macros[i]);
362 
363 	assert(indentableMacros->size() < elements);
364 }
365 
366 /**
367  * Build the vector of non-assignment operators.
368  * Used by ONLY ASBeautifier.cpp
369  *
370  * @param nonAssignmentOperators       a reference to the vector to be built.
371  */
buildNonAssignmentOperators(vector<const string * > * nonAssignmentOperators)372 void ASResource::buildNonAssignmentOperators(vector<const string*>* nonAssignmentOperators)
373 {
374 	const size_t elements = 15;
375 	static bool reserved = false;
376 	if (!reserved)
377 	{
378 		nonAssignmentOperators->reserve(elements);
379 		reserved = true;
380 	}
381 
382 	nonAssignmentOperators->emplace_back(&AS_EQUAL);
383 	nonAssignmentOperators->emplace_back(&AS_PLUS_PLUS);
384 	nonAssignmentOperators->emplace_back(&AS_MINUS_MINUS);
385 	nonAssignmentOperators->emplace_back(&AS_NOT_EQUAL);
386 	nonAssignmentOperators->emplace_back(&AS_GR_EQUAL);
387 	nonAssignmentOperators->emplace_back(&AS_GR_GR_GR);
388 	nonAssignmentOperators->emplace_back(&AS_GR_GR);
389 	nonAssignmentOperators->emplace_back(&AS_LS_EQUAL);
390 	nonAssignmentOperators->emplace_back(&AS_LS_LS_LS);
391 	nonAssignmentOperators->emplace_back(&AS_LS_LS);
392 	nonAssignmentOperators->emplace_back(&AS_ARROW);
393 	nonAssignmentOperators->emplace_back(&AS_AND);
394 	nonAssignmentOperators->emplace_back(&AS_OR);
395 	nonAssignmentOperators->emplace_back(&AS_LAMBDA);
396 
397 	assert(nonAssignmentOperators->size() < elements);
398 	sort(nonAssignmentOperators->begin(), nonAssignmentOperators->end(), sortOnLength);
399 }
400 
401 /**
402  * Build the vector of header non-paren headers.
403  * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
404  * NOTE: Non-paren headers should also be included in the headers vector.
405  *
406  * @param nonParenHeaders       a reference to the vector to be built.
407  */
buildNonParenHeaders(vector<const string * > * nonParenHeaders,int fileType,bool beautifier)408 void ASResource::buildNonParenHeaders(vector<const string*>* nonParenHeaders, int fileType, bool beautifier)
409 {
410 	const size_t elements = 20;
411 	static bool reserved = false;
412 	if (!reserved)
413 	{
414 		nonParenHeaders->reserve(elements);
415 		reserved = true;
416 	}
417 
418 	nonParenHeaders->emplace_back(&AS_ELSE);
419 	nonParenHeaders->emplace_back(&AS_DO);
420 	nonParenHeaders->emplace_back(&AS_TRY);
421 	nonParenHeaders->emplace_back(&AS_CATCH);		// can be paren or non-paren
422 	nonParenHeaders->emplace_back(&AS_CASE);		// can be paren or non-paren
423 	nonParenHeaders->emplace_back(&AS_DEFAULT);
424 	nonParenHeaders->emplace_back(&AS_QFOREVER);	// QT
425 	nonParenHeaders->emplace_back(&AS_FOREVER);	// Boost
426 
427 	if (fileType == C_TYPE)
428 	{
429 		nonParenHeaders->emplace_back(&_AS_TRY);		// __try
430 		nonParenHeaders->emplace_back(&_AS_FINALLY);	// __finally
431 	}
432 	if (fileType == JAVA_TYPE)
433 	{
434 		nonParenHeaders->emplace_back(&AS_FINALLY);
435 	}
436 
437 	if (fileType == SHARP_TYPE)
438 	{
439 		nonParenHeaders->emplace_back(&AS_FINALLY);
440 		nonParenHeaders->emplace_back(&AS_GET);
441 		nonParenHeaders->emplace_back(&AS_SET);
442 		nonParenHeaders->emplace_back(&AS_ADD);
443 		nonParenHeaders->emplace_back(&AS_REMOVE);
444 	}
445 
446 	if (beautifier)
447 	{
448 		if (fileType == C_TYPE)
449 		{
450 			nonParenHeaders->emplace_back(&AS_TEMPLATE);
451 		}
452 		if (fileType == JAVA_TYPE)
453 		{
454 			nonParenHeaders->emplace_back(&AS_STATIC);
455 		}
456 	}
457 
458 	assert(nonParenHeaders->size() < elements);
459 	sort(nonParenHeaders->begin(), nonParenHeaders->end(), sortOnName);
460 }
461 
462 /**
463  * Build the vector of operators.
464  * Used by ONLY ASFormatter.cpp
465  *
466  * @param operators             a reference to the vector to be built.
467  */
buildOperators(vector<const string * > * operators,int fileType)468 void ASResource::buildOperators(vector<const string*>* operators, int fileType)
469 {
470 	const size_t elements = 50;
471 	static bool reserved = false;
472 	if (!reserved)
473 	{
474 		operators->reserve(elements);
475 		reserved = true;
476 	}
477 
478 
479 	operators->emplace_back(&AS_PLUS_ASSIGN);
480 	operators->emplace_back(&AS_MINUS_ASSIGN);
481 	operators->emplace_back(&AS_MULT_ASSIGN);
482 	operators->emplace_back(&AS_DIV_ASSIGN);
483 	operators->emplace_back(&AS_MOD_ASSIGN);
484 	operators->emplace_back(&AS_OR_ASSIGN);
485 	operators->emplace_back(&AS_AND_ASSIGN);
486 	operators->emplace_back(&AS_XOR_ASSIGN);
487 	operators->emplace_back(&AS_EQUAL);
488 	operators->emplace_back(&AS_PLUS_PLUS);
489 	operators->emplace_back(&AS_MINUS_MINUS);
490 	operators->emplace_back(&AS_NOT_EQUAL);
491 	operators->emplace_back(&AS_GR_EQUAL);
492 	operators->emplace_back(&AS_GR_GR_GR_ASSIGN);
493 	operators->emplace_back(&AS_GR_GR_ASSIGN);
494 	operators->emplace_back(&AS_GR_GR_GR);
495 	operators->emplace_back(&AS_GR_GR);
496 	operators->emplace_back(&AS_LS_EQUAL);
497 	operators->emplace_back(&AS_LS_LS_LS_ASSIGN);
498 	operators->emplace_back(&AS_LS_LS_ASSIGN);
499 	operators->emplace_back(&AS_LS_LS_LS);
500 	operators->emplace_back(&AS_LS_LS);
501 	operators->emplace_back(&AS_QUESTION_QUESTION);
502 	operators->emplace_back(&AS_LAMBDA);
503 	operators->emplace_back(&AS_ARROW);
504 	operators->emplace_back(&AS_AND);
505 	operators->emplace_back(&AS_OR);
506 	operators->emplace_back(&AS_SCOPE_RESOLUTION);
507 	operators->emplace_back(&AS_PLUS);
508 	operators->emplace_back(&AS_MINUS);
509 	operators->emplace_back(&AS_MULT);
510 	operators->emplace_back(&AS_DIV);
511 	operators->emplace_back(&AS_MOD);
512 	operators->emplace_back(&AS_QUESTION);
513 	operators->emplace_back(&AS_COLON);
514 	operators->emplace_back(&AS_ASSIGN);
515 	operators->emplace_back(&AS_LS);
516 	operators->emplace_back(&AS_GR);
517 	operators->emplace_back(&AS_NOT);
518 	operators->emplace_back(&AS_BIT_OR);
519 	operators->emplace_back(&AS_BIT_AND);
520 	operators->emplace_back(&AS_BIT_NOT);
521 	operators->emplace_back(&AS_BIT_XOR);
522 	if (fileType == C_TYPE)
523 	{
524 		operators->emplace_back(&AS_GCC_MIN_ASSIGN);
525 		operators->emplace_back(&AS_GCC_MAX_ASSIGN);
526 	}
527 
528 	assert(operators->size() < elements);
529 	sort(operators->begin(), operators->end(), sortOnLength);
530 }
531 
532 /**
533  * Build the vector of pre-block statements.
534  * Used by ONLY ASBeautifier.cpp
535  * NOTE: Cannot be both a header and a preBlockStatement.
536  *
537  * @param preBlockStatements        a reference to the vector to be built.
538  */
buildPreBlockStatements(vector<const string * > * preBlockStatements,int fileType)539 void ASResource::buildPreBlockStatements(vector<const string*>* preBlockStatements, int fileType)
540 {
541 	const size_t elements = 10;
542 	static bool reserved = false;
543 	if (!reserved)
544 	{
545 		preBlockStatements->reserve(elements);
546 		reserved = true;
547 	}
548 
549 	preBlockStatements->emplace_back(&AS_CLASS);
550 	if (fileType == C_TYPE)
551 	{
552 		preBlockStatements->emplace_back(&AS_STRUCT);
553 		preBlockStatements->emplace_back(&AS_UNION);
554 		preBlockStatements->emplace_back(&AS_NAMESPACE);
555 		preBlockStatements->emplace_back(&AS_MODULE);     // for CORBA IDL
556 		preBlockStatements->emplace_back(&AS_INTERFACE);  // for CORBA IDL
557 	}
558 	if (fileType == JAVA_TYPE)
559 	{
560 		preBlockStatements->emplace_back(&AS_INTERFACE);
561 		preBlockStatements->emplace_back(&AS_THROWS);
562 	}
563 	if (fileType == SHARP_TYPE)
564 	{
565 		preBlockStatements->emplace_back(&AS_INTERFACE);
566 		preBlockStatements->emplace_back(&AS_NAMESPACE);
567 		preBlockStatements->emplace_back(&AS_WHERE);
568 		preBlockStatements->emplace_back(&AS_STRUCT);
569 	}
570 
571 	assert(preBlockStatements->size() < elements);
572 	sort(preBlockStatements->begin(), preBlockStatements->end(), sortOnName);
573 }
574 
575 /**
576  * Build the vector of pre-command headers.
577  * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
578  * NOTE: Cannot be both a header and a preCommandHeader.
579  *
580  * A preCommandHeader is in a function definition between
581  * the closing paren and the opening brace.
582  * e.g. in "void foo() const {}", "const" is a preCommandHeader.
583  */
buildPreCommandHeaders(vector<const string * > * preCommandHeaders,int fileType)584 void ASResource::buildPreCommandHeaders(vector<const string*>* preCommandHeaders, int fileType)
585 {
586 	const size_t elements = 10;
587 	static bool reserved = false;
588 	if (!reserved)
589 	{
590 		preCommandHeaders->reserve(elements);
591 		reserved = true;
592 	}
593 
594 	if (fileType == C_TYPE)
595 	{
596 		preCommandHeaders->emplace_back(&AS_CONST);
597 		preCommandHeaders->emplace_back(&AS_FINAL);
598 		preCommandHeaders->emplace_back(&AS_INTERRUPT);
599 		preCommandHeaders->emplace_back(&AS_NOEXCEPT);
600 		preCommandHeaders->emplace_back(&AS_OVERRIDE);
601 		preCommandHeaders->emplace_back(&AS_VOLATILE);
602 		preCommandHeaders->emplace_back(&AS_SEALED);			// Visual C only
603 		preCommandHeaders->emplace_back(&AS_AUTORELEASEPOOL);	// Obj-C only
604 	}
605 
606 	if (fileType == JAVA_TYPE)
607 	{
608 		preCommandHeaders->emplace_back(&AS_THROWS);
609 	}
610 
611 	if (fileType == SHARP_TYPE)
612 	{
613 		preCommandHeaders->emplace_back(&AS_WHERE);
614 	}
615 
616 	assert(preCommandHeaders->size() < elements);
617 	sort(preCommandHeaders->begin(), preCommandHeaders->end(), sortOnName);
618 }
619 
620 /**
621  * Build the vector of pre-definition headers.
622  * Used by ONLY ASFormatter.cpp
623  * NOTE: Do NOT add 'enum' here. It is an array type brace.
624  * NOTE: Do NOT add 'extern' here. Do not want an extra indent.
625  *
626  * @param preDefinitionHeaders      a reference to the vector to be built.
627  */
buildPreDefinitionHeaders(vector<const string * > * preDefinitionHeaders,int fileType)628 void ASResource::buildPreDefinitionHeaders(vector<const string*>* preDefinitionHeaders, int fileType)
629 {
630 	const size_t elements = 10;
631 	static bool reserved = false;
632 	if (!reserved)
633 	{
634 		preDefinitionHeaders->reserve(elements);
635 		reserved = true;
636 	}
637 
638 	preDefinitionHeaders->emplace_back(&AS_CLASS);
639 	if (fileType == C_TYPE)
640 	{
641 		preDefinitionHeaders->emplace_back(&AS_STRUCT);
642 		preDefinitionHeaders->emplace_back(&AS_UNION);
643 		preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
644 		preDefinitionHeaders->emplace_back(&AS_MODULE);     // for CORBA IDL
645 		preDefinitionHeaders->emplace_back(&AS_INTERFACE);  // for CORBA IDL
646 	}
647 	if (fileType == JAVA_TYPE)
648 	{
649 		preDefinitionHeaders->emplace_back(&AS_INTERFACE);
650 	}
651 	if (fileType == SHARP_TYPE)
652 	{
653 		preDefinitionHeaders->emplace_back(&AS_STRUCT);
654 		preDefinitionHeaders->emplace_back(&AS_INTERFACE);
655 		preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
656 	}
657 
658 	assert(preDefinitionHeaders->size() < elements);
659 	sort(preDefinitionHeaders->begin(), preDefinitionHeaders->end(), sortOnName);
660 }
661 
662 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
663  *                             ASBase Functions
664  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
665 
666 // check if a specific line position contains a header.
findHeader(const string & line,int i,const vector<const string * > * possibleHeaders) const667 const string* ASBase::findHeader(const string& line, int i,
668                                  const vector<const string*>* possibleHeaders) const
669 {
670 	assert(isCharPotentialHeader(line, i));
671 	// check the word
672 	size_t maxHeaders = possibleHeaders->size();
673 	for (size_t p = 0; p < maxHeaders; p++)
674 	{
675 		const string* header = (*possibleHeaders)[p];
676 		const size_t wordEnd = i + header->length();
677 		if (wordEnd > line.length())
678 			continue;
679 		int result = (line.compare(i, header->length(), *header));
680 		if (result > 0)
681 			continue;
682 		if (result < 0)
683 			break;
684 		// check that this is not part of a longer word
685 		if (wordEnd == line.length())
686 			return header;
687 		if (isLegalNameChar(line[wordEnd]))
688 			continue;
689 		const char peekChar = peekNextChar(line, wordEnd - 1);
690 		// is not a header if part of a definition
691 		if (peekChar == ',' || peekChar == ')')
692 			break;
693 		// the following accessor definitions are NOT headers
694 		// goto default; is NOT a header
695 		// default(int) keyword in C# is NOT a header
696 		else if ((header == &AS_GET
697 		          || header == &AS_SET
698 		          || header == &AS_DEFAULT)
699 		         && (peekChar == ';' || peekChar == '(' || peekChar == '='))
700 			break;
701 		return header;
702 	}
703 	return nullptr;
704 }
705 
706 // check if a specific line position contains a keyword.
findKeyword(const string & line,int i,const string & keyword) const707 bool ASBase::findKeyword(const string& line, int i, const string& keyword) const
708 {
709 	assert(isCharPotentialHeader(line, i));
710 	// check the word
711 	const size_t keywordLength = keyword.length();
712 	const size_t wordEnd = i + keywordLength;
713 	if (wordEnd > line.length())
714 		return false;
715 	if (line.compare(i, keywordLength, keyword) != 0)
716 		return false;
717 	// check that this is not part of a longer word
718 	if (wordEnd == line.length())
719 		return true;
720 	if (isLegalNameChar(line[wordEnd]))
721 		return false;
722 	// is not a keyword if part of a definition
723 	const char peekChar = peekNextChar(line, (int) wordEnd - 1);
724 	if (peekChar == ',' || peekChar == ')')
725 		return false;
726 	return true;
727 }
728 
729 // check if a specific line position contains an operator.
findOperator(const string & line,int i,const vector<const string * > * possibleOperators) const730 const string* ASBase::findOperator(const string& line, int i,
731                                    const vector<const string*>* possibleOperators) const
732 {
733 	assert(isCharPotentialOperator(line[i]));
734 	// find the operator in the vector
735 	// the vector contains the LONGEST operators first
736 	// must loop thru the entire vector
737 	size_t maxOperators = possibleOperators->size();
738 	for (size_t p = 0; p < maxOperators; p++)
739 	{
740 		const size_t wordEnd = i + (*(*possibleOperators)[p]).length();
741 		if (wordEnd > line.length())
742 			continue;
743 		if (line.compare(i, (*(*possibleOperators)[p]).length(), *(*possibleOperators)[p]) == 0)
744 			return (*possibleOperators)[p];
745 	}
746 	return nullptr;
747 }
748 
749 // get the current word on a line
750 // index must point to the beginning of the word
getCurrentWord(const string & line,size_t index) const751 string ASBase::getCurrentWord(const string& line, size_t index) const
752 {
753 	assert(isCharPotentialHeader(line, index));
754 	size_t lineLength = line.length();
755 	size_t i;
756 	for (i = index; i < lineLength; i++)
757 	{
758 		if (!isLegalNameChar(line[i]))
759 			break;
760 	}
761 	return line.substr(index, i - index);
762 }
763 
764 // check if a specific character can be used in a legal variable/method/class name
isLegalNameChar(char ch) const765 bool ASBase::isLegalNameChar(char ch) const
766 {
767 	if (isWhiteSpace(ch))
768 		return false;
769 	if ((unsigned char) ch > 127)
770 		return false;
771 	return (isalnum((unsigned char) ch)
772 	        || ch == '.' || ch == '_'
773 	        || (isJavaStyle() && ch == '$')
774 	        || (isSharpStyle() && ch == '@'));  // may be used as a prefix
775 }
776 
777 // check if a specific character can be part of a header
isCharPotentialHeader(const string & line,size_t i) const778 bool ASBase::isCharPotentialHeader(const string& line, size_t i) const
779 {
780 	assert(!isWhiteSpace(line[i]));
781 	char prevCh = ' ';
782 	if (i > 0)
783 		prevCh = line[i - 1];
784 	if (!isLegalNameChar(prevCh) && isLegalNameChar(line[i]))
785 		return true;
786 	return false;
787 }
788 
789 // check if a specific character can be part of an operator
isCharPotentialOperator(char ch) const790 bool ASBase::isCharPotentialOperator(char ch) const
791 {
792 	assert(!isWhiteSpace(ch));
793 	if ((unsigned) ch > 127)
794 		return false;
795 	return (ispunct((unsigned char) ch)
796 	        && ch != '{' && ch != '}'
797 	        && ch != '(' && ch != ')'
798 	        && ch != '[' && ch != ']'
799 	        && ch != ';' && ch != ','
800 	        && ch != '#' && ch != '\\'
801 	        && ch != '\'' && ch != '\"');
802 }
803 
804 // check if a specific character is a digit
805 // NOTE: Visual C isdigit() gives assert error if char > 256
isDigit(char ch) const806 bool ASBase::isDigit(char ch) const
807 {
808 	return (ch >= '0' && ch <= '9');
809 }
810 
811 // check if a specific character is a digit separator
isDigitSeparator(const string & line,int i) const812 bool ASBase::isDigitSeparator(const string& line, int i) const
813 {
814 	assert(line[i] == '\'');
815 	// casting to (unsigned char) eliminates negative characters
816 	// will get a "Debug Assertion Failed" if not cast
817 	bool foundDigitSeparator = i > 0
818 	                           && isxdigit((unsigned char) line[i - 1])
819 	                           && i < (int) line.length() - 1
820 	                           && isxdigit((unsigned char) line[i + 1]);
821 	return foundDigitSeparator;
822 }
823 
824 // peek at the next unread character.
peekNextChar(const string & line,int i) const825 char ASBase::peekNextChar(const string& line, int i) const
826 {
827 	char ch = ' ';
828 	size_t peekNum = line.find_first_not_of(" \t", i + 1);
829 	if (peekNum == string::npos)
830 		return ch;
831 	ch = line[peekNum];
832 	return ch;
833 }
834 
835 }   // end namespace astyle
836