The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
8.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. namespace build_tools
  21. {
  22. static bool isReservedKeyword (String::CharPointerType token, const int tokenLength) noexcept
  23. {
  24. static const char* const keywords2Char[] =
  25. { "do", "if", "or", nullptr };
  26. static const char* const keywords3Char[] =
  27. { "and", "asm", "for", "int", "new", "not", "try", "xor", nullptr };
  28. static const char* const keywords4Char[] =
  29. { "auto", "bool", "case", "char", "else", "enum", "goto",
  30. "long", "this", "true", "void", nullptr };
  31. static const char* const keywords5Char[] =
  32. { "bitor", "break", "catch", "class", "compl", "const", "false", "final",
  33. "float", "or_eq", "short", "throw", "union", "using", "while", nullptr };
  34. static const char* const keywords6Char[] =
  35. { "and_eq", "bitand", "delete", "double", "export", "extern", "friend",
  36. "import", "inline", "module", "not_eq", "public", "return", "signed",
  37. "sizeof", "static", "struct", "switch", "typeid", "xor_eq", nullptr };
  38. static const char* const keywords7Char[] =
  39. { "__cdecl", "_Pragma", "alignas", "alignof", "concept", "default",
  40. "mutable", "nullptr", "private", "typedef", "uint8_t", "virtual",
  41. "wchar_t", nullptr };
  42. static const char* const keywordsOther[] =
  43. { "@class", "@dynamic", "@end", "@implementation", "@interface", "@public",
  44. "@private", "@protected", "@property", "@synthesize", "__fastcall", "__stdcall",
  45. "atomic_cancel", "atomic_commit", "atomic_noexcept", "char16_t", "char32_t",
  46. "co_await", "co_return", "co_yield", "const_cast", "constexpr", "continue",
  47. "decltype", "dynamic_cast", "explicit", "namespace", "noexcept", "operator", "override",
  48. "protected", "register", "reinterpret_cast", "requires", "static_assert",
  49. "static_cast", "synchronized", "template", "thread_local", "typename", "unsigned",
  50. "volatile", nullptr };
  51. const char* const* k;
  52. switch (tokenLength)
  53. {
  54. case 2: k = keywords2Char; break;
  55. case 3: k = keywords3Char; break;
  56. case 4: k = keywords4Char; break;
  57. case 5: k = keywords5Char; break;
  58. case 6: k = keywords6Char; break;
  59. case 7: k = keywords7Char; break;
  60. default:
  61. if (tokenLength < 2 || tokenLength > 16)
  62. return false;
  63. k = keywordsOther;
  64. break;
  65. }
  66. for (int i = 0; k[i] != nullptr; ++i)
  67. if (token.compare (CharPointer_ASCII (k[i])) == 0)
  68. return true;
  69. return false;
  70. }
  71. static bool isReservedKeyword (const String& token) noexcept
  72. {
  73. return isReservedKeyword (token.getCharPointer(), token.length());
  74. }
  75. //==============================================================================
  76. /** Takes a UTF8 string and writes it to a stream using standard C++ escape sequences for any
  77. non-ascii bytes.
  78. Although not strictly a tokenising function, this is still a function that often comes in
  79. handy when working with C++ code!
  80. Note that addEscapeChars() is easier to use than this function if you're working with Strings.
  81. @see addEscapeChars
  82. */
  83. static void writeEscapeChars (OutputStream& out, const char* utf8, const int numBytesToRead,
  84. const int maxCharsOnLine, const bool breakAtNewLines,
  85. const bool replaceSingleQuotes, const bool allowStringBreaks)
  86. {
  87. int charsOnLine = 0;
  88. bool lastWasHexEscapeCode = false;
  89. bool trigraphDetected = false;
  90. for (int i = 0; i < numBytesToRead || numBytesToRead < 0; ++i)
  91. {
  92. auto c = (unsigned char) utf8[i];
  93. bool startNewLine = false;
  94. switch (c)
  95. {
  96. case '\t': out << "\\t"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
  97. case '\r': out << "\\r"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
  98. case '\n': out << "\\n"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; startNewLine = breakAtNewLines; break;
  99. case '\\': out << "\\\\"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
  100. case '\"': out << "\\\""; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
  101. case '?':
  102. if (trigraphDetected)
  103. {
  104. out << "\\?";
  105. charsOnLine++;
  106. trigraphDetected = false;
  107. }
  108. else
  109. {
  110. out << "?";
  111. trigraphDetected = true;
  112. }
  113. lastWasHexEscapeCode = false;
  114. charsOnLine++;
  115. break;
  116. case 0:
  117. if (numBytesToRead < 0)
  118. return;
  119. out << "\\0";
  120. lastWasHexEscapeCode = true;
  121. trigraphDetected = false;
  122. charsOnLine += 2;
  123. break;
  124. case '\'':
  125. if (replaceSingleQuotes)
  126. {
  127. out << "\\\'";
  128. lastWasHexEscapeCode = false;
  129. trigraphDetected = false;
  130. charsOnLine += 2;
  131. break;
  132. }
  133. // deliberate fall-through...
  134. default:
  135. if (c >= 32 && c < 127 && ! (lastWasHexEscapeCode // (have to avoid following a hex escape sequence with a valid hex digit)
  136. && CharacterFunctions::getHexDigitValue (c) >= 0))
  137. {
  138. out << (char) c;
  139. lastWasHexEscapeCode = false;
  140. trigraphDetected = false;
  141. ++charsOnLine;
  142. }
  143. else if (allowStringBreaks && lastWasHexEscapeCode && c >= 32 && c < 127)
  144. {
  145. out << "\"\"" << (char) c;
  146. lastWasHexEscapeCode = false;
  147. trigraphDetected = false;
  148. charsOnLine += 3;
  149. }
  150. else
  151. {
  152. out << (c < 16 ? "\\x0" : "\\x") << String::toHexString ((int) c);
  153. lastWasHexEscapeCode = true;
  154. trigraphDetected = false;
  155. charsOnLine += 4;
  156. }
  157. break;
  158. }
  159. if ((startNewLine || (maxCharsOnLine > 0 && charsOnLine >= maxCharsOnLine))
  160. && (numBytesToRead < 0 || i < numBytesToRead - 1))
  161. {
  162. charsOnLine = 0;
  163. out << "\"" << newLine << "\"";
  164. lastWasHexEscapeCode = false;
  165. }
  166. }
  167. }
  168. }
  169. }