mirror of
https://github.com/lihop/godot-xterm.git
synced 2025-05-04 20:24:23 +02:00
Add all the files
This commit is contained in:
parent
d7db117f8b
commit
96e9ddcf79
68 changed files with 9064 additions and 7 deletions
131
addons/godot_xterm/parser/constants.gd
Normal file
131
addons/godot_xterm/parser/constants.gd
Normal file
|
@ -0,0 +1,131 @@
|
|||
# Copyright (c) 2020 The GodotXterm authors.
|
||||
# Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
# License MIT
|
||||
extends Reference
|
||||
|
||||
# Psuedo-character placeholder for non-ascii characters (unicode).
|
||||
const NON_ASCII_PRINTABLE = 0xa0
|
||||
|
||||
# Payload limit for OSC and DCS.
|
||||
const PAYLOAD_LIMIT = 10000000
|
||||
|
||||
# Internal states of EscapeSequenceParser.
|
||||
enum ParserState {
|
||||
GROUND
|
||||
ESCAPE
|
||||
ESCAPE_INTERMEDIATE
|
||||
CSI_ENTRY
|
||||
CSI_PARAM
|
||||
CSI_INTERMEDIATE
|
||||
CSI_IGNORE
|
||||
SOS_PM_APC_STRING
|
||||
OSC_STRING
|
||||
DCS_ENTRY
|
||||
DCS_PARAM
|
||||
DCS_IGNORE
|
||||
DCS_INTERMEDIATE
|
||||
DCS_PASSTHROUGH
|
||||
}
|
||||
|
||||
# Internal actions of EscapeSequenceParser.
|
||||
enum ParserAction {
|
||||
IGNORE
|
||||
ERROR
|
||||
PRINT
|
||||
EXECUTE
|
||||
OSC_START
|
||||
OSC_PUT
|
||||
OSC_END
|
||||
CSI_DISPATCH
|
||||
PARAM
|
||||
COLLECT
|
||||
ESC_DISPATCH
|
||||
CLEAR
|
||||
DCS_HOOK
|
||||
DCS_PUT
|
||||
DCS_UNHOOK
|
||||
}
|
||||
|
||||
# Internal states of OscParser.
|
||||
enum OscState {
|
||||
START
|
||||
ID
|
||||
PAYLOAD
|
||||
ABORT
|
||||
}
|
||||
|
||||
# C0 control codes
|
||||
# See: https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C0_controls
|
||||
enum C0 {
|
||||
NUL
|
||||
SOH
|
||||
STX
|
||||
ETX
|
||||
EOT
|
||||
ENQ
|
||||
ACK
|
||||
BEL
|
||||
BS
|
||||
HT
|
||||
LF
|
||||
VT
|
||||
FF
|
||||
CR
|
||||
SO
|
||||
SI
|
||||
DLE
|
||||
DC1
|
||||
DC2
|
||||
DC3
|
||||
DC4
|
||||
NAK
|
||||
SYN
|
||||
ETB
|
||||
CAN
|
||||
EM
|
||||
SUB
|
||||
ESC
|
||||
FS
|
||||
GS
|
||||
RS
|
||||
US
|
||||
SP
|
||||
DEL = 0x7f
|
||||
}
|
||||
|
||||
# C1 control codes
|
||||
# See: https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_controls
|
||||
enum C1 {
|
||||
PAD = 0x80
|
||||
HOP = 0x81
|
||||
BPH = 0x82
|
||||
NBH = 0x83
|
||||
IND = 0x84
|
||||
NEL = 0x85
|
||||
SSA = 0x86
|
||||
ESA = 0x87
|
||||
HTS = 0x88
|
||||
HTJ = 0x89
|
||||
VTS = 0x8a
|
||||
PLD = 0x8b
|
||||
PLU = 0x8c
|
||||
RI = 0x8d
|
||||
SS2 = 0x8e
|
||||
SS3 = 0x8f
|
||||
DCS = 0x90
|
||||
PU1 = 0x91
|
||||
PU2 = 0x92
|
||||
STS = 0x93
|
||||
CCH = 0x94
|
||||
MW = 0x95
|
||||
SPA = 0x96
|
||||
EPA = 0x97
|
||||
SOS = 0x98
|
||||
SGCI = 0x99
|
||||
SCI = 0x9a
|
||||
CSI = 0x9b
|
||||
ST = 0x9c
|
||||
OSC = 0x9d
|
||||
PM = 0x9e
|
||||
APC = 0x9f
|
||||
}
|
77
addons/godot_xterm/parser/dcs_parser.gd
Normal file
77
addons/godot_xterm/parser/dcs_parser.gd
Normal file
|
@ -0,0 +1,77 @@
|
|||
# Copyright (c) 2020 The GodotXterm authors.
|
||||
# Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
# License MIT
|
||||
extends Reference
|
||||
|
||||
|
||||
const Decoder = preload("res://addons/godot_xterm/input/text_decoder.gd")
|
||||
|
||||
|
||||
const EMPTY_HANDLERS = []
|
||||
|
||||
|
||||
var _handlers: Dictionary = {}
|
||||
var _active: Array = EMPTY_HANDLERS
|
||||
var _ident: int = 0
|
||||
var _handler_fb: Dictionary
|
||||
|
||||
|
||||
func _init():
|
||||
pass
|
||||
|
||||
|
||||
func set_handler(ident: int, handler):
|
||||
_handlers[ident] = [handler]
|
||||
|
||||
|
||||
func clear_handler(ident: int):
|
||||
_handlers.erase(ident)
|
||||
|
||||
|
||||
func set_handler_fallback(target, method):
|
||||
_handler_fb = {'target': target, 'method': method}
|
||||
|
||||
|
||||
func reset():
|
||||
if _active.size():
|
||||
unhook(false)
|
||||
_active = EMPTY_HANDLERS
|
||||
_ident = 0
|
||||
|
||||
|
||||
func hook(ident: int, params):
|
||||
# always reset leftover handlers
|
||||
reset()
|
||||
_ident = ident
|
||||
_active = _handlers[ident] if _handlers.has(ident) else EMPTY_HANDLERS
|
||||
if _active.empty():
|
||||
_handler_fb['target'].call(_handler_fb['method'], _ident, 'HOOK', params)
|
||||
else:
|
||||
_active.invert()
|
||||
for handler in _active:
|
||||
handler.hook(params)
|
||||
_active.invert()
|
||||
|
||||
|
||||
func put(data: Array, start: int, end: int):
|
||||
if _active.empty():
|
||||
_handler_fb['target'].call(_handler_fb['method'], _ident, 'PUT',
|
||||
Decoder.utf32_to_string(data, start, end))
|
||||
else:
|
||||
_active.invert()
|
||||
for handler in _active:
|
||||
handler.put(data, start, end)
|
||||
_active.invert()
|
||||
|
||||
|
||||
func unhook(success: bool):
|
||||
if _active.empty():
|
||||
_handler_fb['target'].call(_handler_fb['method'], _ident, 'UNHOOK', success)
|
||||
else:
|
||||
_active.invert()
|
||||
for handler in _active:
|
||||
if handler.unhook(success) != false:
|
||||
success = false # will cleanup left over handlers
|
||||
_active.invert()
|
||||
_active = EMPTY_HANDLERS
|
||||
_ident = 0
|
329
addons/godot_xterm/parser/escape_sequence_parser.gd
Normal file
329
addons/godot_xterm/parser/escape_sequence_parser.gd
Normal file
|
@ -0,0 +1,329 @@
|
|||
# Copyright (c) 2020 The GodotXterm authors. All rights reserved.
|
||||
# Copyright (c) 2018 The xterm.js authers. All rights reserved.
|
||||
# License MIT
|
||||
extends Reference
|
||||
|
||||
const Constants = preload("res://addons/godot_xterm/parser/constants.gd")
|
||||
const TransitionTable = preload("res://addons/godot_xterm/parser/transition_table.gd")
|
||||
const VT500TransitionTable = preload("res://addons/godot_xterm/parser/vt500_transition_table.gd")
|
||||
const DcsParser = preload("res://addons/godot_xterm/parser/dcs_parser.gd")
|
||||
const Params = preload("res://addons/godot_xterm/parser/params.gd")
|
||||
|
||||
const TableAccess = TransitionTable.TableAccess
|
||||
const NON_ASCII_PRINTABLE = Constants.NON_ASCII_PRINTABLE
|
||||
const ParserState = Constants.ParserState
|
||||
const ParserAction = Constants.ParserAction
|
||||
|
||||
var initial_state
|
||||
var current_state
|
||||
var preceding_codepoint
|
||||
|
||||
var _transitions
|
||||
|
||||
# buffers over several parse calls
|
||||
var _params
|
||||
var _collect
|
||||
|
||||
# handler lookup containers
|
||||
var _print_handler
|
||||
var _execute_handlers
|
||||
var _csi_handlers
|
||||
var _esc_handlers
|
||||
var _osc_parser
|
||||
var _dcs_parser
|
||||
var _error_handler
|
||||
|
||||
# fallback handlers
|
||||
var _print_handler_fb
|
||||
var _execute_handler_fb
|
||||
var _csi_handler_fb
|
||||
var _esc_handler_fb
|
||||
var _error_handler_fb
|
||||
|
||||
|
||||
# Default do noting fallback handler.
|
||||
# Allows a variable number of arguments from 0 - 7.
|
||||
func noop(a = null, b = null, c = null, d = null, e = null, f = null, g = null):
|
||||
pass
|
||||
|
||||
|
||||
func _init(transitions = VT500TransitionTable.new().table):
|
||||
initial_state = ParserState.GROUND
|
||||
current_state = initial_state
|
||||
_transitions = transitions
|
||||
_params = Params.new() # Defaults to 32 storable params/subparams
|
||||
_params.add_param(0) # ZDM (Zero Default Mode
|
||||
_collect = 0
|
||||
preceding_codepoint = 0
|
||||
|
||||
# set default fallback handlers and handler lookup containers
|
||||
var noop = {'target': self, 'method': 'noop'}
|
||||
_print_handler_fb = noop
|
||||
_execute_handler_fb = noop
|
||||
_csi_handler_fb = noop
|
||||
_esc_handler_fb = noop
|
||||
_error_handler_fb = noop
|
||||
_print_handler = _print_handler_fb
|
||||
_execute_handlers = {}
|
||||
_csi_handlers = {}
|
||||
_esc_handlers = {}
|
||||
_osc_parser = null # TODO OscParser.new()
|
||||
_dcs_parser = DcsParser.new()
|
||||
_error_handler = _error_handler_fb
|
||||
|
||||
# swallow 7bit ST (ESC+\)
|
||||
set_esc_handler({'final': '\\'}, self, 'noop')
|
||||
|
||||
|
||||
static func identifier(id: Dictionary, final_range: Array = [0x40, 0x7e]):
|
||||
var res = 0
|
||||
|
||||
var prefix = id.get('prefix')
|
||||
var intermediates = id.get('intermediates')
|
||||
var final = id.get('final')
|
||||
|
||||
if prefix:
|
||||
if prefix.length() > 1:
|
||||
push_error("only one byte prefix supported")
|
||||
res = prefix.to_ascii()[0]
|
||||
if res and 0x3c > res or res > 0x3f:
|
||||
push_error("prefix must be in the range 0x3c-0x3f")
|
||||
|
||||
if intermediates:
|
||||
if intermediates.length() > 2:
|
||||
push_error("only two bytes as intermediates are supported")
|
||||
for intermediate in intermediates:
|
||||
var im = intermediate.to_ascii()[0]
|
||||
if 0x20 > im or im > 0x2f:
|
||||
push_error("intermediate must be in the range 0x20-0x2f")
|
||||
res = res << 8
|
||||
res = res | im
|
||||
|
||||
if final.length() != 1:
|
||||
push_error("final must be a single byte")
|
||||
var final_code = final.to_ascii()[0]
|
||||
if final_range[0] > final_code or final_code > final_range[1]:
|
||||
push_error("final must be in the range " + String(final_range[0]) + "-" + String(final_range[1]))
|
||||
res = res << 8
|
||||
res = res | final_code
|
||||
|
||||
return res
|
||||
|
||||
static func ident_to_string(ident: int):
|
||||
var res = PoolStringArray([])
|
||||
while ident:
|
||||
res.append(PoolByteArray([ident & 0xFF]).get_string_from_ascii())
|
||||
ident >>= 8
|
||||
res.invert()
|
||||
return res.join('')
|
||||
|
||||
func set_print_handler(target: Object, method: String):
|
||||
_print_handler = { 'target': target, 'method': method }
|
||||
|
||||
|
||||
func add_esc_handler(id, target, method):
|
||||
var ident = identifier(id, [0x30, 0x7e])
|
||||
if not _esc_handlers.has(ident):
|
||||
_esc_handlers[ident] = []
|
||||
var handler_list = _esc_handlers[ident]
|
||||
handler_list.append({'target': target, 'method': method})
|
||||
|
||||
|
||||
func set_csi_handler(id: Dictionary, target: Object, method: String):
|
||||
_csi_handlers[identifier(id)] = [{ 'target': target, 'method': method }]
|
||||
|
||||
|
||||
func set_csi_handler_fallback(target, method):
|
||||
_csi_handler_fb = { 'target': target, 'method': method }
|
||||
|
||||
|
||||
func set_execute_handler(flag: int, target: Object, method: String):
|
||||
_execute_handlers[flag] = { 'target': target, 'method': method }
|
||||
|
||||
|
||||
func set_execute_handler_fallback(target: Object, method: String):
|
||||
_execute_handler_fb = { 'target': target, 'method': method }
|
||||
|
||||
|
||||
func set_esc_handler(id, target, method):
|
||||
_esc_handlers[identifier(id, [0x30, 0x7e])] = [{'target': target, 'method': method}]
|
||||
|
||||
|
||||
func set_esc_handler_fallback(target: Object, method: String):
|
||||
_esc_handler_fb = {'target': target, 'method': method}
|
||||
|
||||
|
||||
func add_dcs_handler(id, target, method):
|
||||
pass
|
||||
# TODO!!!
|
||||
|
||||
func set_dcs_handler(id, target: Object, method: String):
|
||||
_dcs_parser.set_handler(id, {'target': target, 'method': method})
|
||||
|
||||
func set_dcs_handler_fallback(target: Object, method: String):
|
||||
_dcs_parser.set_handler_fallback(target, method)
|
||||
|
||||
func reset():
|
||||
current_state = initial_state
|
||||
_params.reset()
|
||||
_params.add_param(0) # ZDM
|
||||
_collect = 0
|
||||
preceding_codepoint = 0
|
||||
|
||||
func parse(data: Array, length: int):
|
||||
var code = 0
|
||||
var transition = 0
|
||||
var _current_state = current_state
|
||||
var dcs = _dcs_parser
|
||||
var collect = _collect
|
||||
var params = _params
|
||||
|
||||
#print("table", table)
|
||||
|
||||
#print("parse -> data: ", data, " length: ", length)
|
||||
|
||||
# Process input string.
|
||||
var i = 0
|
||||
while i < length:
|
||||
#print("i: ", i)
|
||||
code = data[i]
|
||||
|
||||
#print("code: ", code)
|
||||
|
||||
# Normal transition and action lookup.
|
||||
transition = _transitions[_current_state << TableAccess.INDEX_STATE_SHIFT | code if code < 0xa0 else NON_ASCII_PRINTABLE]
|
||||
|
||||
#print ("transition: ", transition)
|
||||
#print("current state: ", current_state)
|
||||
|
||||
match transition >> TableAccess.TRANSITION_ACTION_SHIFT:
|
||||
ParserAction.PRINT:
|
||||
# read ahead with loop unrolling
|
||||
# # Note: 0x20 (SP) is included, 0x7F (DEL) is excluded
|
||||
var j = i + 1
|
||||
while true:
|
||||
code = data[j] if j < data.size() else 0
|
||||
if j >= length or code < 0x20 or (code > 0x7e and code < NON_ASCII_PRINTABLE):
|
||||
_print_handler['target'].call(_print_handler['method'], data, i, j)
|
||||
i = j - 1
|
||||
break
|
||||
j += 1
|
||||
code = data[j] if j < data.size() else 0
|
||||
if j >= length or code < 0x20 or (code > 0x7e and code < NON_ASCII_PRINTABLE):
|
||||
_print_handler['target'].call(_print_handler['method'], data, i, j)
|
||||
i = j - 1
|
||||
break
|
||||
j += 1
|
||||
code = data[j] if j < data.size() else 0
|
||||
if j >= length or code < 0x20 or (code > 0x7e and code < NON_ASCII_PRINTABLE):
|
||||
_print_handler['target'].call(_print_handler['method'], data, i, j)
|
||||
i = j - 1
|
||||
break
|
||||
j += 1
|
||||
code = data[j] if j < data.size() else 0
|
||||
if j >= length or code < 0x20 or (code > 0x7e and code < NON_ASCII_PRINTABLE):
|
||||
_print_handler['target'].call(_print_handler['method'], data, i, j)
|
||||
i = j - 1
|
||||
break
|
||||
j += 1
|
||||
ParserAction.EXECUTE:
|
||||
var handler = _execute_handlers.get(code)
|
||||
if handler:
|
||||
handler['target'].call(handler['method'])
|
||||
elif _execute_handler_fb:
|
||||
_execute_handler_fb['target'].call(_execute_handler_fb['method'], code)
|
||||
preceding_codepoint = 0
|
||||
ParserAction.IGNORE:
|
||||
pass
|
||||
ParserAction.ERROR:
|
||||
print("Parser error!")
|
||||
|
||||
ParserAction.CSI_DISPATCH:
|
||||
# Trigger CSI Handler
|
||||
var handlers = _csi_handlers.get((collect << 8 | code), [])
|
||||
handlers.invert()
|
||||
for handler in handlers:
|
||||
# undefined or true means success and to stop bubbling
|
||||
if handler['target'].call(handler['method'], params.to_array()):
|
||||
continue
|
||||
handlers.invert()
|
||||
if handlers.empty():
|
||||
_csi_handler_fb['target'].call(_csi_handler_fb['method'], collect << 8 | code, params.to_array())
|
||||
preceding_codepoint = 0
|
||||
|
||||
|
||||
ParserAction.PARAM:
|
||||
# Inner loop digits (0x30 - 0x39) and ; (0x3b) and : (0x3a)
|
||||
var do = true
|
||||
while do:
|
||||
match code:
|
||||
0x3b:
|
||||
params.add_param(0)
|
||||
0x3a:
|
||||
params.add_sub_param(-1)
|
||||
_:
|
||||
params.add_digit(code - 48)
|
||||
i += 1
|
||||
code = data[i] if i < data.size() else 0
|
||||
do = i < length and code > 0x2f and code < 0x3c
|
||||
i-=1
|
||||
|
||||
ParserAction.COLLECT:
|
||||
collect <<= 8
|
||||
collect |= code
|
||||
|
||||
ParserAction.ESC_DISPATCH:
|
||||
var handlers = _esc_handlers.get((collect << 8 | code), [])
|
||||
handlers.invert()
|
||||
for handler in handlers:
|
||||
# undefined or true means success and to stop bubbling
|
||||
if handler['target'].call(handler['method']) != false:
|
||||
continue
|
||||
handlers.invert()
|
||||
if handlers.empty():
|
||||
_esc_handler_fb['target'].call(_esc_handler_fb['method'], collect << 8 | code)
|
||||
preceding_codepoint = 0
|
||||
|
||||
ParserAction.CLEAR:
|
||||
params.reset()
|
||||
params.add_param(0) # ZDM
|
||||
collect = 0
|
||||
|
||||
ParserAction.DCS_HOOK:
|
||||
dcs.hook(collect << 8 | code, params.to_array())
|
||||
|
||||
ParserAction.DCS_PUT:
|
||||
# inner loop - exit DCS_PUT: 0x18, 0x1a, 0x1b, 0x7f, 0x80 - 0x9f
|
||||
# unhook triggered by: 0x1b, 0x9c (success) and 0x18, 0x1a (abort)
|
||||
for j in range(i + 1, length + 1):
|
||||
code = data[j]
|
||||
if code == 0x18 or code == 0x1a or code == 0x1b or (code > 0x7f and code < NON_ASCII_PRINTABLE):
|
||||
dcs.put(data, i, j)
|
||||
i = j - 1
|
||||
break
|
||||
break
|
||||
ParserAction.DCS_UNHOOK:
|
||||
_dcs_parser.unhook(code != 0x18 and code != 0x1a)
|
||||
if code == 0x1b:
|
||||
transition |= ParserState.ESCAPE
|
||||
params.reset()
|
||||
params.add_param(0) # ZDM
|
||||
collect = 0;
|
||||
preceding_codepoint = 0
|
||||
ParserAction.OSC_START:
|
||||
pass
|
||||
|
||||
ParserAction.OSC_PUT:
|
||||
pass
|
||||
|
||||
ParserAction.OSC_END:
|
||||
pass
|
||||
|
||||
_current_state = transition & TableAccess.TRANSITION_STATE_MASK
|
||||
i += 1
|
||||
|
||||
# save collected intermediates
|
||||
_collect = collect
|
||||
|
||||
# save state
|
||||
current_state = _current_state
|
104
addons/godot_xterm/parser/params.gd
Normal file
104
addons/godot_xterm/parser/params.gd
Normal file
|
@ -0,0 +1,104 @@
|
|||
# Copyright (c) 2020 The GodotTerm authors.
|
||||
# Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
# License MIT
|
||||
extends Reference
|
||||
|
||||
|
||||
# Max value supported for a single param/subparam (clamped to positive int32 range).
|
||||
const MAX_VALUE = 0x7FFFFFFF;
|
||||
# Max allowed subparams for a single sequence (hardcoded limitation).
|
||||
const MAX_SUBPARAMS = 256;
|
||||
|
||||
var params = []
|
||||
var length = 0
|
||||
|
||||
var sub_params = []
|
||||
var sub_params_length = 0
|
||||
var _max_length
|
||||
var _max_sub_params_length
|
||||
var sub_params_idx = []
|
||||
var _reject_digits = false
|
||||
var _reject_sub_digits = false
|
||||
var digit_is_sub = false
|
||||
|
||||
|
||||
static func from_array(values: Array):
|
||||
# Workaround as per: https://github.com/godotengine/godot/issues/19345#issuecomment-471218401
|
||||
var params = load("res://addons/godot_xterm/parser/params.gd").new()
|
||||
if values.empty():
|
||||
return params
|
||||
# skip leading sub params
|
||||
for i in range(values.size()):
|
||||
var value = values[i]
|
||||
if typeof(value) == TYPE_ARRAY:
|
||||
if i == 0:
|
||||
# skip leading sub params
|
||||
continue
|
||||
else:
|
||||
for sub_param in value:
|
||||
params.add_sub_param(sub_param)
|
||||
else:
|
||||
params.add_param(value)
|
||||
return params
|
||||
|
||||
|
||||
func _init(max_length: int = 32, max_sub_params_length: int = 32):
|
||||
_max_length = max_length
|
||||
_max_sub_params_length = max_sub_params_length
|
||||
|
||||
if (max_sub_params_length > MAX_SUBPARAMS):
|
||||
push_error("max_sub_params_length must not be greater than 256")
|
||||
|
||||
params.resize(max_length)
|
||||
sub_params.resize(max_sub_params_length)
|
||||
sub_params_idx.resize(max_length)
|
||||
|
||||
func add_param(value: int):
|
||||
digit_is_sub = false
|
||||
if length >= _max_length:
|
||||
_reject_digits = true
|
||||
return
|
||||
if value < -1:
|
||||
push_error('values lesser than -1 are not allowed')
|
||||
sub_params_idx[length] = sub_params_length << 8 | sub_params_length
|
||||
params[length] = MAX_VALUE if value > MAX_VALUE else value
|
||||
length += 1
|
||||
|
||||
func add_sub_param(value: int):
|
||||
digit_is_sub = true
|
||||
if !length:
|
||||
return
|
||||
if _reject_digits or sub_params_length >= _max_sub_params_length:
|
||||
_reject_sub_digits = true
|
||||
return
|
||||
if value < -1:
|
||||
push_error('values lesser than -1 are not allowed')
|
||||
sub_params[sub_params_length] = MAX_VALUE if value > MAX_VALUE else value
|
||||
sub_params_length += 1
|
||||
sub_params_idx[length - 1] += 1
|
||||
|
||||
func add_digit(value: int):
|
||||
print("adding digit: ", value, " is sub: ", digit_is_sub)
|
||||
var _length = sub_params_length if digit_is_sub else length
|
||||
if _reject_digits or (not _length) or (digit_is_sub and _reject_sub_digits):
|
||||
return
|
||||
var store = sub_params if digit_is_sub else params
|
||||
var cur = store[_length - 1]
|
||||
store[_length - 1] = min(cur * 10 + value, MAX_VALUE) if ~cur else value
|
||||
|
||||
func to_array():
|
||||
var res = []
|
||||
for i in range(length):
|
||||
res.append(params[i])
|
||||
var start = sub_params_idx[i] >> 8
|
||||
var end = sub_params_idx[i] & 0xff
|
||||
if end - start > 0:
|
||||
res.append(sub_params.slice(start, end - 1))
|
||||
return res
|
||||
|
||||
func reset():
|
||||
length = 0
|
||||
sub_params_length = 0
|
||||
_reject_digits = false
|
||||
_reject_sub_digits = false
|
||||
digit_is_sub = false
|
26
addons/godot_xterm/parser/transition_table.gd
Normal file
26
addons/godot_xterm/parser/transition_table.gd
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 The GodotXterm authors.
|
||||
# Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
# License MIT
|
||||
extends Reference
|
||||
|
||||
enum TableAccess {
|
||||
TRANSITION_ACTION_SHIFT = 4,
|
||||
TRANSITION_STATE_MASK = 15,
|
||||
INDEX_STATE_SHIFT = 8
|
||||
}
|
||||
|
||||
var table: PoolByteArray = PoolByteArray()
|
||||
|
||||
func _init(length: int):
|
||||
table.resize(length)
|
||||
|
||||
func setDefault(action: int, next: int):
|
||||
for i in range(table.size()):
|
||||
table[i] = action << TableAccess.TRANSITION_ACTION_SHIFT | next
|
||||
|
||||
func add(code: int, state: int, action: int, next: int):
|
||||
table[state << TableAccess.INDEX_STATE_SHIFT | code] = action << TableAccess.TRANSITION_ACTION_SHIFT | next
|
||||
|
||||
func addMany(codes: Array, state: int, action: int, next: int):
|
||||
for code in codes:
|
||||
add(code, state, action, next)
|
123
addons/godot_xterm/parser/vt500_transition_table.gd
Normal file
123
addons/godot_xterm/parser/vt500_transition_table.gd
Normal file
|
@ -0,0 +1,123 @@
|
|||
# Copyright (c) 2020 The GodotXterm authors.
|
||||
# Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
# License MIT
|
||||
extends "res://addons/godot_xterm/parser/transition_table.gd"
|
||||
|
||||
const Constants = preload("res://addons/godot_xterm/parser/constants.gd")
|
||||
const ParserState = Constants.ParserState
|
||||
const ParserAction = Constants.ParserAction
|
||||
const NON_ASCII_PRINTABLE = Constants.NON_ASCII_PRINTABLE
|
||||
|
||||
var PRINTABLES = Array(range(0x20, 0x7f)) # 0x20 (SP) included, 0x7f (DEL) excluded.
|
||||
var EXECUTABLES = Array(range(0x00, 0x18)) + [0x19] + Array(range(0x1c, 0x20))
|
||||
|
||||
func _init().(4096):
|
||||
# Set default transition.
|
||||
setDefault(ParserAction.ERROR, ParserState.GROUND)
|
||||
|
||||
# Printables.
|
||||
addMany(PRINTABLES, ParserState.GROUND, ParserAction.PRINT, ParserState.GROUND)
|
||||
|
||||
# Global anywhere rules.
|
||||
for state in ParserState.values():
|
||||
addMany([0x18, 0x1a, 0x99, 0x9a], state, ParserAction.EXECUTE, ParserState.GROUND)
|
||||
addMany(range(0x80, 0x90), state, ParserAction.EXECUTE, ParserState.GROUND)
|
||||
addMany(range(0x90, 0x98), state, ParserAction.EXECUTE, ParserState.GROUND)
|
||||
add(0x9c, state, ParserAction.IGNORE, ParserState.GROUND) # ST as terminator
|
||||
add(0x1b, state, ParserAction.CLEAR, ParserState.ESCAPE) # ESC
|
||||
add(0x9d, state, ParserAction.OSC_START, ParserState.OSC_STRING) # OSC
|
||||
addMany([0x98, 0x9e, 0x9f], state, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING)
|
||||
add(0x9b, state, ParserAction.CLEAR, ParserState.CSI_ENTRY) # CSI
|
||||
add(0x90, state, ParserAction.CLEAR, ParserState.DCS_ENTRY) # DCS
|
||||
|
||||
# Rules for executables and 7f.
|
||||
addMany(EXECUTABLES, ParserState.GROUND, ParserAction.EXECUTE, ParserState.GROUND)
|
||||
addMany(EXECUTABLES, ParserState.ESCAPE, ParserAction.EXECUTE, ParserState.ESCAPE)
|
||||
add(0x7f, ParserState.ESCAPE, ParserAction.IGNORE, ParserState.ESCAPE)
|
||||
addMany(EXECUTABLES, ParserState.OSC_STRING, ParserAction.IGNORE, ParserState.OSC_STRING)
|
||||
addMany(EXECUTABLES, ParserState.CSI_ENTRY, ParserAction.EXECUTE, ParserState.CSI_ENTRY)
|
||||
add(0x7f, ParserState.CSI_ENTRY, ParserAction.IGNORE, ParserState.CSI_ENTRY)
|
||||
addMany(EXECUTABLES, ParserState.CSI_PARAM, ParserAction.EXECUTE, ParserState.CSI_PARAM)
|
||||
add(0x7f, ParserState.CSI_PARAM, ParserAction.IGNORE, ParserState.CSI_PARAM);
|
||||
addMany(EXECUTABLES, ParserState.CSI_IGNORE, ParserAction.EXECUTE, ParserState.CSI_IGNORE)
|
||||
addMany(EXECUTABLES, ParserState.CSI_INTERMEDIATE, ParserAction.EXECUTE, ParserState.CSI_INTERMEDIATE)
|
||||
add(0x7f, ParserState.CSI_INTERMEDIATE, ParserAction.IGNORE, ParserState.CSI_INTERMEDIATE)
|
||||
addMany(EXECUTABLES, ParserState.ESCAPE_INTERMEDIATE, ParserAction.EXECUTE, ParserState.ESCAPE_INTERMEDIATE)
|
||||
add(0x7f, ParserState.ESCAPE_INTERMEDIATE, ParserAction.IGNORE, ParserState.ESCAPE_INTERMEDIATE);
|
||||
|
||||
# OSC.
|
||||
add(0x5d, ParserState.ESCAPE, ParserAction.OSC_START, ParserState.OSC_STRING)
|
||||
addMany(PRINTABLES, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING)
|
||||
add(0x7f, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING)
|
||||
addMany([0x9c, 0x1b, 0x18, 0x1a, 0x07], ParserState.OSC_STRING, ParserAction.OSC_END, ParserState.GROUND)
|
||||
addMany(range(0x1c, 0x20), ParserState.OSC_STRING, ParserAction.IGNORE, ParserState.OSC_STRING)
|
||||
|
||||
# SOS/PM/APC does nothing.
|
||||
addMany([0x58, 0x5e, 0x5f], ParserState.ESCAPE, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING)
|
||||
addMany(PRINTABLES, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING)
|
||||
addMany(EXECUTABLES, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING)
|
||||
add(0x9c, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.GROUND)
|
||||
add(0x7f, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING)
|
||||
# csi entries
|
||||
add(0x5b, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.CSI_ENTRY)
|
||||
addMany(range(0x40, 0x7f), ParserState.CSI_ENTRY, ParserAction.CSI_DISPATCH, ParserState.GROUND)
|
||||
addMany(range(0x30, 0x3c), ParserState.CSI_ENTRY, ParserAction.PARAM, ParserState.CSI_PARAM)
|
||||
addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.CSI_ENTRY, ParserAction.COLLECT, ParserState.CSI_PARAM)
|
||||
addMany(range(0x30, 0x3c), ParserState.CSI_PARAM, ParserAction.PARAM, ParserState.CSI_PARAM)
|
||||
addMany(range(0x40, 0x7f), ParserState.CSI_PARAM, ParserAction.CSI_DISPATCH, ParserState.GROUND)
|
||||
addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.CSI_PARAM, ParserAction.IGNORE, ParserState.CSI_IGNORE)
|
||||
addMany(range(0x20, 0x40), ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE)
|
||||
add(0x7f, ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE)
|
||||
addMany(range(0x40, 0x7f), ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.GROUND)
|
||||
addMany(range(0x20, 0x30), ParserState.CSI_ENTRY, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE)
|
||||
addMany(range(0x20, 0x30), ParserState.CSI_INTERMEDIATE, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE)
|
||||
addMany(range(0x30, 0x40), ParserState.CSI_INTERMEDIATE, ParserAction.IGNORE, ParserState.CSI_IGNORE)
|
||||
addMany(range(0x40, 0x7f), ParserState.CSI_INTERMEDIATE, ParserAction.CSI_DISPATCH, ParserState.GROUND)
|
||||
addMany(range(0x20, 0x30), ParserState.CSI_PARAM, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE)
|
||||
# esc_intermediate
|
||||
addMany(range(0x20, 0x30), ParserState.ESCAPE, ParserAction.COLLECT, ParserState.ESCAPE_INTERMEDIATE)
|
||||
addMany(range(0x20, 0x30), ParserState.ESCAPE_INTERMEDIATE, ParserAction.COLLECT, ParserState.ESCAPE_INTERMEDIATE)
|
||||
addMany(range(0x30, 0x7f), ParserState.ESCAPE_INTERMEDIATE, ParserAction.ESC_DISPATCH, ParserState.GROUND)
|
||||
addMany(range(0x30, 0x50), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND)
|
||||
addMany(range(0x51, 0x58), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND)
|
||||
addMany([0x59, 0x5a, 0x5c], ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND)
|
||||
addMany(range(0x60, 0x7f), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);
|
||||
|
||||
# dcs entry
|
||||
add(0x50, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.DCS_ENTRY)
|
||||
addMany(EXECUTABLES, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY)
|
||||
add(0x7f, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY)
|
||||
addMany(range(0x1c, 0x20), ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY)
|
||||
addMany(range(0x20, 0x30), ParserState.DCS_ENTRY, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE)
|
||||
addMany(range(0x30, 0x3c), ParserState.DCS_ENTRY, ParserAction.PARAM, ParserState.DCS_PARAM)
|
||||
addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.DCS_ENTRY, ParserAction.COLLECT, ParserState.DCS_PARAM)
|
||||
addMany(EXECUTABLES, ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE)
|
||||
addMany(range(0x20, 0x80), ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE)
|
||||
addMany(range(0x1c, 0x20), ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE)
|
||||
addMany(EXECUTABLES, ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM)
|
||||
add(0x7f, ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM)
|
||||
addMany(range(0x1c, 0x20), ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM)
|
||||
addMany(range(0x30, 0x3c), ParserState.DCS_PARAM, ParserAction.PARAM, ParserState.DCS_PARAM)
|
||||
addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_IGNORE)
|
||||
addMany(range(0x20, 0x30), ParserState.DCS_PARAM, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE)
|
||||
addMany(EXECUTABLES, ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE)
|
||||
add(0x7f, ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE)
|
||||
addMany(range(0x1c, 0x20), ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE)
|
||||
addMany(range(0x20, 0x30), ParserState.DCS_INTERMEDIATE, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE)
|
||||
addMany(range(0x30, 0x40), ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_IGNORE)
|
||||
addMany(range(0x40, 0x7f), ParserState.DCS_INTERMEDIATE, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH)
|
||||
addMany(range(0x40, 0x7f), ParserState.DCS_PARAM, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH)
|
||||
addMany(range(0x40, 0x7f), ParserState.DCS_ENTRY, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH)
|
||||
addMany(EXECUTABLES, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH)
|
||||
addMany(PRINTABLES, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH)
|
||||
add(0x7f, ParserState.DCS_PASSTHROUGH, ParserAction.IGNORE, ParserState.DCS_PASSTHROUGH)
|
||||
addMany([0x1b, 0x9c, 0x18, 0x1a], ParserState.DCS_PASSTHROUGH, ParserAction.DCS_UNHOOK, ParserState.GROUND);
|
||||
|
||||
# special handling of unicode chars
|
||||
add(NON_ASCII_PRINTABLE, ParserState.GROUND, ParserAction.PRINT, ParserState.GROUND)
|
||||
add(NON_ASCII_PRINTABLE, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING)
|
||||
add(NON_ASCII_PRINTABLE, ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE)
|
||||
add(NON_ASCII_PRINTABLE, ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE)
|
||||
add(NON_ASCII_PRINTABLE, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH)
|
||||
|
||||
return table
|
Loading…
Add table
Add a link
Reference in a new issue