EscapeSequenceParser.cpp 5.8 KB

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