EscapeSequenceParser.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2022, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Format.h>
  7. #include <AK/Types.h>
  8. #include <LibVT/EscapeSequenceParser.h>
  9. #include <LibVT/EscapeSequenceStateMachine.h>
  10. namespace VT {
  11. EscapeSequenceParser::EscapeSequenceParser(EscapeSequenceExecutor& executor)
  12. : m_executor(executor)
  13. , m_state_machine([this](auto action, auto byte) { perform_action(action, byte); })
  14. {
  15. }
  16. Vector<EscapeSequenceParser::OscParameter> EscapeSequenceParser::osc_parameters() const
  17. {
  18. VERIFY(m_osc_raw.size() >= m_osc_parameter_indexes.last());
  19. Vector<EscapeSequenceParser::OscParameter> params;
  20. size_t prev_idx = 0;
  21. for (auto end_idx : m_osc_parameter_indexes) {
  22. // If the parameter is empty, we take an out of bounds index as the beginning of the Span.
  23. // This should not be a problem as we won't dereference the 0-length Span that's created.
  24. // Using &m_osc_raw[prev_idx] to get the start pointer checks whether we're out of bounds,
  25. // so we would crash.
  26. params.append({ m_osc_raw.data() + prev_idx, end_idx - prev_idx });
  27. prev_idx = end_idx;
  28. }
  29. return params;
  30. }
  31. void EscapeSequenceParser::perform_action(EscapeSequenceStateMachine::Action action, u8 byte)
  32. {
  33. auto advance_utf8 = [&](u8 byte) {
  34. u32 new_code_point = m_code_point;
  35. new_code_point <<= 6;
  36. new_code_point |= byte & 0x3f;
  37. return new_code_point;
  38. };
  39. switch (action) {
  40. case EscapeSequenceStateMachine::Action::_Ignore:
  41. break;
  42. case EscapeSequenceStateMachine::Action::Print:
  43. m_executor.emit_code_point((u32)byte);
  44. break;
  45. case EscapeSequenceStateMachine::Action::PrintUTF8:
  46. m_executor.emit_code_point(advance_utf8(byte));
  47. break;
  48. case EscapeSequenceStateMachine::Action::Execute:
  49. m_executor.execute_control_code(byte);
  50. break;
  51. case EscapeSequenceStateMachine::Action::Hook:
  52. if (m_param_vector.size() == MAX_PARAMETERS)
  53. m_ignoring = true;
  54. else
  55. m_param_vector.append(m_param);
  56. m_executor.dcs_hook(m_param_vector, intermediates(), m_ignoring, byte);
  57. break;
  58. case EscapeSequenceStateMachine::Action::Put:
  59. m_executor.receive_dcs_char(byte);
  60. break;
  61. case EscapeSequenceStateMachine::Action::BeginUTF8:
  62. if ((byte & 0xe0) == 0xc0) {
  63. m_code_point = byte & 0x1f;
  64. } else if ((byte & 0xf0) == 0xe0) {
  65. m_code_point = byte & 0x0f;
  66. } else if ((byte & 0xf8) == 0xf0) {
  67. m_code_point = byte & 0x07;
  68. } else {
  69. dbgln("Invalid character was parsed as UTF-8 initial byte {:02x}", byte);
  70. VERIFY_NOT_REACHED();
  71. }
  72. break;
  73. case EscapeSequenceStateMachine::Action::AdvanceUTF8:
  74. VERIFY((byte & 0xc0) == 0x80);
  75. m_code_point = advance_utf8(byte);
  76. break;
  77. case EscapeSequenceStateMachine::Action::FailUTF8:
  78. m_executor.emit_code_point(U'�');
  79. break;
  80. case EscapeSequenceStateMachine::Action::OscStart:
  81. m_osc_raw.clear();
  82. m_osc_parameter_indexes.clear();
  83. break;
  84. case EscapeSequenceStateMachine::Action::OscPut:
  85. if (byte == ';') {
  86. if (m_osc_parameter_indexes.size() == MAX_OSC_PARAMETERS) {
  87. dbgln("EscapeSequenceParser::perform_action: shenanigans! OSC sequence has too many parameters");
  88. } else {
  89. m_osc_parameter_indexes.append(m_osc_raw.size());
  90. }
  91. } else {
  92. m_osc_raw.append(byte);
  93. }
  94. break;
  95. case EscapeSequenceStateMachine::Action::OscEnd:
  96. if (m_osc_parameter_indexes.size() == MAX_OSC_PARAMETERS) {
  97. dbgln("EscapeSequenceParser::perform_action: shenanigans! OSC sequence has too many parameters");
  98. } else {
  99. m_osc_parameter_indexes.append(m_osc_raw.size());
  100. }
  101. m_executor.execute_osc_sequence(osc_parameters(), byte);
  102. break;
  103. case EscapeSequenceStateMachine::Action::Unhook:
  104. m_executor.execute_dcs_sequence();
  105. break;
  106. case EscapeSequenceStateMachine::Action::CsiDispatch:
  107. if (m_param_vector.size() > MAX_PARAMETERS) {
  108. dbgln("EscapeSequenceParser::perform_action: shenanigans! CSI sequence has too many parameters");
  109. m_ignoring = true;
  110. } else {
  111. m_param_vector.append(m_param);
  112. }
  113. m_executor.execute_csi_sequence(m_param_vector, intermediates(), m_ignoring, byte);
  114. break;
  115. case EscapeSequenceStateMachine::Action::EscDispatch:
  116. m_executor.execute_escape_sequence(intermediates(), m_ignoring, byte);
  117. break;
  118. case EscapeSequenceStateMachine::Action::Collect:
  119. if (m_intermediate_idx == MAX_INTERMEDIATES) {
  120. dbgln("EscapeSequenceParser::perform_action: shenanigans! escape sequence has too many intermediates");
  121. m_ignoring = true;
  122. } else {
  123. m_intermediates[m_intermediate_idx++] = byte;
  124. }
  125. break;
  126. case EscapeSequenceStateMachine::Action::Param:
  127. if (m_param_vector.size() == MAX_PARAMETERS) {
  128. dbgln("EscapeSequenceParser::perform_action: shenanigans! escape sequence has too many parameters");
  129. m_ignoring = true;
  130. } else {
  131. if (byte == ';') {
  132. m_param_vector.append(m_param);
  133. m_param = 0;
  134. } else if (byte == ':') {
  135. dbgln("EscapeSequenceParser::perform_action: subparameters are not yet implemented");
  136. } else {
  137. m_param *= 10;
  138. m_param += (byte - '0');
  139. }
  140. }
  141. break;
  142. case EscapeSequenceStateMachine::Action::Clear:
  143. m_intermediate_idx = 0;
  144. m_ignoring = false;
  145. m_param = 0;
  146. m_param_vector.clear_with_capacity();
  147. break;
  148. }
  149. }
  150. }