Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3395d051a9 | ||
|
|
31b8409120 | ||
|
|
3eca55a80d |
@@ -25,4 +25,4 @@ When writing benchmark instructions:
|
||||
## Notes
|
||||
|
||||
- Benchmarks run from built JS in `out-test/benchmark/*.benchmark.js`.
|
||||
- Keep `NODE_PATH=./out` (handled by the npm script).
|
||||
- Benchmark sources import compiled modules from `../../out/common/` and `../../out/browser/` (run `npm run build` first).
|
||||
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
# @license MIT
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
if [[ ! -f src/common/parser/wasm/transition_table.h ]]; then
|
||||
npm run build
|
||||
node bin/gen_parser_transition_table.mjs
|
||||
fi
|
||||
|
||||
WASM_DIR=src/common/parser/wasm
|
||||
OUT="$WASM_DIR/parser.wasm"
|
||||
|
||||
# Apple Clang (Xcode CLT) has no wasm32 target; prefer Homebrew LLVM when needed.
|
||||
wasm_clang_has_target() {
|
||||
"$1" --print-targets 2>/dev/null | grep -q 'wasm32'
|
||||
}
|
||||
|
||||
resolve_wasm_toolchain() {
|
||||
local clang_bin=clang
|
||||
if wasm_clang_has_target clang; then
|
||||
:
|
||||
else
|
||||
local llvm_prefix=""
|
||||
if command -v brew >/dev/null 2>&1; then
|
||||
llvm_prefix="$(brew --prefix llvm 2>/dev/null || true)"
|
||||
fi
|
||||
for prefix in "$llvm_prefix" /opt/homebrew/opt/llvm /usr/local/opt/llvm; do
|
||||
if [[ -n "$prefix" && -x "$prefix/bin/clang" ]] && wasm_clang_has_target "$prefix/bin/clang"; then
|
||||
clang_bin="$prefix/bin/clang"
|
||||
local lld_prefix=""
|
||||
if command -v brew >/dev/null 2>&1; then
|
||||
lld_prefix="$(brew --prefix lld 2>/dev/null || true)"
|
||||
fi
|
||||
for lld_dir in "$lld_prefix/bin" /opt/homebrew/opt/lld/bin /usr/local/opt/lld/bin; do
|
||||
if [[ -n "$lld_dir" && -x "$lld_dir/lld" ]]; then
|
||||
PATH="$lld_dir:$(dirname "$clang_bin"):$PATH"
|
||||
break
|
||||
fi
|
||||
done
|
||||
PATH="$(dirname "$clang_bin"):$PATH"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ! wasm_clang_has_target "$clang_bin"; then
|
||||
echo "error: no clang with wasm32 support found (macOS: brew install llvm lld)" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
WASM_CLANG="$clang_bin"
|
||||
}
|
||||
|
||||
resolve_wasm_toolchain
|
||||
|
||||
"$WASM_CLANG" --target=wasm32-unknown-unknown -O2 -nostdlib -fuse-ld=lld \
|
||||
-Wl,--no-entry \
|
||||
-Wl,--export-memory \
|
||||
-Wl,--export=reset \
|
||||
-Wl,--export=scan \
|
||||
-Wl,--export=probe_action \
|
||||
-Wl,--export=set_state \
|
||||
-Wl,--export=sync_params_from \
|
||||
-Wl,--export=export_params_to \
|
||||
-Wl,--export=get_params_len \
|
||||
-Wl,--export=get_subparams_len \
|
||||
-Wl,--export=get_subparams_ptr \
|
||||
-Wl,--export=get_subparams_idx_ptr \
|
||||
-Wl,--export=get_input_ptr \
|
||||
-Wl,--export=get_kinds_ptr \
|
||||
-Wl,--export=get_starts_ptr \
|
||||
-Wl,--export=get_lengths_ptr \
|
||||
-Wl,--export=get_aux_ptr \
|
||||
-Wl,--export=get_param_starts_ptr \
|
||||
-Wl,--export=get_param_counts_ptr \
|
||||
-Wl,--export=get_params_ptr \
|
||||
-Wl,--export=get_state_ptr \
|
||||
-Wl,--export=get_header_ptr \
|
||||
-Wl,--initial-memory=67108864 \
|
||||
-Wl,--max-memory=67108864 \
|
||||
"$WASM_DIR/parser.c" -o "$OUT"
|
||||
|
||||
node bin/embed_parser_wasm.mjs
|
||||
|
||||
echo "Built $OUT"
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { join, dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const root = join(__dirname, '..');
|
||||
const wasm = readFileSync(join(root, 'src/common/parser/wasm/parser.wasm'));
|
||||
const b64 = wasm.toString('base64');
|
||||
|
||||
const out = `/**
|
||||
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
/** Base64-encoded parser.wasm (generated by bin/build_parser_wasm.sh) */
|
||||
export const PARSER_WASM_BASE64 = '${b64}';\n`;
|
||||
|
||||
writeFileSync(join(root, 'src/common/parser/wasm/parser.wasm.embed.ts'), out);
|
||||
console.info(`Embedded parser.wasm (${wasm.length} bytes)`);
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
import { writeFileSync } from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, join } from 'path';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const root = join(__dirname, '..');
|
||||
|
||||
// Import compiled transition table
|
||||
const { VT500_TRANSITION_TABLE } = await import(join(root, 'out/common/parser/EscapeSequenceParser.js'));
|
||||
|
||||
const table = VT500_TRANSITION_TABLE.table;
|
||||
let out = '/* Auto-generated by bin/gen_parser_transition_table.mjs - do not edit */\n';
|
||||
out += `#ifndef PARSER_TRANSITION_TABLE_H\n#define PARSER_TRANSITION_TABLE_H\n\n`;
|
||||
out += `#include <stdint.h>\n\n`;
|
||||
out += `#define PARSER_TABLE_SIZE ${table.length}\n\n`;
|
||||
out += `static const uint16_t PARSER_TRANSITION_TABLE[PARSER_TABLE_SIZE] = {\n`;
|
||||
for (let i = 0; i < table.length; i++) {
|
||||
if (i % 16 === 0) out += ' ';
|
||||
out += `0x${table[i].toString(16)}`;
|
||||
out += i < table.length - 1 ? ', ' : '';
|
||||
if (i % 16 === 15) out += '\n';
|
||||
}
|
||||
if (table.length % 16 !== 0) out += '\n';
|
||||
out += `};\n\n#endif\n`;
|
||||
|
||||
const headerPath = join(root, 'src/common/parser/wasm/transition_table.h');
|
||||
writeFileSync(headerPath, out);
|
||||
console.info(`Wrote ${headerPath} (${table.length} entries)`);
|
||||
@@ -34,6 +34,7 @@
|
||||
"start": "node demo/start",
|
||||
"dev": "concurrently -k -p [{name}] -n tsc,esbuild,esbuild-demo-client,esbuild-demo-server,server -c blue,yellow,cyan,green,magenta \"npm:tsc-watch\" \"npm:esbuild-watch\" \"npm:esbuild-demo-client-watch\" \"npm:esbuild-demo-server-watch\" \"npm:start\"",
|
||||
"build": "npm run tsc",
|
||||
"build:parser-wasm": "bash bin/build_parser_wasm.sh",
|
||||
"watch": "npm run tsc-watch",
|
||||
"tsc": "tsgo -b ./tsconfig.all.json",
|
||||
"tsc-watch": "tsgo -b -w ./tsconfig.all.json --preserveWatchOutput",
|
||||
|
||||
@@ -77,10 +77,10 @@ class TestEscapeSequenceParser extends EscapeSequenceParser {
|
||||
public get realParams(): IParams {
|
||||
return this._params;
|
||||
}
|
||||
public get collect(): string {
|
||||
public get collectStr(): string {
|
||||
return this.identToString(this._collect);
|
||||
}
|
||||
public set collect(value: string) {
|
||||
public set collectStr(value: string) {
|
||||
this._collect = 0;
|
||||
for (let i = 0; i < value.length; ++i) {
|
||||
this._collect <<= 8;
|
||||
@@ -248,19 +248,19 @@ describe('EscapeSequenceParser', () => {
|
||||
assert.equal(parser.currentState, ParserState.GROUND);
|
||||
assert.equal(parser.osc, '');
|
||||
assert.deepEqual(parser.params, [0]);
|
||||
assert.equal(parser.collect, '');
|
||||
assert.equal(parser.collectStr, '');
|
||||
});
|
||||
it('reset states', () => {
|
||||
parser.currentState = 124;
|
||||
parser.osc = '#';
|
||||
parser.params = [123];
|
||||
parser.collect = '#';
|
||||
parser.collectStr = '#';
|
||||
|
||||
parser.reset();
|
||||
assert.equal(parser.currentState, ParserState.GROUND);
|
||||
assert.equal(parser.osc, '');
|
||||
assert.deepEqual(parser.params, [0]);
|
||||
assert.equal(parser.collect, '');
|
||||
assert.equal(parser.collectStr, '');
|
||||
});
|
||||
});
|
||||
describe('state transitions and actions', () => {
|
||||
@@ -327,11 +327,11 @@ describe('EscapeSequenceParser', () => {
|
||||
for (state in states) {
|
||||
parser.currentState = state;
|
||||
parser.params = [23];
|
||||
parser.collect = '#';
|
||||
parser.collectStr = '#';
|
||||
parse(parser, '\x1b');
|
||||
assert.equal(parser.currentState, ParserState.ESCAPE);
|
||||
assert.deepEqual(parser.params, [0]);
|
||||
assert.equal(parser.collect, '');
|
||||
assert.equal(parser.collectStr, '');
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -383,7 +383,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.ESCAPE_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -419,7 +419,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.ESCAPE_INTERMEDIATE;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.ESCAPE_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -442,21 +442,21 @@ describe('EscapeSequenceParser', () => {
|
||||
// C0
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parser.params = [123];
|
||||
parser.collect = '#';
|
||||
parser.collectStr = '#';
|
||||
parse(parser, '[');
|
||||
assert.equal(parser.currentState, ParserState.CSI_ENTRY);
|
||||
assert.deepEqual(parser.params, [0]);
|
||||
assert.equal(parser.collect, '');
|
||||
assert.equal(parser.collectStr, '');
|
||||
parser.reset();
|
||||
// C1
|
||||
for (state in states) {
|
||||
parser.currentState = state;
|
||||
parser.params = [123];
|
||||
parser.collect = '#';
|
||||
parser.collectStr = '#';
|
||||
parse(parser, '\x9b');
|
||||
assert.equal(parser.currentState, ParserState.CSI_ENTRY);
|
||||
assert.deepEqual(parser.params, [0]);
|
||||
assert.equal(parser.collect, '');
|
||||
assert.equal(parser.collectStr, '');
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -517,7 +517,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.CSI_PARAM);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -582,7 +582,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.CSI_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -593,7 +593,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.CSI_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -619,7 +619,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.CSI_INTERMEDIATE;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.CSI_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -848,7 +848,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.DCS_PARAM);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -930,7 +930,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.DCS_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -941,7 +941,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.DCS_PARAM;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.DCS_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -965,7 +965,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.DCS_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -976,7 +976,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parse(parser, '\x20' + chars[i]);
|
||||
assert.equal(parser.currentState, ParserState.DCS_IGNORE);
|
||||
assert.equal(parser.collect, '\x20');
|
||||
assert.equal(parser.collectStr, '\x20');
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -1079,7 +1079,7 @@ describe('EscapeSequenceParser', () => {
|
||||
parser.currentState = ParserState.APC_ENTRY;
|
||||
parse(parser, collect[i]);
|
||||
assert.equal(parser.currentState, ParserState.APC_INTERMEDIATE);
|
||||
assert.equal(parser.collect, collect[i]);
|
||||
assert.equal(parser.collectStr, collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -11,6 +11,8 @@ import { Params } from './Params';
|
||||
import { OscParser } from './OscParser';
|
||||
import { DcsParser } from './DcsParser';
|
||||
import { ApcParser } from './ApcParser';
|
||||
import { parseWithWasmScanner } from './EscapeSequenceParserWasm';
|
||||
import { WasmEscapeScanner } from './WasmEscapeScanner';
|
||||
|
||||
/**
|
||||
* VT commands done by the parser
|
||||
@@ -269,6 +271,9 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
protected _params: Params;
|
||||
protected _collect: number;
|
||||
|
||||
public get collect(): number { return this._collect; }
|
||||
public set collect(value: number) { this._collect = value; }
|
||||
|
||||
// handler lookup containers
|
||||
protected _printHandler: PrintHandlerType;
|
||||
protected _executeHandlers: { [flag: number]: ExecuteHandlerType };
|
||||
@@ -297,6 +302,15 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
chunkPos: 0
|
||||
};
|
||||
|
||||
protected _scanCache: {
|
||||
opIndex: number;
|
||||
stateBeforeScan?: number;
|
||||
inputOffset?: number;
|
||||
chunkStart?: number;
|
||||
scan?: import('./ScanTypes').ScanResult;
|
||||
data?: Uint32Array;
|
||||
} = { opIndex: 0 };
|
||||
|
||||
constructor(
|
||||
protected readonly _transitions: TransitionTable = VT500_TRANSITION_TABLE
|
||||
) {
|
||||
@@ -494,12 +508,20 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
*/
|
||||
public reset(): void {
|
||||
this.currentState = this.initialState;
|
||||
WasmEscapeScanner.initSync();
|
||||
WasmEscapeScanner.reset();
|
||||
this._oscParser.reset();
|
||||
this._dcsParser.reset();
|
||||
this._apcParser.reset();
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
this.precedingJoinState = 0;
|
||||
this._scanCache.opIndex = 0;
|
||||
this._scanCache.inputOffset = 0;
|
||||
this._scanCache.chunkStart = undefined;
|
||||
this._scanCache.scan = undefined;
|
||||
this._scanCache.data = undefined;
|
||||
this._scanCache.stateBeforeScan = undefined;
|
||||
// abort pending continuation from async handler
|
||||
// Here the RESET type indicates, that the next parse call will
|
||||
// ignore any saved stack, instead continues sync with next codepoint from GROUND
|
||||
@@ -572,363 +594,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
* ```
|
||||
*/
|
||||
public parse(data: Uint32Array, length: number, promiseResult?: boolean): void | Promise<boolean> {
|
||||
let code: number;
|
||||
let transition: number;
|
||||
let start = 0;
|
||||
let handlerResult: void | boolean | Promise<boolean>;
|
||||
|
||||
// resume from async handler
|
||||
if (this._parseStack.state) {
|
||||
// allow sync parser reset even in continuation mode
|
||||
// Note: can be used to recover parser from improper continuation error below
|
||||
if (this._parseStack.state === ParserStackType.RESET) {
|
||||
this._parseStack.state = ParserStackType.NONE;
|
||||
start = this._parseStack.chunkPos + 1; // continue with next codepoint in GROUND
|
||||
} else {
|
||||
if (promiseResult === undefined || this._parseStack.state === ParserStackType.FAIL) {
|
||||
/**
|
||||
* Reject further parsing on improper continuation after pausing. This is a really bad
|
||||
* condition with screwed up execution order and prolly messed up terminal state,
|
||||
* therefore we exit hard with an exception and reject any further parsing.
|
||||
*
|
||||
* Note: With `Terminal.write` usage this exception should never occur, as the top level
|
||||
* calls are guaranteed to handle async conditions properly. If you ever encounter this
|
||||
* exception in your terminal integration it indicates, that you injected data chunks to
|
||||
* `InputHandler.parse` or `EscapeSequenceParser.parse` synchronously without waiting for
|
||||
* continuation of a running async handler.
|
||||
*
|
||||
* It is possible to get rid of this error by calling `reset`. But dont rely on that, as
|
||||
* the pending async handler still might mess up the terminal later. Instead fix the
|
||||
* faulty async handling, so this error will not be thrown anymore.
|
||||
*/
|
||||
this._parseStack.state = ParserStackType.FAIL;
|
||||
throw new Error('improper continuation due to previous async handler, giving up parsing');
|
||||
}
|
||||
|
||||
// we have to resume the old handler loop if:
|
||||
// - return value of the promise was `false`
|
||||
// - handlers are not exhausted yet
|
||||
const handlers = this._parseStack.handlers;
|
||||
let handlerPos = this._parseStack.handlerPos - 1;
|
||||
switch (this._parseStack.state) {
|
||||
case ParserStackType.CSI:
|
||||
if (promiseResult === false && handlerPos > -1) {
|
||||
for (; handlerPos >= 0; handlerPos--) {
|
||||
handlerResult = (handlers as CsiHandlerType[])[handlerPos](this._params);
|
||||
if (handlerResult === true) {
|
||||
break;
|
||||
} else if (handlerResult instanceof Promise) {
|
||||
this._parseStack.handlerPos = handlerPos;
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._parseStack.handlers = [];
|
||||
break;
|
||||
case ParserStackType.ESC:
|
||||
if (promiseResult === false && handlerPos > -1) {
|
||||
for (; handlerPos >= 0; handlerPos--) {
|
||||
handlerResult = (handlers as EscHandlerType[])[handlerPos]();
|
||||
if (handlerResult === true) {
|
||||
break;
|
||||
} else if (handlerResult instanceof Promise) {
|
||||
this._parseStack.handlerPos = handlerPos;
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._parseStack.handlers = [];
|
||||
break;
|
||||
case ParserStackType.DCS:
|
||||
code = data[this._parseStack.chunkPos];
|
||||
handlerResult = this._dcsParser.unhook(code !== 0x18 && code !== 0x1a, promiseResult);
|
||||
if (handlerResult) {
|
||||
return handlerResult;
|
||||
}
|
||||
if (code === 0x1b) this._parseStack.transition |= ParserState.ESCAPE;
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
break;
|
||||
case ParserStackType.OSC:
|
||||
code = data[this._parseStack.chunkPos];
|
||||
handlerResult = this._oscParser.end(code !== 0x18 && code !== 0x1a, promiseResult);
|
||||
if (handlerResult) {
|
||||
return handlerResult;
|
||||
}
|
||||
if (code === 0x1b) this._parseStack.transition |= ParserState.ESCAPE;
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
break;
|
||||
case ParserStackType.APC:
|
||||
code = data[this._parseStack.chunkPos];
|
||||
handlerResult = this._apcParser.end(code !== 0x18 && code !== 0x1a, promiseResult);
|
||||
if (handlerResult) {
|
||||
return handlerResult;
|
||||
}
|
||||
if (code === 0x1b) this._parseStack.transition |= ParserState.ESCAPE;
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
break;
|
||||
}
|
||||
// cleanup before continuing with the main sync loop
|
||||
this._parseStack.state = ParserStackType.NONE;
|
||||
start = this._parseStack.chunkPos + 1;
|
||||
this.precedingJoinState = 0;
|
||||
this.currentState = this._parseStack.transition & TableAccess.TRANSITION_STATE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
// continue with main sync loop
|
||||
|
||||
// process input string
|
||||
for (let i = start; i < length; ++i) {
|
||||
code = data[i];
|
||||
|
||||
// EXE fast-path: common control bytes (0x00-0x17) in non-payload states
|
||||
if (code < 0x18 && this.currentState <= ParserState.CSI_IGNORE) {
|
||||
(this._executeHandlersArr[code] ?? this._executeHandlerFb)(code);
|
||||
this.precedingJoinState = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// CSI fast-path: collapse ESC [ into a single entry, parse params+final in a tight loop
|
||||
if (code === 0x1b
|
||||
&& this.currentState < ParserState.OSC_STRING
|
||||
&& i + 2 < length && data[i + 1] === 0x5b
|
||||
) {
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
let k = i + 2;
|
||||
let ch = data[k];
|
||||
if (ch >= 0x3c && ch <= 0x3f) {
|
||||
this._collect = ch;
|
||||
k++;
|
||||
}
|
||||
let csiDone = false;
|
||||
for (; k < length; k++) {
|
||||
ch = data[k];
|
||||
if (ch >= 0x30 && ch <= 0x39) {
|
||||
this._params.addDigit(ch - 48);
|
||||
} else if (ch === 0x3b) {
|
||||
this._params.addParam(0);
|
||||
} else if (ch === 0x3a) {
|
||||
this._params.addSubParam(-1);
|
||||
} else if (ch >= 0x40 && ch <= 0x7e) {
|
||||
const handlers = this._csiHandlers[this._collect << 8 | ch];
|
||||
let j = handlers ? handlers.length - 1 : -1;
|
||||
for (; j >= 0; j--) {
|
||||
handlerResult = handlers[j](this._params);
|
||||
if (handlerResult === true) {
|
||||
break;
|
||||
} else if (handlerResult instanceof Promise) {
|
||||
transition = ParserAction.CSI_DISPATCH << TableAccess.TRANSITION_ACTION_SHIFT | ParserState.GROUND;
|
||||
this._preserveStack(ParserStackType.CSI, handlers, j, transition, k);
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
if (j < 0) {
|
||||
this._csiHandlerFb(this._collect << 8 | ch, this._params);
|
||||
}
|
||||
this.precedingJoinState = 0;
|
||||
i = k;
|
||||
this.currentState = ParserState.GROUND;
|
||||
csiDone = true;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!csiDone) {
|
||||
i = k - 1;
|
||||
this.currentState = ParserState.CSI_PARAM;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// normal transition & action lookup
|
||||
transition = this._transitions.table[
|
||||
this.currentState << TableAccess.INDEX_STATE_SHIFT |
|
||||
(code < NON_ASCII_PRINTABLE ? code : NON_ASCII_PRINTABLE)
|
||||
];
|
||||
switch (transition >> TableAccess.TRANSITION_ACTION_SHIFT) {
|
||||
case ParserAction.PRINT:
|
||||
// Note: 0x20 (SP) is included, 0x7F (DEL) is excluded
|
||||
let c = i;
|
||||
const l4 = length - 4;
|
||||
while (c < l4
|
||||
&& data[++c] >= 0x20 && (data[c] <= 0x7e || data[c] >= NON_ASCII_PRINTABLE)
|
||||
&& data[++c] >= 0x20 && (data[c] <= 0x7e || data[c] >= NON_ASCII_PRINTABLE)
|
||||
&& data[++c] >= 0x20 && (data[c] <= 0x7e || data[c] >= NON_ASCII_PRINTABLE)
|
||||
&& data[++c] >= 0x20 && (data[c] <= 0x7e || data[c] >= NON_ASCII_PRINTABLE)
|
||||
) {}
|
||||
if (c >= l4) {
|
||||
while (c < length && data[c] >= 0x20 && (data[c] <= 0x7e || data[c] >= NON_ASCII_PRINTABLE)) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
this._printHandler(data, i, c);
|
||||
i = c - 1;
|
||||
break;
|
||||
case ParserAction.EXECUTE:
|
||||
if (this._executeHandlers[code]) this._executeHandlers[code]();
|
||||
else this._executeHandlerFb(code);
|
||||
this.precedingJoinState = 0;
|
||||
break;
|
||||
case ParserAction.IGNORE:
|
||||
break;
|
||||
case ParserAction.ERROR:
|
||||
const inject: IParsingState = this._errorHandler(
|
||||
{
|
||||
position: i,
|
||||
code,
|
||||
currentState: this.currentState,
|
||||
collect: this._collect,
|
||||
params: this._params,
|
||||
abort: false
|
||||
});
|
||||
if (inject.abort) return;
|
||||
// inject values: currently not implemented
|
||||
break;
|
||||
case ParserAction.CSI_DISPATCH:
|
||||
// Trigger CSI Handler
|
||||
const handlers = this._csiHandlers[this._collect << 8 | code];
|
||||
let j = handlers ? handlers.length - 1 : -1;
|
||||
for (; j >= 0; j--) {
|
||||
// true means success and to stop bubbling
|
||||
// a promise indicates an async handler that needs to finish before progressing
|
||||
handlerResult = handlers[j](this._params);
|
||||
if (handlerResult === true) {
|
||||
break;
|
||||
} else if (handlerResult instanceof Promise) {
|
||||
this._preserveStack(ParserStackType.CSI, handlers, j, transition, i);
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
if (j < 0) {
|
||||
this._csiHandlerFb(this._collect << 8 | code, this._params);
|
||||
}
|
||||
this.precedingJoinState = 0;
|
||||
break;
|
||||
case ParserAction.PARAM:
|
||||
// inner loop: digits (0x30 - 0x39) and ; (0x3b) and : (0x3a)
|
||||
do {
|
||||
switch (code) {
|
||||
case 0x3b:
|
||||
this._params.addParam(0); // ZDM
|
||||
break;
|
||||
case 0x3a:
|
||||
this._params.addSubParam(-1);
|
||||
break;
|
||||
default: // 0x30 - 0x39
|
||||
this._params.addDigit(code - 48);
|
||||
}
|
||||
} while (++i < length && (code = data[i]) > 0x2f && code < 0x3c);
|
||||
i--;
|
||||
break;
|
||||
case ParserAction.COLLECT:
|
||||
this._collect <<= 8;
|
||||
this._collect |= code;
|
||||
break;
|
||||
case ParserAction.ESC_DISPATCH:
|
||||
const handlersEsc = this._escHandlers[this._collect << 8 | code];
|
||||
let jj = handlersEsc ? handlersEsc.length - 1 : -1;
|
||||
for (; jj >= 0; jj--) {
|
||||
// true means success and to stop bubbling
|
||||
// a promise indicates an async handler that needs to finish before progressing
|
||||
handlerResult = handlersEsc[jj]();
|
||||
if (handlerResult === true) {
|
||||
break;
|
||||
} else if (handlerResult instanceof Promise) {
|
||||
this._preserveStack(ParserStackType.ESC, handlersEsc, jj, transition, i);
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
if (jj < 0) {
|
||||
this._escHandlerFb(this._collect << 8 | code);
|
||||
}
|
||||
this.precedingJoinState = 0;
|
||||
break;
|
||||
case ParserAction.CLEAR:
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
break;
|
||||
case ParserAction.DCS_HOOK:
|
||||
this._dcsParser.hook(this._collect << 8 | code, this._params);
|
||||
break;
|
||||
case 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 (let j = i + 1; ; ++j) {
|
||||
if (j >= length || (code = data[j]) === 0x18 || code === 0x1a || code === 0x1b || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {
|
||||
this._dcsParser.put(data, i, j);
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ParserAction.DCS_UNHOOK:
|
||||
handlerResult = this._dcsParser.unhook(code !== 0x18 && code !== 0x1a);
|
||||
if (handlerResult) {
|
||||
this._preserveStack(ParserStackType.DCS, [], 0, transition, i);
|
||||
return handlerResult;
|
||||
}
|
||||
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
this.precedingJoinState = 0;
|
||||
break;
|
||||
case ParserAction.OSC_START:
|
||||
this._oscParser.start();
|
||||
break;
|
||||
case ParserAction.OSC_PUT:
|
||||
// inner loop: 0x20 (SP) included, 0x7F (DEL) included
|
||||
for (let j = i + 1; ; j++) {
|
||||
if (j >= length || (code = data[j]) < 0x20 || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {
|
||||
this._oscParser.put(data, i, j);
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ParserAction.OSC_END:
|
||||
handlerResult = this._oscParser.end(code !== 0x18 && code !== 0x1a);
|
||||
if (handlerResult) {
|
||||
this._preserveStack(ParserStackType.OSC, [], 0, transition, i);
|
||||
return handlerResult;
|
||||
}
|
||||
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
this.precedingJoinState = 0;
|
||||
break;
|
||||
case ParserAction.APC_START:
|
||||
this._apcParser.start(this._collect << 8 | code);
|
||||
break;
|
||||
case ParserAction.APC_PUT:
|
||||
// inner loop - exit APC_PUT: 0x18, 0x1a, 0x1b, 0x9c
|
||||
// allowed: 00/08 .. 00/13, 02/00 .. 07/14 + NON_ASCII_PRINTABLE
|
||||
for (let j = i + 1; ; ++j) {
|
||||
if (j < length && (
|
||||
(data[j] >= 0x20 && data[j] < 0x7f) || (data[j] >= 0x08 && data[j] < 0x0e) || data[j] >= NON_ASCII_PRINTABLE
|
||||
)) continue;
|
||||
this._apcParser.put(data, i, j);
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ParserAction.APC_END:
|
||||
handlerResult = this._apcParser.end(code !== 0x18 && code !== 0x1a);
|
||||
if (handlerResult) {
|
||||
this._preserveStack(ParserStackType.APC, [], 0, transition, i);
|
||||
return handlerResult;
|
||||
}
|
||||
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
||||
this._params.resetZdm();
|
||||
this._collect = 0;
|
||||
this.precedingJoinState = 0;
|
||||
break;
|
||||
}
|
||||
this.currentState = transition & TableAccess.TRANSITION_STATE_MASK;
|
||||
}
|
||||
return parseWithWasmScanner(this as unknown as import('./EscapeSequenceParserWasm').IWasmParseHost, data, length, promiseResult, this._scanCache);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
/**
|
||||
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ParserState } from './Constants';
|
||||
import { Params } from './Params';
|
||||
import { Op, ScanResult } from './ScanTypes';
|
||||
import { WasmEscapeScanner } from './WasmEscapeScanner';
|
||||
import {
|
||||
CsiHandlerType,
|
||||
EscHandlerType,
|
||||
IParams,
|
||||
IParsingState,
|
||||
IParserStackState,
|
||||
ParserStackType,
|
||||
ResumableHandlersType
|
||||
} from './Types';
|
||||
|
||||
export interface IWasmParseHost {
|
||||
currentState: number;
|
||||
collect: number;
|
||||
precedingJoinState: number;
|
||||
readonly _params: Params;
|
||||
readonly _parseStack: IParserStackState;
|
||||
readonly _csiHandlers: { [ident: number]: CsiHandlerType[] | undefined };
|
||||
readonly _escHandlers: { [ident: number]: EscHandlerType[] | undefined };
|
||||
readonly _executeHandlers: { [flag: number]: (() => void) | undefined };
|
||||
readonly _executeHandlersArr: Array<((code: number) => void) | undefined>;
|
||||
_csiHandlerFb(ident: number, params: IParams): void;
|
||||
_escHandlerFb(ident: number): void;
|
||||
_executeHandlerFb(code: number): void;
|
||||
_printHandler(data: Uint32Array, start: number, end: number): void;
|
||||
_oscParser: { start(): void; put(data: Uint32Array, start: number, end: number): void; end(success: boolean, promiseResult?: boolean): void | Promise<boolean> };
|
||||
_dcsParser: { hook(ident: number, params: IParams): void; put(data: Uint32Array, start: number, end: number): void; unhook(success: boolean, promiseResult?: boolean): void | Promise<boolean> };
|
||||
_apcParser: { start(ident: number): void; put(data: Uint32Array, start: number, end: number): void; end(success: boolean, promiseResult?: boolean): void | Promise<boolean> };
|
||||
_preserveStack(state: ParserStackType, handlers: ResumableHandlersType, handlerPos: number, transition: number, chunkPos: number): void;
|
||||
_errorHandler(state: IParsingState): IParsingState;
|
||||
}
|
||||
|
||||
let wasmReady = false;
|
||||
|
||||
function ensureWasm(): void {
|
||||
if (!wasmReady) {
|
||||
WasmEscapeScanner.initSync();
|
||||
wasmReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
function loadParams(host: IWasmParseHost, scan: ScanResult, opIndex: number): void {
|
||||
const start = scan.paramStarts[opIndex] ?? 0;
|
||||
const count = scan.paramCounts[opIndex] ?? 0;
|
||||
if (count === 0) {
|
||||
host._params.resetZdm();
|
||||
return;
|
||||
}
|
||||
let idx = start;
|
||||
host._params.resetZdm();
|
||||
for (let p = 0; p < count; p++) {
|
||||
const main = scan.params[idx++] | 0;
|
||||
if (p === 0) {
|
||||
host._params.params[0] = main;
|
||||
host._params.length = 1;
|
||||
} else {
|
||||
host._params.addParam(main);
|
||||
}
|
||||
while (idx < scan.params.length && (scan.params[idx] & 0x80000000) !== 0) {
|
||||
const sv = scan.params[idx++] & 0x7FFFFFFF;
|
||||
host._params.addSubParam(sv === 0x7FFFFFFF ? -1 : sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** True when a chunked WASM scan of `data` is still in progress (e.g. nested parse during print). */
|
||||
function isActiveWasmParse(scanCache: IWasmScanCache, data: Uint32Array, length: number): boolean {
|
||||
return scanCache.data === data
|
||||
&& (scanCache.inputOffset ?? 0) < length
|
||||
&& (scanCache.scan !== undefined || scanCache.chunkStart !== undefined);
|
||||
}
|
||||
|
||||
export function parseWithWasmScanner(
|
||||
host: IWasmParseHost,
|
||||
data: Uint32Array,
|
||||
length: number,
|
||||
promiseResult: boolean | undefined,
|
||||
scanCache: IWasmScanCache
|
||||
): void | Promise<boolean> {
|
||||
ensureWasm();
|
||||
|
||||
// Resume async handler dispatch without rescanning
|
||||
if (host._parseStack.state) {
|
||||
return resumeWasmParse(host, data, length, promiseResult, scanCache);
|
||||
}
|
||||
|
||||
if (!isActiveWasmParse(scanCache, data, length)) {
|
||||
scanCache.stateBeforeScan = host.currentState;
|
||||
scanCache.inputOffset = 0;
|
||||
scanCache.scan = undefined;
|
||||
scanCache.opIndex = 0;
|
||||
scanCache.data = undefined;
|
||||
scanCache.chunkStart = undefined;
|
||||
}
|
||||
return runWasmScanChunks(host, data, length, promiseResult, scanCache);
|
||||
}
|
||||
|
||||
interface IWasmScanCache {
|
||||
scan?: ScanResult;
|
||||
data?: Uint32Array;
|
||||
opIndex: number;
|
||||
stateBeforeScan?: number;
|
||||
inputOffset?: number;
|
||||
chunkStart?: number;
|
||||
}
|
||||
|
||||
function runWasmScanChunks(
|
||||
host: IWasmParseHost,
|
||||
data: Uint32Array,
|
||||
length: number,
|
||||
promiseResult: boolean | undefined,
|
||||
scanCache: IWasmScanCache
|
||||
): void | Promise<boolean> {
|
||||
let pos = scanCache.inputOffset ?? 0;
|
||||
const stateBeforeScan = scanCache.stateBeforeScan ?? host.currentState;
|
||||
|
||||
while (pos < length) {
|
||||
if (!scanCache.scan || scanCache.data !== data || scanCache.chunkStart !== pos) {
|
||||
WasmEscapeScanner.syncParserState(host.currentState, host.collect, host._params);
|
||||
const scan = WasmEscapeScanner.scan(data, length, pos);
|
||||
scanCache.scan = scan;
|
||||
scanCache.data = data;
|
||||
scanCache.chunkStart = pos;
|
||||
scanCache.opIndex = 0;
|
||||
host.currentState = WasmEscapeScanner.currentState;
|
||||
host.collect = WasmEscapeScanner.collect;
|
||||
}
|
||||
|
||||
const scan = scanCache.scan;
|
||||
if (!scan) {
|
||||
throw new Error('Wasm parser scan cache missing during chunked parse');
|
||||
}
|
||||
|
||||
const result = dispatchScanOps(host, data, scan, scanCache.opIndex, scanCache, promiseResult, stateBeforeScan);
|
||||
if (result instanceof Promise) {
|
||||
scanCache.inputOffset = pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
const nextOffset = scan.nextOffset;
|
||||
if (nextOffset <= pos) {
|
||||
throw new Error(`Wasm parser scan did not advance (stuck at input offset ${pos})`);
|
||||
}
|
||||
pos = nextOffset;
|
||||
scanCache.inputOffset = pos;
|
||||
scanCache.scan = undefined;
|
||||
scanCache.opIndex = 0;
|
||||
}
|
||||
|
||||
scanCache.inputOffset = length;
|
||||
scanCache.scan = undefined;
|
||||
scanCache.data = undefined;
|
||||
scanCache.chunkStart = undefined;
|
||||
}
|
||||
|
||||
function resumeWasmParse(
|
||||
host: IWasmParseHost,
|
||||
data: Uint32Array,
|
||||
length: number,
|
||||
promiseResult: boolean | undefined,
|
||||
scanCache: IWasmScanCache
|
||||
): void | Promise<boolean> {
|
||||
if (host._parseStack.state === ParserStackType.RESET) {
|
||||
host._parseStack.state = ParserStackType.NONE;
|
||||
scanCache.opIndex = host._parseStack.chunkPos + 1;
|
||||
host._parseStack.chunkPos = 0;
|
||||
if (!scanCache.scan || scanCache.data !== data) {
|
||||
return parseWithWasmScanner(host, data, length, promiseResult, scanCache);
|
||||
}
|
||||
return runWasmScanChunks(host, data, length, promiseResult, scanCache);
|
||||
}
|
||||
|
||||
if (promiseResult === undefined || host._parseStack.state === ParserStackType.FAIL) {
|
||||
host._parseStack.state = ParserStackType.FAIL;
|
||||
throw new Error('improper continuation due to previous async handler, giving up parsing');
|
||||
}
|
||||
|
||||
const handlers = host._parseStack.handlers;
|
||||
let handlerPos = host._parseStack.handlerPos - 1;
|
||||
let handlerResult: void | boolean | Promise<boolean>;
|
||||
const scan = scanCache.scan;
|
||||
const opIndex = scanCache.opIndex;
|
||||
|
||||
if (!scan) {
|
||||
throw new Error('missing scan cache on wasm parser resume');
|
||||
}
|
||||
|
||||
switch (host._parseStack.state) {
|
||||
case ParserStackType.CSI:
|
||||
if (promiseResult === false && handlerPos > -1) {
|
||||
for (; handlerPos >= 0; handlerPos--) {
|
||||
handlerResult = (handlers as CsiHandlerType[])[handlerPos](host._params);
|
||||
if (handlerResult === true) break;
|
||||
if (handlerResult instanceof Promise) {
|
||||
host._parseStack.handlerPos = handlerPos;
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
host._parseStack.handlers = [];
|
||||
scanCache.opIndex = opIndex + 1;
|
||||
break;
|
||||
case ParserStackType.ESC:
|
||||
if (promiseResult === false && handlerPos > -1) {
|
||||
for (; handlerPos >= 0; handlerPos--) {
|
||||
handlerResult = (handlers as EscHandlerType[])[handlerPos]();
|
||||
if (handlerResult === true) break;
|
||||
if (handlerResult instanceof Promise) {
|
||||
host._parseStack.handlerPos = handlerPos;
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
host._parseStack.handlers = [];
|
||||
scanCache.opIndex = opIndex + 1;
|
||||
break;
|
||||
case ParserStackType.DCS: {
|
||||
const code = data[host._parseStack.chunkPos];
|
||||
handlerResult = host._dcsParser.unhook(code !== 0x18 && code !== 0x1a, promiseResult);
|
||||
if (handlerResult) return handlerResult;
|
||||
if (code === 0x1b) host.currentState = ParserState.ESCAPE;
|
||||
host._params.resetZdm();
|
||||
host.collect = 0;
|
||||
scanCache.opIndex = opIndex + 1;
|
||||
break;
|
||||
}
|
||||
case ParserStackType.OSC: {
|
||||
const code = data[host._parseStack.chunkPos];
|
||||
handlerResult = host._oscParser.end(code !== 0x18 && code !== 0x1a, promiseResult);
|
||||
if (handlerResult) return handlerResult;
|
||||
if (code === 0x1b) host.currentState = ParserState.ESCAPE;
|
||||
host._params.resetZdm();
|
||||
host.collect = 0;
|
||||
scanCache.opIndex = opIndex + 1;
|
||||
break;
|
||||
}
|
||||
case ParserStackType.APC: {
|
||||
const code = data[host._parseStack.chunkPos];
|
||||
handlerResult = host._apcParser.end(code !== 0x18 && code !== 0x1a, promiseResult);
|
||||
if (handlerResult) return handlerResult;
|
||||
if (code === 0x1b) host.currentState = ParserState.ESCAPE;
|
||||
host._params.resetZdm();
|
||||
host.collect = 0;
|
||||
scanCache.opIndex = opIndex + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
host._parseStack.state = ParserStackType.NONE;
|
||||
host.precedingJoinState = 0;
|
||||
return runWasmScanChunks(host, data, length, promiseResult, scanCache);
|
||||
}
|
||||
|
||||
function dispatchScanOps(
|
||||
host: IWasmParseHost,
|
||||
data: Uint32Array,
|
||||
scan: ScanResult,
|
||||
fromOp: number,
|
||||
scanCache: IWasmScanCache,
|
||||
promiseResult: boolean | undefined,
|
||||
stateBeforeScan: number
|
||||
): void | Promise<boolean> {
|
||||
let handlerResult: void | boolean | Promise<boolean>;
|
||||
|
||||
for (let o = fromOp; o < scan.opCount; o++) {
|
||||
scanCache.opIndex = o;
|
||||
const kind = scan.kinds[o];
|
||||
const start = scan.starts[o];
|
||||
const len = scan.lengths[o];
|
||||
const aux = scan.aux[o];
|
||||
const chunkPos = kind === Op.Csi ? len : start;
|
||||
|
||||
switch (kind) {
|
||||
case Op.Print:
|
||||
host._printHandler(data, start, start + len);
|
||||
break;
|
||||
case Op.Execute: {
|
||||
const code = aux;
|
||||
const count = len > 0 ? len : 1;
|
||||
for (let n = 0; n < count; n++) {
|
||||
if (code < 0x18) {
|
||||
const exe = host._executeHandlersArr[code];
|
||||
if (exe) exe(code);
|
||||
else host._executeHandlerFb(code);
|
||||
} else if (host._executeHandlers[code]) {
|
||||
host._executeHandlers[code]!();
|
||||
} else {
|
||||
host._executeHandlerFb(code);
|
||||
}
|
||||
}
|
||||
host.precedingJoinState = 0;
|
||||
break;
|
||||
}
|
||||
case Op.Csi: {
|
||||
host.collect = aux >> 8;
|
||||
loadParams(host, scan, o);
|
||||
const handlers = host._csiHandlers[aux];
|
||||
let j = handlers ? handlers.length - 1 : -1;
|
||||
for (; j >= 0; j--) {
|
||||
handlerResult = handlers;
|
||||
if (handlerResult === true) break;
|
||||
if (handlerResult instanceof Promise) {
|
||||
host._preserveStack(ParserStackType.CSI, handlers!, j, 0, chunkPos);
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
if (j < 0) host._csiHandlerFb(aux, host._params);
|
||||
host.precedingJoinState = 0;
|
||||
break;
|
||||
}
|
||||
case Op.Esc: {
|
||||
host.collect = aux >> 8;
|
||||
loadParams(host, scan, o);
|
||||
const handlersEsc = host._escHandlers[aux];
|
||||
const escCount = len > 0 ? len : 1;
|
||||
escLoop: for (let rep = 0; rep < escCount; rep++) {
|
||||
let jj = handlersEsc ? handlersEsc.length - 1 : -1;
|
||||
for (; jj >= 0; jj--) {
|
||||
handlerResult = handlersEsc![jj]();
|
||||
if (handlerResult === true) continue escLoop;
|
||||
if (handlerResult instanceof Promise) {
|
||||
host._preserveStack(ParserStackType.ESC, handlersEsc!, jj, 0, chunkPos);
|
||||
return handlerResult;
|
||||
}
|
||||
}
|
||||
if (jj < 0) host._escHandlerFb(aux);
|
||||
}
|
||||
host.precedingJoinState = 0;
|
||||
break;
|
||||
}
|
||||
case Op.OscStart:
|
||||
host._oscParser.start();
|
||||
break;
|
||||
case Op.OscPut:
|
||||
if (len > 0) host._oscParser.put(data, start, start + len);
|
||||
break;
|
||||
case Op.OscEnd: {
|
||||
const term = aux;
|
||||
handlerResult = host._oscParser.end(term !== 0x18 && term !== 0x1a);
|
||||
if (handlerResult) {
|
||||
host._preserveStack(ParserStackType.OSC, [], 0, 0, start);
|
||||
return handlerResult;
|
||||
}
|
||||
if (term === 0x1b) host.currentState = ParserState.ESCAPE;
|
||||
host._params.resetZdm();
|
||||
host.collect = 0;
|
||||
host.precedingJoinState = 0;
|
||||
break;
|
||||
}
|
||||
case Op.DcsHook: {
|
||||
host.collect = aux >> 8;
|
||||
loadParams(host, scan, o);
|
||||
host._dcsParser.hook(aux, host._params);
|
||||
break;
|
||||
}
|
||||
case Op.DcsPut:
|
||||
if (len > 0) host._dcsParser.put(data, start, start + len);
|
||||
break;
|
||||
case Op.DcsUnhook: {
|
||||
const term = aux;
|
||||
handlerResult = host._dcsParser.unhook(term !== 0x18 && term !== 0x1a);
|
||||
if (handlerResult) {
|
||||
host._preserveStack(ParserStackType.DCS, [], 0, 0, start);
|
||||
return handlerResult;
|
||||
}
|
||||
host._params.resetZdm();
|
||||
host.collect = 0;
|
||||
host.precedingJoinState = 0;
|
||||
break;
|
||||
}
|
||||
case Op.ApcStart:
|
||||
host._apcParser.start(aux);
|
||||
break;
|
||||
case Op.ApcPut:
|
||||
if (len > 0) host._apcParser.put(data, start, start + len);
|
||||
break;
|
||||
case Op.ApcEnd: {
|
||||
const term = aux;
|
||||
handlerResult = host._apcParser.end(term !== 0x18 && term !== 0x1a);
|
||||
if (handlerResult) {
|
||||
host._preserveStack(ParserStackType.APC, [], 0, 0, start);
|
||||
return handlerResult;
|
||||
}
|
||||
host._params.resetZdm();
|
||||
host.collect = 0;
|
||||
host.precedingJoinState = 0;
|
||||
break;
|
||||
}
|
||||
case Op.Error: {
|
||||
WasmEscapeScanner.exportParamsTo(host._params);
|
||||
const inject = host._errorHandler({
|
||||
position: start,
|
||||
code: aux & 0xFFFF,
|
||||
currentState: aux >> 16,
|
||||
collect: WasmEscapeScanner.collect,
|
||||
params: host._params,
|
||||
abort: false
|
||||
});
|
||||
if (inject.abort) return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scanCache.opIndex = scan.opCount;
|
||||
host.currentState = WasmEscapeScanner.currentState;
|
||||
host.collect = WasmEscapeScanner.collect;
|
||||
WasmEscapeScanner.exportParamsTo(host._params);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
export const Op = {
|
||||
Print: 0,
|
||||
Execute: 1,
|
||||
Esc: 2,
|
||||
Csi: 3,
|
||||
Osc: 4,
|
||||
Dcs: 5,
|
||||
Apc: 6,
|
||||
DcsHook: 7,
|
||||
DcsPut: 8,
|
||||
DcsUnhook: 9,
|
||||
OscStart: 10,
|
||||
OscPut: 11,
|
||||
OscEnd: 12,
|
||||
ApcStart: 13,
|
||||
ApcPut: 14,
|
||||
ApcEnd: 15,
|
||||
Error: 16
|
||||
} as const;
|
||||
|
||||
export type OpKind = typeof Op[keyof typeof Op];
|
||||
|
||||
export type ScanResult = {
|
||||
kinds: Uint8Array;
|
||||
starts: Uint32Array;
|
||||
lengths: Uint32Array;
|
||||
aux: Uint32Array;
|
||||
params: Uint32Array;
|
||||
paramStarts: Uint32Array;
|
||||
paramCounts: Uint16Array;
|
||||
opCount: number;
|
||||
nextOffset: number;
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { StringToUtf32 } from '../input/TextDecoder';
|
||||
import { Op } from './ScanTypes';
|
||||
import { WasmEscapeScanner } from './WasmEscapeScanner';
|
||||
|
||||
describe('WasmEscapeScanner', () => {
|
||||
before(() => {
|
||||
WasmEscapeScanner.initSync();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
WasmEscapeScanner.reset();
|
||||
});
|
||||
|
||||
it('scans hello with SGR sequences', () => {
|
||||
const input = 'hello\x1b[31mred\x1b[0m';
|
||||
const data = new Uint32Array(input.length);
|
||||
const len = new StringToUtf32().decode(input, data);
|
||||
const scan = WasmEscapeScanner.scan(data, len);
|
||||
|
||||
assert.equal(scan.opCount, 4);
|
||||
assert.deepEqual(Array.from(scan.kinds), [Op.Print, Op.Csi, Op.Print, Op.Csi]);
|
||||
assert.deepEqual(Array.from(scan.starts), [0, 0, 10, 1]);
|
||||
// CSI/ESC: lengths hold final-byte index; print ops use run length
|
||||
assert.deepEqual(Array.from(scan.lengths), [5, 9, 3, 16]);
|
||||
assert.deepEqual(Array.from(scan.aux), [0, 'm'.charCodeAt(0), 0, 'm'.charCodeAt(0)]);
|
||||
assert.deepEqual(Array.from(scan.paramStarts), [0, 0, 0, 1]);
|
||||
assert.deepEqual(Array.from(scan.paramCounts), [0, 1, 0, 1]);
|
||||
assert.deepEqual(Array.from(scan.params), [31, 0]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Params } from './Params';
|
||||
import { Op, ScanResult } from './ScanTypes';
|
||||
import { PARSER_WASM_BASE64 } from './wasm/parser.wasm.embed';
|
||||
|
||||
export { Op };
|
||||
|
||||
const WASM_IMPORTS = {
|
||||
env: {
|
||||
memory: new WebAssembly.Memory({ initial: 1024, maximum: 1024 })
|
||||
}
|
||||
};
|
||||
|
||||
let wasmModule: WebAssembly.Instance | undefined;
|
||||
let wasmExports: {
|
||||
memory: WebAssembly.Memory;
|
||||
reset: () => void;
|
||||
scan: (offset: number, length: number) => number;
|
||||
set_state: (state: number, collect: number) => void;
|
||||
get_input_ptr: () => number;
|
||||
get_kinds_ptr: () => number;
|
||||
get_starts_ptr: () => number;
|
||||
get_lengths_ptr: () => number;
|
||||
get_aux_ptr: () => number;
|
||||
get_param_starts_ptr: () => number;
|
||||
get_param_counts_ptr: () => number;
|
||||
get_params_ptr: () => number;
|
||||
get_state_ptr: () => number;
|
||||
get_header_ptr: () => number;
|
||||
sync_params_from: (srcPtr: number, len: number) => void;
|
||||
export_params_to: (dstPtr: number, maxLen: number) => void;
|
||||
get_params_len: () => number;
|
||||
get_subparams_len: () => number;
|
||||
get_subparams_ptr: () => number;
|
||||
get_subparams_idx_ptr: () => number;
|
||||
};
|
||||
|
||||
async function initWasm(): Promise<void> {
|
||||
if (wasmModule) return;
|
||||
const bytes = Uint8Array.from(atob(PARSER_WASM_BASE64), c => c.charCodeAt(0));
|
||||
const mod = await WebAssembly.instantiate(bytes, WASM_IMPORTS);
|
||||
wasmModule = mod.instance;
|
||||
wasmExports = wasmModule.exports as typeof wasmExports;
|
||||
}
|
||||
|
||||
function ensureWasm(): typeof wasmExports {
|
||||
if (!wasmExports) {
|
||||
throw new Error('WasmEscapeScanner not initialized. Call WasmEscapeScanner.init() first.');
|
||||
}
|
||||
return wasmExports;
|
||||
}
|
||||
|
||||
export class WasmEscapeScanner {
|
||||
private static _initPromise: Promise<void> | undefined;
|
||||
private static _syncReady = false;
|
||||
|
||||
public static init(): Promise<void> {
|
||||
if (!this._initPromise) {
|
||||
this._initPromise = initWasm().then(() => {
|
||||
this._syncReady = true;
|
||||
wasmExports.reset();
|
||||
});
|
||||
}
|
||||
return this._initPromise;
|
||||
}
|
||||
|
||||
/** Synchronous init for unit tests (Node supports sync instantiate). */
|
||||
public static initSync(): void {
|
||||
if (this._syncReady) return;
|
||||
const binary = globalThis.atob(PARSER_WASM_BASE64);
|
||||
const bytes = new Uint8Array(binary.length);
|
||||
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
||||
const mod = new WebAssembly.Module(bytes);
|
||||
wasmModule = new WebAssembly.Instance(mod, WASM_IMPORTS);
|
||||
wasmExports = wasmModule.exports as typeof wasmExports;
|
||||
wasmExports.reset();
|
||||
this._syncReady = true;
|
||||
}
|
||||
|
||||
public static reset(): void {
|
||||
ensureWasm().reset();
|
||||
}
|
||||
|
||||
public static get currentState(): number {
|
||||
const mem = new Uint32Array(ensureWasm().memory.buffer);
|
||||
const statePtr = ensureWasm().get_state_ptr() >> 2;
|
||||
return mem[statePtr];
|
||||
}
|
||||
|
||||
public static set currentState(value: number) {
|
||||
const ex = ensureWasm();
|
||||
const mem = new Uint32Array(ex.memory.buffer);
|
||||
const statePtr = ex.get_state_ptr() >> 2;
|
||||
ex.set_state(value, mem[statePtr + 1]);
|
||||
}
|
||||
|
||||
public static get collect(): number {
|
||||
const mem = new Uint32Array(ensureWasm().memory.buffer);
|
||||
return mem[(ensureWasm().get_state_ptr() >> 2) + 1];
|
||||
}
|
||||
|
||||
public static set collect(value: number) {
|
||||
const ex = ensureWasm();
|
||||
ex.set_state(memState(ex), value);
|
||||
}
|
||||
|
||||
public static syncParserState(currentState: number, collect: number, params: Params): void {
|
||||
const ex = ensureWasm();
|
||||
ex.set_state(currentState, collect);
|
||||
if (params.length === 0) {
|
||||
ex.sync_params_from(ex.get_params_ptr(), 0);
|
||||
return;
|
||||
}
|
||||
const mem = ex.memory.buffer;
|
||||
const paramsPtr = ex.get_params_ptr();
|
||||
const view = new Int32Array(mem, paramsPtr, params.length);
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
view[i] = params.params[i];
|
||||
}
|
||||
ex.sync_params_from(paramsPtr, params.length);
|
||||
}
|
||||
|
||||
public static exportParamsTo(params: Params): void {
|
||||
const ex = ensureWasm();
|
||||
const len = ex.get_params_len();
|
||||
params.reset();
|
||||
if (len === 0) {
|
||||
params.resetZdm();
|
||||
return;
|
||||
}
|
||||
const mem = ex.memory.buffer;
|
||||
const dstPtr = ex.get_params_ptr();
|
||||
ex.export_params_to(dstPtr, len);
|
||||
const pView = new Int32Array(mem, dstPtr, len);
|
||||
const subLen = ex.get_subparams_len();
|
||||
const subView = subLen > 0 ? new Int32Array(mem, ex.get_subparams_ptr(), subLen) : undefined;
|
||||
const idxView = new Uint16Array(mem, ex.get_subparams_idx_ptr(), len);
|
||||
|
||||
params.resetZdm();
|
||||
params.params[0] = pView[0];
|
||||
params.length = 1;
|
||||
if (subView && len > 0) {
|
||||
const start0 = idxView[0] >> 8;
|
||||
const end0 = idxView[0] & 0xFF;
|
||||
for (let k = start0; k < end0; k++) {
|
||||
params.addSubParam(subView[k]);
|
||||
}
|
||||
}
|
||||
for (let i = 1; i < len; i++) {
|
||||
params.addParam(pView[i]);
|
||||
if (subView) {
|
||||
const start = idxView[i] >> 8;
|
||||
const end = idxView[i] & 0xFF;
|
||||
for (let k = start; k < end; k++) {
|
||||
params.addSubParam(subView[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static scan(data: Uint32Array, length: number, offset = 0): ScanResult {
|
||||
const ex = ensureWasm();
|
||||
const inputPtr = ex.get_input_ptr();
|
||||
const mem = ex.memory.buffer;
|
||||
const inputView = new Uint32Array(mem, inputPtr, length);
|
||||
inputView.set(data.subarray(0, length));
|
||||
|
||||
const opCount = ex.scan(offset, length);
|
||||
if (opCount < 0) {
|
||||
throw new Error('Wasm parser op buffer overflow');
|
||||
}
|
||||
|
||||
const count = opCount;
|
||||
const kinds = new Uint8Array(mem, ex.get_kinds_ptr(), count);
|
||||
const starts = new Uint32Array(mem, ex.get_starts_ptr(), count);
|
||||
const lengths = new Uint32Array(mem, ex.get_lengths_ptr(), count);
|
||||
const aux = new Uint32Array(mem, ex.get_aux_ptr(), count);
|
||||
const paramStarts = new Uint32Array(mem, ex.get_param_starts_ptr(), count);
|
||||
const paramCounts = new Uint16Array(mem, ex.get_param_counts_ptr(), count);
|
||||
|
||||
const headerView = new Uint32Array(mem, ex.get_header_ptr(), 4);
|
||||
const paramsLen = headerView[2];
|
||||
const nextOffset = headerView[3];
|
||||
|
||||
const params = new Uint32Array(mem, ex.get_params_ptr(), paramsLen);
|
||||
|
||||
return {
|
||||
kinds: kinds.slice(),
|
||||
starts: starts.slice(),
|
||||
lengths: lengths.slice(),
|
||||
aux: aux.slice(),
|
||||
params: params.slice(),
|
||||
paramStarts: paramStarts.slice(),
|
||||
paramCounts: paramCounts.slice(),
|
||||
opCount: count,
|
||||
nextOffset
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function memState(ex: typeof wasmExports): number {
|
||||
const mem = new Uint32Array(ex.memory.buffer);
|
||||
return mem[ex.get_state_ptr() >> 2];
|
||||
}
|
||||
@@ -0,0 +1,505 @@
|
||||
/* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT */
|
||||
|
||||
#include "parser.h"
|
||||
#include "transition_table.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/* Static transition table is linked at 65536; scratch must sit above it. */
|
||||
#define MEM_BASE 65536
|
||||
#define PARSER_TABLE_BYTE_SIZE (PARSER_TABLE_SIZE * sizeof(uint16_t))
|
||||
#define MEM_STATE (((MEM_BASE + PARSER_TABLE_BYTE_SIZE) + 255u) & ~255u)
|
||||
/* ParserWasmState is ~2.3KB; keep header and op buffers past it */
|
||||
#define MEM_HEADER (MEM_STATE + 2048)
|
||||
#define MEM_KINDS (MEM_HEADER + 64)
|
||||
#define MEM_STARTS (MEM_KINDS + PARSER_MAX_OPS)
|
||||
#define MEM_LENGTHS (MEM_STARTS + PARSER_MAX_OPS * 4)
|
||||
#define MEM_AUX (MEM_LENGTHS + PARSER_MAX_OPS * 4)
|
||||
#define MEM_PARAM_STARTS (MEM_AUX + PARSER_MAX_OPS * 4)
|
||||
#define MEM_PARAM_COUNTS (MEM_PARAM_STARTS + PARSER_MAX_OPS * 4)
|
||||
#define MEM_PARAMS_ARENA (MEM_PARAM_COUNTS + PARSER_MAX_OPS * 2) /* uint16 param counts */
|
||||
#define MEM_INPUT_BASE (MEM_PARAMS_ARENA + PARSER_MAX_PARAMS * 4)
|
||||
|
||||
static ParserWasmState *state(void) { return (ParserWasmState *)(uintptr_t)MEM_STATE; }
|
||||
static ParserScanHeader *header(void) { return (ParserScanHeader *)(uintptr_t)MEM_HEADER; }
|
||||
static uint8_t *kinds(void) { return (uint8_t *)(uintptr_t)MEM_KINDS; }
|
||||
static uint32_t *starts(void) { return (uint32_t *)(uintptr_t)MEM_STARTS; }
|
||||
static uint32_t *lengths(void) { return (uint32_t *)(uintptr_t)MEM_LENGTHS; }
|
||||
static uint32_t *aux(void) { return (uint32_t *)(uintptr_t)MEM_AUX; }
|
||||
static uint32_t *param_starts(void) { return (uint32_t *)(uintptr_t)MEM_PARAM_STARTS; }
|
||||
static uint16_t *param_counts(void) { return (uint16_t *)(uintptr_t)MEM_PARAM_COUNTS; }
|
||||
static int32_t *params_arena(void) { return (int32_t *)(uintptr_t)MEM_PARAMS_ARENA; }
|
||||
static uint32_t *input(void) { return (uint32_t *)(uintptr_t)MEM_INPUT_BASE; }
|
||||
|
||||
static uint32_t transition_lookup(uint32_t st, uint32_t code) {
|
||||
uint32_t idx = code < PARSER_NON_ASCII_PRINTABLE ? code : PARSER_NON_ASCII_PRINTABLE;
|
||||
return PARSER_TRANSITION_TABLE[st << PARSER_TABLE_INDEX_STATE_SHIFT | idx];
|
||||
}
|
||||
|
||||
static void params_reset_zdm(ParserWasmState *s) {
|
||||
s->params_len = 1;
|
||||
s->subparams_len = 0;
|
||||
s->reject_digits = 0;
|
||||
s->reject_sub_digits = 0;
|
||||
s->digit_is_sub = 0;
|
||||
s->subparams_idx[0] = 0;
|
||||
s->params[0] = 0;
|
||||
}
|
||||
|
||||
static void params_reset(ParserWasmState *s) {
|
||||
s->params_len = 0;
|
||||
s->subparams_len = 0;
|
||||
s->reject_digits = 0;
|
||||
s->reject_sub_digits = 0;
|
||||
s->digit_is_sub = 0;
|
||||
}
|
||||
|
||||
static void params_add_param(ParserWasmState *s, int32_t value) {
|
||||
s->digit_is_sub = 0;
|
||||
if (s->params_len >= PARSER_PARAMS_MAX_LEN) {
|
||||
s->reject_digits = 1;
|
||||
return;
|
||||
}
|
||||
s->subparams_idx[s->params_len] = (uint16_t)(s->subparams_len << 8 | s->subparams_len);
|
||||
if (value < 0) value = 0;
|
||||
if (value > 0x7FFFFFFF) value = 0x7FFFFFFF;
|
||||
s->params[s->params_len++] = value;
|
||||
}
|
||||
|
||||
static void params_add_subparam(ParserWasmState *s, int32_t value) {
|
||||
s->digit_is_sub = 1;
|
||||
if (!s->params_len) return;
|
||||
if (s->reject_digits || s->subparams_len >= PARSER_SUBPARAMS_MAX_LEN) {
|
||||
s->reject_sub_digits = 1;
|
||||
return;
|
||||
}
|
||||
if (value < 0) value = -1;
|
||||
if (value > 0x7FFFFFFF) value = 0x7FFFFFFF;
|
||||
s->subparams[s->subparams_len++] = value;
|
||||
s->subparams_idx[s->params_len - 1]++;
|
||||
}
|
||||
|
||||
static void params_add_digit(ParserWasmState *s, int32_t digit) {
|
||||
uint32_t len;
|
||||
if (s->reject_digits) return;
|
||||
len = s->digit_is_sub ? s->subparams_len : s->params_len;
|
||||
if (!len) return;
|
||||
if (s->digit_is_sub && s->reject_sub_digits) return;
|
||||
int32_t *store = s->digit_is_sub ? s->subparams : s->params;
|
||||
int32_t cur = store[len - 1];
|
||||
store[len - 1] = cur >= 0 ? (cur * 10 + digit > 0x7FFFFFFF ? 0x7FFFFFFF : cur * 10 + digit) : digit;
|
||||
}
|
||||
|
||||
static void copy_params_to_arena(uint32_t op_idx, ParserWasmState *s) {
|
||||
uint32_t start = header()->params_arena_len;
|
||||
param_starts()[op_idx] = start;
|
||||
param_counts()[op_idx] = (uint16_t)s->params_len;
|
||||
for (uint32_t i = 0; i < s->params_len; i++) {
|
||||
if (header()->params_arena_len >= PARSER_MAX_PARAMS) return;
|
||||
params_arena()[header()->params_arena_len++] = s->params[i];
|
||||
uint16_t idx = s->subparams_idx[i];
|
||||
uint32_t sub_start = idx >> 8;
|
||||
uint32_t sub_end = idx & 0xFF;
|
||||
for (uint32_t k = sub_start; k < sub_end; k++) {
|
||||
if (header()->params_arena_len >= PARSER_MAX_PARAMS) return;
|
||||
int32_t sv = s->subparams[k];
|
||||
uint32_t encoded = 0x80000000u | (uint32_t)(sv < 0 ? 0x7FFFFFFF : sv);
|
||||
params_arena()[header()->params_arena_len++] = encoded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int emit_op(uint8_t kind, uint32_t start, uint32_t length, uint32_t aux_val, ParserWasmState *s) {
|
||||
uint32_t idx = header()->op_count;
|
||||
if (idx > 0) {
|
||||
uint32_t prev = idx - 1;
|
||||
if (kind == OP_EXECUTE && kinds()[prev] == OP_EXECUTE && aux()[prev] == aux_val) {
|
||||
lengths()[prev]++;
|
||||
return (int)prev;
|
||||
}
|
||||
if (kind == OP_ESC && kinds()[prev] == OP_ESC && aux()[prev] == aux_val) {
|
||||
lengths()[prev]++;
|
||||
return (int)prev;
|
||||
}
|
||||
}
|
||||
if (idx >= PARSER_MAX_OPS) return -1;
|
||||
kinds()[idx] = kind;
|
||||
starts()[idx] = start;
|
||||
if ((kind == OP_EXECUTE || kind == OP_ESC) && length == 0) {
|
||||
lengths()[idx] = 1;
|
||||
} else {
|
||||
lengths()[idx] = length;
|
||||
}
|
||||
aux()[idx] = aux_val;
|
||||
if (kind == OP_CSI || kind == OP_DCS_HOOK) {
|
||||
uint32_t input_pos = start;
|
||||
copy_params_to_arena(idx, s);
|
||||
lengths()[idx] = input_pos;
|
||||
starts()[idx] = param_starts()[idx];
|
||||
} else if (kind == OP_ESC) {
|
||||
uint32_t input_pos = start;
|
||||
uint32_t repeat = lengths()[idx];
|
||||
copy_params_to_arena(idx, s);
|
||||
starts()[idx] = input_pos;
|
||||
lengths()[idx] = repeat;
|
||||
} else {
|
||||
param_starts()[idx] = 0;
|
||||
param_counts()[idx] = 0;
|
||||
}
|
||||
header()->op_count++;
|
||||
return (int)idx;
|
||||
}
|
||||
|
||||
static int is_printable(uint32_t code) {
|
||||
return (code >= 0x20 && code <= 0x7e) || code >= PARSER_NON_ASCII_PRINTABLE;
|
||||
}
|
||||
|
||||
__attribute__((export_name("reset")))
|
||||
void reset(void) {
|
||||
ParserWasmState *s = state();
|
||||
s->current_state = PARSER_STATE_GROUND;
|
||||
s->collect = 0;
|
||||
s->preceding_join_state = 0;
|
||||
s->osc_start = 0;
|
||||
s->dcs_start = 0;
|
||||
s->apc_start = 0;
|
||||
params_reset_zdm(s);
|
||||
header()->op_count = 0;
|
||||
header()->input_len = 0;
|
||||
header()->params_arena_len = 0;
|
||||
header()->scan_offset = 0;
|
||||
}
|
||||
|
||||
__attribute__((export_name("get_input_ptr")))
|
||||
uint32_t get_input_ptr(void) { return MEM_INPUT_BASE; }
|
||||
|
||||
__attribute__((export_name("get_kinds_ptr")))
|
||||
uint32_t get_kinds_ptr(void) { return MEM_KINDS; }
|
||||
|
||||
__attribute__((export_name("get_starts_ptr")))
|
||||
uint32_t get_starts_ptr(void) { return MEM_STARTS; }
|
||||
|
||||
__attribute__((export_name("get_lengths_ptr")))
|
||||
uint32_t get_lengths_ptr(void) { return MEM_LENGTHS; }
|
||||
|
||||
__attribute__((export_name("get_aux_ptr")))
|
||||
uint32_t get_aux_ptr(void) { return MEM_AUX; }
|
||||
|
||||
__attribute__((export_name("get_param_starts_ptr")))
|
||||
uint32_t get_param_starts_ptr(void) { return MEM_PARAM_STARTS; }
|
||||
|
||||
__attribute__((export_name("get_param_counts_ptr")))
|
||||
uint32_t get_param_counts_ptr(void) { return MEM_PARAM_COUNTS; }
|
||||
|
||||
__attribute__((export_name("get_params_ptr")))
|
||||
uint32_t get_params_ptr(void) { return MEM_PARAMS_ARENA; }
|
||||
|
||||
__attribute__((export_name("get_state_ptr")))
|
||||
uint32_t get_state_ptr(void) { return MEM_STATE; }
|
||||
|
||||
__attribute__((export_name("get_header_ptr")))
|
||||
uint32_t get_header_ptr(void) { return MEM_HEADER; }
|
||||
|
||||
__attribute__((export_name("set_state")))
|
||||
void set_state(uint32_t current_state, uint32_t collect) {
|
||||
state()->current_state = current_state;
|
||||
state()->collect = collect;
|
||||
}
|
||||
|
||||
__attribute__((export_name("export_params_to")))
|
||||
void export_params_to(uint32_t dst_ptr, uint32_t max_len) {
|
||||
ParserWasmState *s = state();
|
||||
int32_t *dst = (int32_t *)(uintptr_t)dst_ptr;
|
||||
uint32_t n = s->params_len < max_len ? s->params_len : max_len;
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
dst[i] = s->params[i];
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((export_name("get_params_len")))
|
||||
uint32_t get_params_len(void) {
|
||||
return state()->params_len;
|
||||
}
|
||||
|
||||
__attribute__((export_name("get_subparams_len")))
|
||||
uint32_t get_subparams_len(void) {
|
||||
return state()->subparams_len;
|
||||
}
|
||||
|
||||
__attribute__((export_name("get_subparams_ptr")))
|
||||
uint32_t get_subparams_ptr(void) {
|
||||
return (uint32_t)(uintptr_t)state()->subparams;
|
||||
}
|
||||
|
||||
__attribute__((export_name("get_subparams_idx_ptr")))
|
||||
uint32_t get_subparams_idx_ptr(void) {
|
||||
return (uint32_t)(uintptr_t)state()->subparams_idx;
|
||||
}
|
||||
|
||||
__attribute__((export_name("sync_params_from")))
|
||||
void sync_params_from(uint32_t src_ptr, uint32_t len) {
|
||||
ParserWasmState *s = state();
|
||||
const int32_t *src = (const int32_t *)(uintptr_t)src_ptr;
|
||||
s->params_len = len > PARSER_PARAMS_MAX_LEN ? PARSER_PARAMS_MAX_LEN : len;
|
||||
for (uint32_t i = 0; i < s->params_len; i++) {
|
||||
s->params[i] = src[i];
|
||||
}
|
||||
s->subparams_len = 0;
|
||||
s->reject_digits = 0;
|
||||
s->reject_sub_digits = 0;
|
||||
s->digit_is_sub = 0;
|
||||
}
|
||||
|
||||
__attribute__((export_name("probe_action")))
|
||||
uint32_t probe_action(uint32_t state_id, uint32_t code) {
|
||||
uint32_t tr = transition_lookup(state_id, code);
|
||||
return tr >> PARSER_TABLE_ACTION_SHIFT;
|
||||
}
|
||||
|
||||
static int emit_or_stop(uint8_t kind, uint32_t start, uint32_t length, uint32_t aux_val, ParserWasmState *s, uint32_t stop_at) {
|
||||
if (emit_op(kind, start, length, aux_val, s) < 0) {
|
||||
header()->scan_offset = stop_at;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((export_name("scan")))
|
||||
int32_t scan(uint32_t offset, uint32_t length) {
|
||||
ParserWasmState *s = state();
|
||||
ParserScanHeader *h = header();
|
||||
h->op_count = 0;
|
||||
h->params_arena_len = 0;
|
||||
h->input_len = length;
|
||||
uint32_t i = offset;
|
||||
uint32_t code;
|
||||
uint32_t transition;
|
||||
uint32_t action;
|
||||
uint32_t print_start;
|
||||
|
||||
while (i < length) {
|
||||
code = input()[i];
|
||||
|
||||
if (code < 0x18 && s->current_state <= PARSER_STATE_CSI_PARAM + 2) {
|
||||
if (!emit_or_stop(OP_EXECUTE, i, 0, code, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->preceding_join_state = 0;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (code == 0x1b && s->current_state < PARSER_STATE_OSC_STRING && i + 2 < length && input()[i + 1] == 0x5b) {
|
||||
params_reset_zdm(s);
|
||||
s->collect = 0;
|
||||
uint32_t k = i + 2;
|
||||
uint32_t ch = input()[k];
|
||||
if (ch >= 0x3c && ch <= 0x3f) {
|
||||
s->collect = ch;
|
||||
k++;
|
||||
}
|
||||
int csi_done = 0;
|
||||
for (; k < length; k++) {
|
||||
ch = input()[k];
|
||||
if (ch >= 0x30 && ch <= 0x39) {
|
||||
params_add_digit(s, ch - 48);
|
||||
} else if (ch == 0x3b) {
|
||||
params_add_param(s, 0);
|
||||
} else if (ch == 0x3a) {
|
||||
params_add_subparam(s, -1);
|
||||
} else if (ch >= 0x40 && ch <= 0x7e) {
|
||||
uint32_t ident = (s->collect << 8) | ch;
|
||||
if (!emit_or_stop(OP_CSI, k, 0, ident, s, k)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->preceding_join_state = 0;
|
||||
i = k;
|
||||
s->current_state = PARSER_STATE_GROUND;
|
||||
csi_done = 1;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!csi_done) {
|
||||
i = k - 1;
|
||||
s->current_state = PARSER_STATE_CSI_PARAM;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
transition = transition_lookup(s->current_state, code);
|
||||
action = transition >> PARSER_TABLE_ACTION_SHIFT;
|
||||
{
|
||||
uint32_t next_state = transition & PARSER_TABLE_STATE_MASK;
|
||||
switch (action) {
|
||||
case 1: /* ERROR - report state before transition (matches TS parser) */
|
||||
if (!emit_or_stop(OP_ERROR, i, 0, (s->current_state << 16) | code, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->current_state = next_state;
|
||||
break;
|
||||
default:
|
||||
s->current_state = next_state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case PARSER_ACTION_PRINT: {
|
||||
print_start = i;
|
||||
uint32_t c = i;
|
||||
uint32_t l4 = length > 4 ? length - 4 : 0;
|
||||
while (c < l4 && is_printable(input()[c]) && is_printable(input()[c + 1]) &&
|
||||
is_printable(input()[c + 2]) && is_printable(input()[c + 3])) {
|
||||
c += 4;
|
||||
}
|
||||
while (c < length && is_printable(input()[c])) c++;
|
||||
if (!emit_or_stop(OP_PRINT, print_start, c - print_start, 0, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
i = c - 1;
|
||||
break;
|
||||
}
|
||||
case PARSER_ACTION_EXECUTE:
|
||||
if (!emit_or_stop(OP_EXECUTE, i, 0, code, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->preceding_join_state = 0;
|
||||
break;
|
||||
case PARSER_ACTION_IGNORE:
|
||||
break;
|
||||
case 1: /* ERROR - handled above */
|
||||
break;
|
||||
case PARSER_ACTION_CSI_DISPATCH: {
|
||||
uint32_t ident = (s->collect << 8) | code;
|
||||
if (!emit_or_stop(OP_CSI, i, 0, ident, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->preceding_join_state = 0;
|
||||
break;
|
||||
}
|
||||
case 8: /* PARAM */
|
||||
do {
|
||||
switch (code) {
|
||||
case 0x3b: params_add_param(s, 0); break;
|
||||
case 0x3a: params_add_subparam(s, -1); break;
|
||||
default: params_add_digit(s, code - 48); break;
|
||||
}
|
||||
} while (++i < length && (code = input()[i]) > 0x2f && code < 0x3c);
|
||||
i--;
|
||||
break;
|
||||
case 9: /* COLLECT */
|
||||
s->collect <<= 8;
|
||||
s->collect |= code;
|
||||
break;
|
||||
case PARSER_ACTION_ESC_DISPATCH: {
|
||||
uint32_t ident = (s->collect << 8) | code;
|
||||
if (!emit_or_stop(OP_ESC, i, 0, ident, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->preceding_join_state = 0;
|
||||
break;
|
||||
}
|
||||
case 11: /* CLEAR */
|
||||
params_reset_zdm(s);
|
||||
s->collect = 0;
|
||||
break;
|
||||
case 4: /* OSC_START */
|
||||
if (!emit_or_stop(OP_OSC_START, i, 0, 0, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->osc_start = i + 1;
|
||||
break;
|
||||
case 5: /* OSC_PUT */
|
||||
for (uint32_t j = i + 1; ; j++) {
|
||||
if (j >= length || (code = input()[j]) < 0x20 ||
|
||||
(code > 0x7f && code < PARSER_NON_ASCII_PRINTABLE)) {
|
||||
if (j > i && !emit_or_stop(OP_OSC_PUT, i, j - i, 0, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PARSER_ACTION_OSC_END: {
|
||||
if (!emit_or_stop(OP_OSC_END, i, 0, code, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->osc_term = code;
|
||||
if (code == 0x1b) s->current_state = PARSER_STATE_ESCAPE;
|
||||
params_reset_zdm(s);
|
||||
s->collect = 0;
|
||||
s->preceding_join_state = 0;
|
||||
break;
|
||||
}
|
||||
case 12: /* DCS_HOOK */
|
||||
s->dcs_hook_ident = (s->collect << 8) | code;
|
||||
if (!emit_or_stop(OP_DCS_HOOK, i, 0, s->dcs_hook_ident, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->dcs_start = i + 1;
|
||||
break;
|
||||
case 13: /* DCS_PUT */
|
||||
for (uint32_t j = i + 1; ; j++) {
|
||||
if (j >= length || (code = input()[j]) == 0x18 || code == 0x1a || code == 0x1b ||
|
||||
(code > 0x7f && code < PARSER_NON_ASCII_PRINTABLE)) {
|
||||
if (j > i && !emit_or_stop(OP_DCS_PUT, i, j - i, 0, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PARSER_ACTION_DCS_UNHOOK: {
|
||||
if (!emit_or_stop(OP_DCS_UNHOOK, i, 0, code, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
if (code == 0x1b) s->current_state = PARSER_STATE_ESCAPE;
|
||||
params_reset_zdm(s);
|
||||
s->collect = 0;
|
||||
s->preceding_join_state = 0;
|
||||
break;
|
||||
}
|
||||
case 15: /* APC_START */
|
||||
s->apc_hook_ident = (s->collect << 8) | code;
|
||||
if (!emit_or_stop(OP_APC_START, i, 0, s->apc_hook_ident, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
s->apc_start = i + 1;
|
||||
break;
|
||||
case 16: /* APC_PUT */
|
||||
for (uint32_t j = i + 1; ; j++) {
|
||||
if (j < length && (
|
||||
(input()[j] >= 0x20 && input()[j] < 0x7f) ||
|
||||
(input()[j] >= 0x08 && input()[j] < 0x0e) ||
|
||||
input()[j] >= PARSER_NON_ASCII_PRINTABLE
|
||||
)) continue;
|
||||
if (j > i && !emit_or_stop(OP_APC_PUT, i, j - i, 0, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PARSER_ACTION_APC_END: {
|
||||
if (!emit_or_stop(OP_APC_END, i, 0, code, s, i)) {
|
||||
return h->op_count > 0 ? (int32_t)h->op_count : -1;
|
||||
}
|
||||
if (code == 0x1b) s->current_state = PARSER_STATE_ESCAPE;
|
||||
params_reset_zdm(s);
|
||||
s->collect = 0;
|
||||
s->preceding_join_state = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
h->scan_offset = length;
|
||||
return (int32_t)h->op_count;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
#ifndef PARSER_WASM_H
|
||||
#define PARSER_WASM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PARSER_NON_ASCII_PRINTABLE 0xA0
|
||||
#define PARSER_TABLE_ACTION_SHIFT 8
|
||||
#define PARSER_TABLE_STATE_MASK 255
|
||||
#define PARSER_TABLE_INDEX_STATE_SHIFT 8
|
||||
|
||||
#define OP_PRINT 0
|
||||
#define OP_EXECUTE 1
|
||||
#define OP_ESC 2
|
||||
#define OP_CSI 3
|
||||
#define OP_OSC 4
|
||||
#define OP_DCS 5
|
||||
#define OP_APC 6
|
||||
#define OP_DCS_HOOK 7
|
||||
#define OP_DCS_PUT 8
|
||||
#define OP_DCS_UNHOOK 9
|
||||
#define OP_OSC_START 10
|
||||
#define OP_OSC_PUT 11
|
||||
#define OP_OSC_END 12
|
||||
#define OP_APC_START 13
|
||||
#define OP_APC_PUT 14
|
||||
#define OP_APC_END 15
|
||||
#define OP_ERROR 16
|
||||
|
||||
#define PARSER_STATE_GROUND 0
|
||||
#define PARSER_STATE_ESCAPE 1
|
||||
#define PARSER_STATE_OSC_STRING 8
|
||||
#define PARSER_STATE_DCS_PASSTHROUGH 13
|
||||
#define PARSER_STATE_APC_PASSTHROUGH 16
|
||||
#define PARSER_STATE_CSI_PARAM 4
|
||||
|
||||
#define PARSER_ACTION_IGNORE 0
|
||||
#define PARSER_ACTION_PRINT 2
|
||||
#define PARSER_ACTION_EXECUTE 3
|
||||
#define PARSER_ACTION_CSI_DISPATCH 7
|
||||
#define PARSER_ACTION_ESC_DISPATCH 10
|
||||
#define PARSER_ACTION_OSC_END 6
|
||||
#define PARSER_ACTION_DCS_UNHOOK 14
|
||||
#define PARSER_ACTION_APC_END 17
|
||||
|
||||
#define PARSER_MAX_OPS 4096
|
||||
#define PARSER_MAX_PARAMS 4096
|
||||
#define PARSER_PARAMS_MAX_LEN 32
|
||||
#define PARSER_SUBPARAMS_MAX_LEN 256
|
||||
|
||||
typedef struct {
|
||||
uint32_t current_state;
|
||||
uint32_t collect;
|
||||
uint32_t preceding_join_state;
|
||||
int32_t params[PARSER_PARAMS_MAX_LEN];
|
||||
uint32_t params_len;
|
||||
int32_t subparams[PARSER_SUBPARAMS_MAX_LEN];
|
||||
uint32_t subparams_len;
|
||||
uint16_t subparams_idx[PARSER_PARAMS_MAX_LEN];
|
||||
uint32_t reject_digits;
|
||||
uint32_t reject_sub_digits;
|
||||
uint32_t digit_is_sub;
|
||||
uint32_t osc_start;
|
||||
uint32_t dcs_start;
|
||||
uint32_t apc_start;
|
||||
uint32_t dcs_hook_ident;
|
||||
uint32_t apc_hook_ident;
|
||||
uint32_t osc_term;
|
||||
} ParserWasmState;
|
||||
|
||||
typedef struct {
|
||||
uint32_t op_count;
|
||||
uint32_t input_len;
|
||||
uint32_t params_arena_len;
|
||||
uint32_t scan_offset;
|
||||
} ParserScanHeader;
|
||||
|
||||
#endif
|
||||
Executable
BIN
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,279 @@
|
||||
/* Auto-generated by bin/gen_parser_transition_table.mjs - do not edit */
|
||||
#ifndef PARSER_TRANSITION_TABLE_H
|
||||
#define PARSER_TRANSITION_TABLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PARSER_TABLE_SIZE 4257
|
||||
|
||||
static const uint16_t PARSER_TRANSITION_TABLE[PARSER_TABLE_SIZE] = {
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0xb01, 0x300, 0x300, 0x300, 0x300,
|
||||
0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200,
|
||||
0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200,
|
||||
0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200,
|
||||
0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200,
|
||||
0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200,
|
||||
0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x100,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x200, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301,
|
||||
0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x300, 0x301, 0x300, 0xb01, 0x301, 0x301, 0x301, 0x301,
|
||||
0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00,
|
||||
0xb09, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0x7, 0xa00, 0xa00, 0xb03, 0xa00, 0x408, 0x7, 0xb0e,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0x1,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302,
|
||||
0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x302, 0x300, 0x302, 0x300, 0xb01, 0x302, 0x302, 0x302, 0x302,
|
||||
0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902, 0x902,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00,
|
||||
0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0xa00, 0x2,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303,
|
||||
0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x300, 0x303, 0x300, 0xb01, 0x303, 0x303, 0x303, 0x303,
|
||||
0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905,
|
||||
0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x904, 0x904, 0x904, 0x904,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x3,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304,
|
||||
0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x304, 0x300, 0x304, 0x300, 0xb01, 0x304, 0x304, 0x304, 0x304,
|
||||
0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905,
|
||||
0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x804, 0x6, 0x6, 0x6, 0x6,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x4,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305,
|
||||
0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x305, 0x300, 0x305, 0x300, 0xb01, 0x305, 0x305, 0x305, 0x305,
|
||||
0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905, 0x905,
|
||||
0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700,
|
||||
0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700, 0x5,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306,
|
||||
0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x306, 0x300, 0x306, 0x300, 0xb01, 0x306, 0x306, 0x306, 0x306,
|
||||
0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6,
|
||||
0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x6, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x300, 0x7, 0x300, 0xb01, 0x7, 0x7, 0x7, 0x7,
|
||||
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x600, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
|
||||
0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x600, 0x8, 0x600, 0x600, 0x8, 0x8, 0x8, 0x8,
|
||||
0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508,
|
||||
0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508,
|
||||
0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508,
|
||||
0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508,
|
||||
0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508,
|
||||
0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508, 0x508,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x600, 0x408, 0x7, 0xb0e,
|
||||
0x508, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9,
|
||||
0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x300, 0x9, 0x300, 0xb01, 0x9, 0x9, 0x9, 0x9,
|
||||
0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c,
|
||||
0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x90a, 0x90a, 0x90a, 0x90a,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0x9,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
|
||||
0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x300, 0xa, 0x300, 0xb01, 0xa, 0xa, 0xa, 0xa,
|
||||
0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c,
|
||||
0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0x80a, 0xb, 0xb, 0xb, 0xb,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xa,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0x300, 0xb, 0x300, 0xb01, 0xb, 0xb, 0xb, 0xb,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0xb, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc,
|
||||
0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0x300, 0xc, 0x300, 0xb01, 0xc, 0xc, 0xc, 0xc,
|
||||
0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c, 0x90c,
|
||||
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d,
|
||||
0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc0d, 0xc,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d,
|
||||
0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xe00, 0xd0d, 0xe00, 0xe00, 0xd0d, 0xd0d, 0xd0d, 0xd0d,
|
||||
0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d,
|
||||
0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d,
|
||||
0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d,
|
||||
0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d,
|
||||
0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d,
|
||||
0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd0d, 0xd,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0xe00, 0x408, 0x7, 0xb0e,
|
||||
0xd0d, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe,
|
||||
0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x300, 0xe, 0x300, 0xb01, 0xe, 0xe, 0xe, 0xe,
|
||||
0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xe,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
|
||||
0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x300, 0xf, 0x300, 0xb01, 0xf, 0xf, 0xf, 0xf,
|
||||
0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f, 0x90f,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10,
|
||||
0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf10, 0xf,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x0, 0x408, 0x7, 0xb0e,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1100, 0x10, 0x1100, 0x1100, 0x10, 0x10, 0x10, 0x10,
|
||||
0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010,
|
||||
0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010,
|
||||
0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010,
|
||||
0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010,
|
||||
0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010,
|
||||
0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x10,
|
||||
0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
0xb09, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x7, 0x300, 0x300, 0xb03, 0x1100, 0x408, 0x7, 0xb0e,
|
||||
0x1010
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
import { perfContext, before, RuntimeCase } from 'xterm-benchmark';
|
||||
import { DecorationService } from '../../src/common/services/DecorationService';
|
||||
import { MockLogService, MockBufferService, MockOptionsService } from '../../src/common/TestUtils.test';
|
||||
import { DecorationService } from '../../out/common/services/DecorationService';
|
||||
import { MockLogService, MockBufferService, MockOptionsService } from '../../out/common/TestUtils.test';
|
||||
const enum Constants {
|
||||
COLS = 80,
|
||||
ROWS = 30,
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
*/
|
||||
import { perfContext, before, beforeEach, ThroughputRuntimeCase } from 'xterm-benchmark';
|
||||
|
||||
import { EscapeSequenceParser } from '../../src/common/parser/EscapeSequenceParser';
|
||||
import { C0, C1 } from '../../src/common/data/EscapeSequences';
|
||||
import { IDcsHandler, IOscHandler, IApcHandler, IParams } from '../../src/common/parser/Types';
|
||||
import { OscHandler } from '../../src/common/parser/OscParser';
|
||||
import { DcsHandler } from '../../src/common/parser/DcsParser';
|
||||
import { ApcHandler } from '../../src/common/parser/ApcParser';
|
||||
import { EscapeSequenceParser } from '../../out/common/parser/EscapeSequenceParser';
|
||||
import { C0, C1 } from '../../out/common/data/EscapeSequences';
|
||||
import { IDcsHandler, IOscHandler, IApcHandler, IParams } from '../../out/common/parser/Types';
|
||||
import { OscHandler } from '../../out/common/parser/OscParser';
|
||||
import { DcsHandler } from '../../out/common/parser/DcsParser';
|
||||
import { ApcHandler } from '../../out/common/parser/ApcParser';
|
||||
|
||||
const SIZE = 5000000;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { perfContext, before, RuntimeCase } from 'xterm-benchmark';
|
||||
import { Emitter } from '../../src/common/Event';
|
||||
import { Emitter } from '../../out/common/Event';
|
||||
|
||||
const ITERATIONS = 1_000_000;
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark';
|
||||
|
||||
import { spawn } from 'node-pty';
|
||||
import { Utf8ToUtf32, stringFromCodePoint } from '../../src/common/input/TextDecoder';
|
||||
import { CoreBrowserTerminal } from '../../src/browser/CoreBrowserTerminal';
|
||||
import { Utf8ToUtf32, stringFromCodePoint } from '../../out/common/input/TextDecoder';
|
||||
import { CoreBrowserTerminal } from '../../out/browser/CoreBrowserTerminal';
|
||||
|
||||
perfContext('Terminal: ls -lR /usr/lib', () => {
|
||||
let content = '';
|
||||
|
||||
Reference in New Issue
Block a user