Bug Summary

File:/rootdir/_build/../src/parser.cc
Warning:line 1389, column 9
This statement is never executed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name parser.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/_build -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -I src/libbte-2.91.so.0.6500.0.p -I src -I ../src -I . -I .. -I src/bte -I ../src/bte -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/pango-1.0 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/uuid -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/p11-kit-1 -I /usr/include/ctk-3.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -D _FILE_OFFSET_BITS=64 -D G_LOG_DOMAIN="BTE" -D LOCALEDIR="/usr/local/share/locale" -D BTE_DISABLE_DEPRECATION_WARNINGS -D BTE_COMPILATION -U PARSER_INCLUDE_NOP -D CDK_VERSION_MIN_REQUIRED=(G_ENCODE_VERSION(3,18)) -D CDK_VERSION_MAX_ALLOWED=(G_ENCODE_VERSION(3,20)) -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/x86_64-linux-gnu/c++/12 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-address-of-packed-member -Wno-missing-field-initializers -Wno-packed -Wno-switch-enum -Wno-unused-parameter -Wwrite-strings -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/rootdir/_build -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-13-131739-9867-1 -x c++ ../src/parser.cc
1/*
2 * Copyright © 2015 David Herrmann <dh.herrmann@gmail.com>
3 * Copyright © 2017, 2018 Christian Persch
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20
21#include "parser.hh"
22
23#include <cstdio>
24#include <cstring>
25#include <cstdlib>
26#include <cerrno>
27
28#include <glib.h>
29
30#include "parser-charset-tables.hh"
31
32#ifdef PARSER_INCLUDE_NOP
33#define _BTE_NOQ(...) _BTE_SEQ(__VA_ARGS__)
34#else
35#define _BTE_NOQ(...)
36#endif
37
38/*
39 * Terminal Parser
40 * This file contains a bunch of UTF-8 helpers and the main ctlseq-parser. The
41 * parser is a simple state-machine that correctly parses all CSI, DCS, OSC, ST
42 * control sequences and generic escape sequences.
43 * The parser itself does not perform any actions but lets the caller react to
44 * detected sequences.
45 *
46 * This parser is mostly DEC VT100+ compatible; known differences are:
47 *
48 * * DEC only recognises up to 16 parameters; bte up to 32 (and that can be easily
49 * extended)
50 *
51 * * DEC's parameter values range is 0..16384; bte supports 0..65535 (16-bit range).
52 *
53 * * When the number of parameter exceeds that number, DEC executes the function
54 * with these parameters, ignoring the excessive parameters; bte ignores the
55 * whole function instead.
56 *
57 * * DEC ignores CSI sequences with colon-separated parameters; bte implements colon-
58 * separated parameters as subparameters (this is an extension taken from ITU-T T.416).
59 *
60 * * DEC executes format effector controls in CSI, OSC, DCS sequences as if the
61 * control was received before the control sequence; bte only does this for CSI
62 * sequences and ignores all controls except ESC and BEL in OSC control strings,
63 * and passes all controls except ESC through to the control string in DCS sequences.
64 *
65 * * DEC only allows ST (either C0 or C1) to terminate OSC strings; bte allows
66 * OSC to be terminated by BEL (this is a deprecated xterm extension).
67 *
68 * * DEC parses ESC Z as DECID, a deprecated function equivalent to DA1; bte
69 * implements ECMA-48's SCI (single character introducer) instead.
70 */
71
72/*
73 * Command Parser
74 * The ctl-seq parser "bte_parser" only detects whole sequences, it does not
75 * detect the specific command. Once a sequence is parsed, the command-parsers
76 * are used to figure out their meaning.
77 */
78
79/*
80 * Intermediates (and, for CSI/DCS, the optional parameter character) are
81 * stored efficiently in an unsigned int. Intermediates can be 2/00..2/15,
82 * plus one value for 'no intermediate'; together that fits into 5 bits.
83 * Parameter character can be 'no parameter character', or one from
84 * 3/12..3/15; that fits into 3 bits.
85 *
86 * In @seq.intermediates, the nth intermediates is stored with shift n * 5,
87 * plus (for CSI/DCS) an additional shift of 3 for the parameter character
88 * which is stored at bits 0..2.
89 *
90 * BTE_SEQ_PARAMETER(u) extracts the parameter character
91 * of a CSI or DCS sequence
92 * BTE_SEQ_REMOVE_PARAMETER(u) extracts the intermediates
93 * of a CSI or DCS sequence
94 * BTE_SEQ_INTERMEDIATE(u) extracts the first intermediate from an
95 * intermediates value (for CSI/DCS, that must be without parameter
96 * character, see BTE_SEQ_REMOVE_PARAMETER)
97 * BTE_SEQ_REMOVE_INTERMEDIATE(u) extracts the remaining intermediates
98 * after the first one; use BTE_SEQ_INTERMEDIATE on its return value
99 * to extract the 2nd intermediate, and so on
100 */
101
102#define BTE_SEQ_PARAMETER_BITS(3) (3)
103#define BTE_SEQ_INTERMEDIATE_BITS(5) (5)
104#define BTE_SEQ_INTERMEDIATE_MASK((1U << (5)) - 1U) ((1U << BTE_SEQ_INTERMEDIATE_BITS(5)) - 1U)
105#define BTE_SEQ_PARAMETER_MASK((1U << (3)) - 1U) ((1U << BTE_SEQ_PARAMETER_BITS(3)) - 1U)
106#define BTE_SEQ_PARAMETER(u)((u) & ((1U << (3)) - 1U)) ((u) & BTE_SEQ_PARAMETER_MASK((1U << (3)) - 1U))
107#define BTE_SEQ_REMOVE_PARAMETER(u)((u) >> (3)) ((u) >> BTE_SEQ_PARAMETER_BITS(3))
108#define BTE_SEQ_INTERMEDIATE(u)((u) & ((1U << (5)) - 1U)) ((u) & BTE_SEQ_INTERMEDIATE_MASK((1U << (5)) - 1U))
109#define BTE_SEQ_REMOVE_INTERMEDIATE(u)((u) >> (5)) ((u) >> BTE_SEQ_INTERMEDIATE_BITS(5))
110#define BTE_MAKE_CHARSET(c,s)((c) | ((s) << (16))) ((c) | ((s) << BTE_CHARSET_SLOT_OFFSET(16)))
111
112/*
113 * _BTE_SEQ_CODE_ESC(final, intermediates):
114 *
115 * Make a value combining the final character and the intermediates,
116 * to be used to match a sequence against known sequences.
117 *
118 * Since this is only used with NONE or HASH as first intermediate,
119 * we can reduce the size of the lookup table by slashing the least
120 * significant bit off.
121 *
122 * Final characters is 3/0..7/14, needing 7 bits.
123 */
124#define _BTE_SEQ_CODE_ESC(f,i)(((f) - 0x30) | ((i) >> 1) << 7) (((f) - 0x30) | ((i) >> 1) << 7)
125
126/*
127 * _BTE_SEQ_CODE_COMBINE(parameter, intermediates)
128 *
129 * Combines intermediates and the parameter character into one
130 * value to be used when matching a sequence against known sequences.
131 */
132#define _BTE_SEQ_CODE_COMBINE(p,i)((p) | ((i) << (3))) ((p) | ((i) << BTE_SEQ_PARAMETER_BITS(3)))
133
134/*
135 * _BTE_SEQ_CODE(final, intermediates):
136 *
137 * Make a value combining the final character and the intermediates,
138 * to be used to match a sequence against known sequences. Used for
139 * CSI and DCS sequences; use _BTE_SEQ_CODE_COMBINE to combine
140 * parameter and intermediates into one to pass as 2nd argument here.
141 *
142 * Final character is 4/0..7/14, needing 6 bits.
143 */
144#define _BTE_SEQ_CODE(f,i)(((f) - 0x40) | ((i) << 6)) (((f) - 0x40) | ((i) << 6))
145
146/*
147 * @introducer: either a C1 control, or the final in the equivalent ESC F sequence
148 * @terminator: either a C1 control, or the final in the equivalent ESC F sequence
149 *
150 * Checks whether the OSC/DCS @introducer and the ST @terminator
151 * are from the same control set, i.e. both C0 or both C1.
152 *
153 * For OSC, this check allows C0 OSC with BEL-as-ST to pass, too.
154 */
155static inline bool
156parser_check_matching_controls(uint32_t introducer,
157 uint32_t terminator)
158{
159 return ((introducer ^ terminator) & 0x80) == 0;
160}
161
162static unsigned int
163bte_parse_host_control(bte_seq_t const* seq)
164{
165 switch (seq->terminator) {
166#define _BTE_SEQ(cmd,type,f,pi,ni,i0) case f: return BTE_CMD_##cmd;
167#include "parser-c01.hh"
168#undef _BTE_SEQ
169 default: return BTE_CMD_NONE;
170 }
171}
172
173static unsigned int
174bte_parse_charset_94(uint32_t raw,
175 unsigned int intermediates)
176{
177 assert (raw >= 0x30 && raw < 0x7f)(static_cast <bool> (raw >= 0x30 && raw <
0x7f) ? void (0) : __assert_fail ("raw >= 0x30 && raw < 0x7f"
, "../src/parser.cc", 177, __extension__ __PRETTY_FUNCTION__)
)
;
178
179 unsigned int remaining_intermediates = BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5));
180
181 switch (BTE_SEQ_INTERMEDIATE(intermediates)((intermediates) & ((1U << (5)) - 1U))) {
182 case BTE_SEQ_INTERMEDIATE_NONE:
183 if (remaining_intermediates == 0 &&
184 raw < (0x30 + G_N_ELEMENTS(charset_graphic_94)(sizeof (charset_graphic_94) / sizeof ((charset_graphic_94)[0
]))
))
185 return charset_graphic_94[raw - 0x30];
186 break;
187
188 case BTE_SEQ_INTERMEDIATE_SPACE:
189 return BTE_CHARSET_DRCS;
190
191 case BTE_SEQ_INTERMEDIATE_BANG:
192 if (remaining_intermediates == 0 &&
193 raw >= 0x40 && (raw < 0x40 + G_N_ELEMENTS(charset_graphic_94_with_2_1)(sizeof (charset_graphic_94_with_2_1) / sizeof ((charset_graphic_94_with_2_1
)[0]))
))
194 return charset_graphic_94_with_2_1[raw - 0x40];
195 break;
196
197 case BTE_SEQ_INTERMEDIATE_DQUOTE:
198 if (remaining_intermediates == 0 &&
199 raw < (0x30 + G_N_ELEMENTS(charset_graphic_94_with_2_2)(sizeof (charset_graphic_94_with_2_2) / sizeof ((charset_graphic_94_with_2_2
)[0]))
))
200 return charset_graphic_94_with_2_2[raw - 0x30];
201 break;
202
203 case BTE_SEQ_INTERMEDIATE_HASH:
204 case BTE_SEQ_INTERMEDIATE_CASH:
205 break;
206
207 case BTE_SEQ_INTERMEDIATE_PERCENT:
208 if (remaining_intermediates == 0 &&
209 raw < (0x30 + G_N_ELEMENTS(charset_graphic_94_with_2_5)(sizeof (charset_graphic_94_with_2_5) / sizeof ((charset_graphic_94_with_2_5
)[0]))
))
210 return charset_graphic_94_with_2_5[raw - 0x30];
211 break;
212
213 case BTE_SEQ_INTERMEDIATE_AND:
214 if (remaining_intermediates == 0 &&
215 raw < (0x30 + G_N_ELEMENTS(charset_graphic_94_with_2_6)(sizeof (charset_graphic_94_with_2_6) / sizeof ((charset_graphic_94_with_2_6
)[0]))
))
216 return charset_graphic_94_with_2_6[raw - 0x30];
217 break;
218 }
219
220 return BTE_CHARSET_NONE;
221}
222
223static unsigned int
224bte_parse_charset_94_n(uint32_t raw,
225 unsigned int intermediates)
226{
227 assert (raw >= 0x30 && raw < 0x7f)(static_cast <bool> (raw >= 0x30 && raw <
0x7f) ? void (0) : __assert_fail ("raw >= 0x30 && raw < 0x7f"
, "../src/parser.cc", 227, __extension__ __PRETTY_FUNCTION__)
)
;
228
229 unsigned int remaining_intermediates = BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5));
230
231 switch (BTE_SEQ_INTERMEDIATE(intermediates)((intermediates) & ((1U << (5)) - 1U))) {
232 case BTE_SEQ_INTERMEDIATE_NONE:
233 if (remaining_intermediates == 0 &&
234 raw < (0x30 + G_N_ELEMENTS(charset_graphic_94_n)(sizeof (charset_graphic_94_n) / sizeof ((charset_graphic_94_n
)[0]))
))
235 return charset_graphic_94_n[raw - 0x30];
236 break;
237
238 case BTE_SEQ_INTERMEDIATE_SPACE:
239 return BTE_CHARSET_DRCS;
240 }
241
242 return BTE_CHARSET_NONE;
243}
244
245static unsigned int
246bte_parse_charset_96(uint32_t raw,
247 unsigned int intermediates)
248{
249 assert (raw >= 0x30 && raw < 0x7f)(static_cast <bool> (raw >= 0x30 && raw <
0x7f) ? void (0) : __assert_fail ("raw >= 0x30 && raw < 0x7f"
, "../src/parser.cc", 249, __extension__ __PRETTY_FUNCTION__)
)
;
250
251 unsigned int remaining_intermediates = BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5));
252
253 switch (BTE_SEQ_INTERMEDIATE(intermediates)((intermediates) & ((1U << (5)) - 1U))) {
254 case BTE_SEQ_INTERMEDIATE_NONE:
255 if (remaining_intermediates == 0 &&
256 raw < (0x30 + G_N_ELEMENTS(charset_graphic_96)(sizeof (charset_graphic_96) / sizeof ((charset_graphic_96)[0
]))
))
257 return charset_graphic_96[raw - 0x30];
258 break;
259
260 case BTE_SEQ_INTERMEDIATE_SPACE:
261 return BTE_CHARSET_DRCS;
262 }
263
264 return BTE_CHARSET_NONE;
265}
266
267static unsigned int
268bte_parse_charset_96_n(uint32_t raw,
269 unsigned int intermediates)
270{
271 if (BTE_SEQ_INTERMEDIATE(intermediates)((intermediates) & ((1U << (5)) - 1U)) == BTE_SEQ_INTERMEDIATE_SPACE)
272 return BTE_CHARSET_DRCS;
273
274 return BTE_CHARSET_NONE;
275}
276
277static unsigned int
278bte_parse_charset_ocs(uint32_t raw,
279 unsigned int intermediates)
280{
281 assert (raw >= 0x30 && raw < 0x7f)(static_cast <bool> (raw >= 0x30 && raw <
0x7f) ? void (0) : __assert_fail ("raw >= 0x30 && raw < 0x7f"
, "../src/parser.cc", 281, __extension__ __PRETTY_FUNCTION__)
)
;
282
283 unsigned int remaining_intermediates = BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5));
284
285 switch (BTE_SEQ_INTERMEDIATE(intermediates)((intermediates) & ((1U << (5)) - 1U))) {
286 case BTE_SEQ_INTERMEDIATE_NONE: /* OCS with standard return */
287 if (remaining_intermediates == 0 &&
288 raw >= 0x30 && raw < (0x30 + G_N_ELEMENTS(charset_ocs)(sizeof (charset_ocs) / sizeof ((charset_ocs)[0]))))
289 return charset_ocs[raw - 0x30];
290 break;
291
292 case BTE_SEQ_INTERMEDIATE_SPACE: /* OCS with standard return */
293 if (remaining_intermediates == 0 &&
294 raw >= 0x30 && raw < (0x30 + G_N_ELEMENTS(charset_ocs_with_2_0)(sizeof (charset_ocs_with_2_0) / sizeof ((charset_ocs_with_2_0
)[0]))
))
295 return charset_ocs_with_2_0[raw - 0x30];
296 /* Or should this return BTE_CHARSET_DRCS; ? */
297 break;
298
299 case BTE_SEQ_INTERMEDIATE_BANG ... BTE_SEQ_INTERMEDIATE_DOT: /* OCS with standard return */
300 break;
301
302 case BTE_SEQ_INTERMEDIATE_SLASH: /* OCS without standard return */
303 if (remaining_intermediates == 0 &&
304 raw >= 0x40 && raw < (0x40 + G_N_ELEMENTS(charset_ocs_with_2_15)(sizeof (charset_ocs_with_2_15) / sizeof ((charset_ocs_with_2_15
)[0]))
))
305 return charset_ocs_with_2_15[raw - 0x40];
306 break;
307 }
308
309 return BTE_CHARSET_NONE;
310}
311
312static unsigned int
313bte_parse_charset_control(uint32_t raw,
314 unsigned int intermediates)
315{
316 assert (raw >= 0x30 && raw < 0x7f)(static_cast <bool> (raw >= 0x30 && raw <
0x7f) ? void (0) : __assert_fail ("raw >= 0x30 && raw < 0x7f"
, "../src/parser.cc", 316, __extension__ __PRETTY_FUNCTION__)
)
;
317
318 unsigned int remaining_intermediates = BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5));
319
320 switch (BTE_SEQ_INTERMEDIATE(intermediates)((intermediates) & ((1U << (5)) - 1U))) {
321 case BTE_SEQ_INTERMEDIATE_BANG: /* C0 controls */
322 if (remaining_intermediates == 0 &&
323 raw >= 0x40 && raw < (0x40 + G_N_ELEMENTS(charset_control_c0)(sizeof (charset_control_c0) / sizeof ((charset_control_c0)[0
]))
))
324 return charset_control_c0[raw - 0x40];
325 break;
326
327 case BTE_SEQ_INTERMEDIATE_DQUOTE: /* C1 controls */
328 if (remaining_intermediates == 0 &&
329 raw >= 0x40 && raw < (0x40 + G_N_ELEMENTS(charset_control_c1)(sizeof (charset_control_c1) / sizeof ((charset_control_c1)[0
]))
))
330 return charset_control_c1[raw - 0x40];
331 break;
332 }
333
334 return BTE_CHARSET_NONE;
335}
336
337static unsigned int
338bte_parse_host_escape(bte_seq_t const* seq,
339 unsigned int *cs_out)
340{
341 unsigned int intermediates = seq->intermediates;
342 unsigned int intermediate0 = BTE_SEQ_INTERMEDIATE(intermediates)((intermediates) & ((1U << (5)) - 1U));
343
344 /* Switch on the first intermediate */
345 switch (intermediate0) {
346 case BTE_SEQ_INTERMEDIATE_NONE:
347 case BTE_SEQ_INTERMEDIATE_HASH: { /* Single control functions */
348 switch (_BTE_SEQ_CODE_ESC(seq->terminator, intermediates)(((seq->terminator) - 0x30) | ((intermediates) >> 1)
<< 7)
) {
349#define _BTE_SEQ(cmd,type,f,p,ni,i) \
350 case _BTE_SEQ_CODE_ESC(f, BTE_SEQ_INTERMEDIATE_##i)(((f) - 0x30) | ((BTE_SEQ_INTERMEDIATE_##i) >> 1) <<
7)
: return BTE_CMD_##cmd;
351#include "parser-esc.hh"
352#undef _BTE_SEQ
353 default: return BTE_CMD_NONE;
354 }
355 break;
356 }
357
358 case BTE_SEQ_INTERMEDIATE_SPACE: /* Announce code structure */
359 if (BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5)) == 0)
360 return BTE_CMD_ACS;
361 break;
362
363 case BTE_SEQ_INTERMEDIATE_BANG: /* C0-designate */
364 case BTE_SEQ_INTERMEDIATE_DQUOTE: /* C1-designate */
365 *cs_out = BTE_MAKE_CHARSET(bte_parse_charset_control(seq->terminator, intermediates),((bte_parse_charset_control(seq->terminator, intermediates
)) | ((intermediate0 - BTE_SEQ_INTERMEDIATE_BANG) << (16
)))
366 intermediate0 - BTE_SEQ_INTERMEDIATE_BANG)((bte_parse_charset_control(seq->terminator, intermediates
)) | ((intermediate0 - BTE_SEQ_INTERMEDIATE_BANG) << (16
)))
;
367 return BTE_CMD_CnD;
368
369 case BTE_SEQ_INTERMEDIATE_CASH: { /* Designate multi-byte character sets */
370 unsigned int remaining_intermediates = BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5));
371 unsigned int intermediate1 = BTE_SEQ_INTERMEDIATE(remaining_intermediates)((remaining_intermediates) & ((1U << (5)) - 1U));
372 remaining_intermediates = BTE_SEQ_REMOVE_INTERMEDIATE(remaining_intermediates)((remaining_intermediates) >> (5));
373
374 /* Check the 2nd intermediate */
375 switch (intermediate1) {
376 case BTE_SEQ_INTERMEDIATE_NONE:
377 /* For compatibility with an earlier version of ISO-2022,
378 * ESC 2/4 4/0, ESC 2/4 4/1 and ESC 2/4 4/2 designate G0
379 * sets (i.e., without the 2/8 as 2nd intermediate byte).
380 */
381 switch (seq->terminator) {
382 case '@':
383 case 'A':
384 case 'B': /* G0-designate multibyte charset */
385 *cs_out = BTE_MAKE_CHARSET(bte_parse_charset_94_n(seq->terminator,((bte_parse_charset_94_n(seq->terminator, remaining_intermediates
)) | ((0) << (16)))
386 remaining_intermediates),((bte_parse_charset_94_n(seq->terminator, remaining_intermediates
)) | ((0) << (16)))
387 0)((bte_parse_charset_94_n(seq->terminator, remaining_intermediates
)) | ((0) << (16)))
;
388 return BTE_CMD_GnDMm;
389 }
390 break;
391
392 case BTE_SEQ_INTERMEDIATE_POPEN: /* G0-designate 94^n-set */
393 case BTE_SEQ_INTERMEDIATE_PCLOSE: /* G1-designate 94^n-set */
394 case BTE_SEQ_INTERMEDIATE_MULT: /* G2-designate 94^n-set */
395 case BTE_SEQ_INTERMEDIATE_PLUS: /* G3-designate 94^n-set */
396 *cs_out = BTE_MAKE_CHARSET(bte_parse_charset_94_n(seq->terminator,((bte_parse_charset_94_n(seq->terminator, remaining_intermediates
)) | ((intermediate1 - BTE_SEQ_INTERMEDIATE_POPEN) << (
16)))
397 remaining_intermediates),((bte_parse_charset_94_n(seq->terminator, remaining_intermediates
)) | ((intermediate1 - BTE_SEQ_INTERMEDIATE_POPEN) << (
16)))
398 intermediate1 - BTE_SEQ_INTERMEDIATE_POPEN)((bte_parse_charset_94_n(seq->terminator, remaining_intermediates
)) | ((intermediate1 - BTE_SEQ_INTERMEDIATE_POPEN) << (
16)))
;
399 return BTE_CMD_GnDMm;
400
401 case BTE_SEQ_INTERMEDIATE_COMMA: /* Reserved for future standardisation */
402 break;
403
404 case BTE_SEQ_INTERMEDIATE_MINUS: /* G1-designate 96^n-set */
405 case BTE_SEQ_INTERMEDIATE_DOT: /* G2-designate 96^n-set */
406 case BTE_SEQ_INTERMEDIATE_SLASH: /* G3-designate 96^n-set */
407 *cs_out = BTE_MAKE_CHARSET(bte_parse_charset_96_n(seq->terminator,((bte_parse_charset_96_n(seq->terminator, remaining_intermediates
)) | ((intermediate1 - BTE_SEQ_INTERMEDIATE_COMMA) << (
16)))
408 remaining_intermediates),((bte_parse_charset_96_n(seq->terminator, remaining_intermediates
)) | ((intermediate1 - BTE_SEQ_INTERMEDIATE_COMMA) << (
16)))
409 intermediate1 - BTE_SEQ_INTERMEDIATE_COMMA)((bte_parse_charset_96_n(seq->terminator, remaining_intermediates
)) | ((intermediate1 - BTE_SEQ_INTERMEDIATE_COMMA) << (
16)))
;
410 return BTE_CMD_GnDMm;
411 }
412 break;
413 }
414
415 case BTE_SEQ_INTERMEDIATE_PERCENT: /* Designate other coding system */
416 *cs_out = bte_parse_charset_ocs(seq->terminator,
417 BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5)));
418 return BTE_CMD_DOCS;
419
420 case BTE_SEQ_INTERMEDIATE_AND: /* Identify revised registration */
421 if (BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)((intermediates) >> (5)) == 0)
422 return BTE_CMD_IRR;
423 break;
424
425 case BTE_SEQ_INTERMEDIATE_SQUOTE: /* Reserved for future standardisation */
426 break;
427
428 case BTE_SEQ_INTERMEDIATE_POPEN: /* G0-designate 94-set */
429 case BTE_SEQ_INTERMEDIATE_PCLOSE: /* G1-designate 94-set */
430 case BTE_SEQ_INTERMEDIATE_MULT: /* G2-designate 94-set */
431 case BTE_SEQ_INTERMEDIATE_PLUS: /* G3-designate 94-set */
432 *cs_out = BTE_MAKE_CHARSET(bte_parse_charset_94(seq->terminator,((bte_parse_charset_94(seq->terminator, ((intermediates) >>
(5)))) | ((intermediate0 - BTE_SEQ_INTERMEDIATE_POPEN) <<
(16)))
433 BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)),((bte_parse_charset_94(seq->terminator, ((intermediates) >>
(5)))) | ((intermediate0 - BTE_SEQ_INTERMEDIATE_POPEN) <<
(16)))
434 intermediate0 - BTE_SEQ_INTERMEDIATE_POPEN)((bte_parse_charset_94(seq->terminator, ((intermediates) >>
(5)))) | ((intermediate0 - BTE_SEQ_INTERMEDIATE_POPEN) <<
(16)))
;
435 return BTE_CMD_GnDm;
436
437 case BTE_SEQ_INTERMEDIATE_COMMA: /* Reserved for future standardisation */
438 break;
439
440 case BTE_SEQ_INTERMEDIATE_MINUS: /* G1-designate 96-set */
441 case BTE_SEQ_INTERMEDIATE_DOT: /* G2-designate 96-set */
442 case BTE_SEQ_INTERMEDIATE_SLASH: /* G3-designate 96-set */
443 *cs_out = BTE_MAKE_CHARSET(bte_parse_charset_96(seq->terminator,((bte_parse_charset_96(seq->terminator, ((intermediates) >>
(5)))) | ((intermediate0 - BTE_SEQ_INTERMEDIATE_COMMA) <<
(16)))
444 BTE_SEQ_REMOVE_INTERMEDIATE(intermediates)),((bte_parse_charset_96(seq->terminator, ((intermediates) >>
(5)))) | ((intermediate0 - BTE_SEQ_INTERMEDIATE_COMMA) <<
(16)))
445 intermediate0 - BTE_SEQ_INTERMEDIATE_COMMA)((bte_parse_charset_96(seq->terminator, ((intermediates) >>
(5)))) | ((intermediate0 - BTE_SEQ_INTERMEDIATE_COMMA) <<
(16)))
;
446 return BTE_CMD_GnDm;
447 }
448
449 return BTE_CMD_NONE;
450}
451
452static unsigned int
453bte_parse_host_csi(bte_seq_t const* seq)
454{
455 switch (_BTE_SEQ_CODE(seq->terminator, seq->intermediates)(((seq->terminator) - 0x40) | ((seq->intermediates) <<
6))
) {
456#define _BTE_SEQ(cmd,type,f,p,ni,i) \
457 case _BTE_SEQ_CODE(f, _BTE_SEQ_CODE_COMBINE(BTE_SEQ_PARAMETER_##p, BTE_SEQ_INTERMEDIATE_##i))(((f) - 0x40) | ((((BTE_SEQ_PARAMETER_##p) | ((BTE_SEQ_INTERMEDIATE_
##i) << (3)))) << 6))
: return BTE_CMD_##cmd;
458#include "parser-csi.hh"
459#undef _BTE_SEQ
460 default: return BTE_CMD_NONE;
461 }
462}
463
464static unsigned int
465bte_parse_host_dcs(bte_seq_t const* seq)
466{
467 switch (_BTE_SEQ_CODE(seq->terminator, seq->intermediates)(((seq->terminator) - 0x40) | ((seq->intermediates) <<
6))
) {
468#define _BTE_SEQ(cmd,type,f,p,ni,i) \
469 case _BTE_SEQ_CODE(f, _BTE_SEQ_CODE_COMBINE(BTE_SEQ_PARAMETER_##p, BTE_SEQ_INTERMEDIATE_##i))(((f) - 0x40) | ((((BTE_SEQ_PARAMETER_##p) | ((BTE_SEQ_INTERMEDIATE_
##i) << (3)))) << 6))
: return BTE_CMD_##cmd;
470#include "parser-dcs.hh"
471#undef _BTE_SEQ
472 default: return BTE_CMD_NONE;
473 }
474}
475
476static unsigned int
477bte_parse_host_sci(bte_seq_t const* seq)
478{
479 switch (_BTE_SEQ_CODE(seq->terminator, 0)(((seq->terminator) - 0x40) | ((0) << 6))) {
480#define _BTE_SEQ(cmd,type,f,p,ni,i) \
481 case _BTE_SEQ_CODE(f, 0)(((f) - 0x40) | ((0) << 6)): return BTE_CMD_##cmd;
482#include "parser-sci.hh"
483#undef _BTE_SEQ
484 default: return BTE_CMD_NONE;
485 }
486}
487
488/*
489 * State Machine
490 * This parser controls the parser-state and returns any detected sequence to
491 * the caller. The parser is based on this state-diagram from Paul Williams:
492 * https://vt100.net/emu/
493 * It was written from scratch and extended where needed.
494 * This parser is fully compatible up to the vt500 series. We expect UCS-4 as
495 * input. It's the callers responsibility to do any UTF-8 parsing.
496 */
497
498enum parser_state_t {
499 STATE_GROUND, /* initial state and ground */
500 STATE_DCS_PASS_ESC, /* ESC after DCS which may be ESC \ aka C0 ST */
501 STATE_OSC_STRING_ESC, /* ESC after OSC which may be ESC \ aka C0 ST */
502 STATE_ESC, /* ESC sequence was started */
503 STATE_ESC_INT, /* intermediate escape characters */
504 STATE_CSI_ENTRY, /* starting CSI sequence */
505 STATE_CSI_PARAM, /* CSI parameters */
506 STATE_CSI_INT, /* intermediate CSI characters */
507 STATE_CSI_IGNORE, /* CSI error; ignore this CSI sequence */
508 STATE_DCS_ENTRY, /* starting DCS sequence */
509 STATE_DCS_PARAM, /* DCS parameters */
510 STATE_DCS_INT, /* intermediate DCS characters */
511 STATE_DCS_PASS, /* DCS data passthrough */
512 STATE_DCS_IGNORE, /* DCS error; ignore this DCS sequence */
513 STATE_OSC_STRING, /* parsing OSC sequence */
514 STATE_ST_IGNORE, /* unimplemented seq; ignore until ST */
515 STATE_SCI, /* single character introducer sequence was started */
516
517 STATE_N,
518};
519
520/* Parser state transitioning */
521
522typedef int (* parser_action_func)(bte_parser_t* parser, uint32_t raw);
523
524// FIXMEchpe: I get weird performance results here from
525// either not inlining, inlining these function or the
526// macros below. Sometimes (after a recompile) one is
527// (as much as 50%!) slower, sometimes the other one etc. ‽
528
529#if 1 // (inline) functions
530
531// #define PTINLINE inline
532#define PTINLINE
533
534/* nop */
535static PTINLINE int
536parser_nop(bte_parser_t* parser,
537 uint32_t raw)
538{
539 return BTE_SEQ_NONE;
540}
541/* dispatch related actions */
542static PTINLINE int
543parser_action(bte_parser_t* parser,
544 uint32_t raw,
545 parser_action_func action)
546{
547 return action(parser, raw);
548}
549
550/* perform state transition */
551static PTINLINE int
552parser_transition_no_action(bte_parser_t* parser,
553 uint32_t raw,
554 unsigned int state)
555{
556 parser->state = state;
557 return BTE_SEQ_NONE;
558}
559
560/* perform state transition and dispatch related actions */
561static PTINLINE int
562parser_transition(bte_parser_t* parser,
563 uint32_t raw,
564 unsigned int state,
565 parser_action_func action)
566{
567 parser->state = state;
568
569 return action(parser, raw);
570}
571
572#undef PTINLINE
573
574#else // macros
575
576/* nop */
577#define parser_nop(parser,raw) \
578 ({ BTE_SEQ_NONE; })
579
580/* dispatch related actions */
581#define parser_action(p,r,a) \
582 ({ \
583 a((p), (r)); \
584 })
585
586/* perform state transition */
587#define parser_transition_no_action(p,r,s) \
588 ({ \
589 parser->state = s; \
590 BTE_SEQ_NONE; \
591 })
592
593/* perform state transition and dispatch related actions */
594#define parser_transition(p,r,s,a) \
595 ({ \
596 (p)->state = s; \
597 a((p), (r)); \
598 })
599
600#endif // (inline) functions or macros
601
602/**
603 * bte_parser_init() - Initialise parser object
604 * @parser: the struct bte_parser
605 */
606void
607bte_parser_init(bte_parser_t* parser)
608{
609 memset(parser, 0, sizeof(*parser));
610 bte_seq_string_init(&parser->seq.arg_str);
611}
612
613/**
614 * bte_parser_deinit() - Deinitialises parser object
615 * @parser: parser object to deinitialise
616 */
617void
618bte_parser_deinit(bte_parser_t* parser)
619{
620 bte_seq_string_free(&parser->seq.arg_str);
621}
622
623static inline int
624parser_clear(bte_parser_t* parser,
625 uint32_t raw)
626{
627 /* seq.command is set when the sequence is executed,
628 * seq.terminator is set when the final character is received,
629 * and seq.introducer is set when the introducer is received,
630 * and all this happens before the sequence is dispatched.
631 * Therefore these fiedls need not be cleared in any case.
632 */
633 return BTE_SEQ_NONE;
634}
635
636static inline int
637parser_clear_int(bte_parser_t* parser,
638 uint32_t raw)
639{
640 parser->seq.intermediates = 0;
641 parser->seq.n_intermediates = 0;
642
643 return parser_clear(parser, raw);
644}
645
646static inline int
647parser_clear_params(bte_parser_t* parser,
648 uint32_t raw)
649{
650 /* The (n_args+1)th parameter may have been started but not
651 * finialised, so it needs cleaning too. All further params
652 * have not been touched, so need not be cleaned.
653 */
654 unsigned int n_args = G_UNLIKELY(parser->seq.n_args >= BTE_PARSER_ARG_MAX)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
parser->seq.n_args >= (32)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 0))
655 ? BTE_PARSER_ARG_MAX(32)
656 : parser->seq.n_args + 1;
657 memset(parser->seq.args, 0, n_args * sizeof(parser->seq.args[0]));
658#ifdef PARSER_EXTRA_CLEAN
659 /* Assert that the assumed-clean params are actually clean. */
660 for (unsigned int n = n_args; n < BTE_PARSER_ARG_MAX(32); ++n)
661 g_assert_cmpuint(parser->seq.args[n], ==, BTE_SEQ_ARG_INIT_DEFAULT)do { guint64 __n1 = (parser->seq.args[n]), __n2 = ((0)); if
(__n1 == __n2) ; else g_assertion_message_cmpnum ("BTE", "../src/parser.cc"
, 661, ((const char*) (__PRETTY_FUNCTION__)), "parser->seq.args[n]"
" " "==" " " "BTE_SEQ_ARG_INIT_DEFAULT", (long double) __n1,
"==", (long double) __n2, 'i'); } while (0)
;
662#endif
663
664 parser->seq.n_args = 0;
665 parser->seq.n_final_args = 0;
666
667 return BTE_SEQ_NONE;
668}
669
670static inline int
671parser_clear_int_and_params(bte_parser_t* parser,
672 uint32_t raw)
673{
674 parser_clear_int(parser, raw);
675 return parser_clear_params(parser, raw);
676}
677
678static int
679parser_ignore(bte_parser_t* parser,
680 uint32_t raw)
681{
682 parser->seq.type = BTE_SEQ_IGNORE;
683 parser->seq.command = BTE_CMD_NONE;
684 parser->seq.terminator = raw;
685
686 return parser->seq.type;
687}
688
689static int
690parser_print(bte_parser_t* parser,
691 uint32_t raw)
692{
693 parser->seq.type = BTE_SEQ_GRAPHIC;
694 parser->seq.command = BTE_CMD_GRAPHIC;
695 parser->seq.terminator = raw;
696
697 return parser->seq.type;
698}
699
700static int
701parser_execute(bte_parser_t* parser,
702 uint32_t raw)
703{
704 parser->seq.type = BTE_SEQ_CONTROL;
705 parser->seq.terminator = raw;
706 parser->seq.command = bte_parse_host_control(&parser->seq);
707
708 return parser->seq.type;
709}
710
711static int
712parser_collect_esc(bte_parser_t* parser,
713 uint32_t raw)
714{
715 assert(raw >= 0x20 && raw <= 0x2f)(static_cast <bool> (raw >= 0x20 && raw <=
0x2f) ? void (0) : __assert_fail ("raw >= 0x20 && raw <= 0x2f"
, "../src/parser.cc", 715, __extension__ __PRETTY_FUNCTION__)
)
;
716
717 /* ESCAPE sequences only have intermediates or 2/0..2/15, so there's no
718 * need for the extra shift as below for CSI/DCS sequences
719 */
720 parser->seq.intermediates |= (BTE_SEQ_MAKE_INTERMEDIATE(raw)((raw) - ' ' + 1) << (BTE_SEQ_INTERMEDIATE_BITS(5) * parser->seq.n_intermediates++));
721
722 return BTE_SEQ_NONE;
723}
724
725static int
726parser_collect_csi(bte_parser_t* parser,
727 uint32_t raw)
728{
729 assert(raw >= 0x20 && raw <= 0x2f)(static_cast <bool> (raw >= 0x20 && raw <=
0x2f) ? void (0) : __assert_fail ("raw >= 0x20 && raw <= 0x2f"
, "../src/parser.cc", 729, __extension__ __PRETTY_FUNCTION__)
)
;
730
731 /* In addition to 2/0..2/15 intermediates, CSI/DCS sequence
732 * can also have one parameter byte 3/12..3/15 at the
733 * start of the parameters (see parser_collect_parameter below);
734 * that's what the extra shift is for.
735 */
736 parser->seq.intermediates |= (BTE_SEQ_MAKE_INTERMEDIATE(raw)((raw) - ' ' + 1) << (BTE_SEQ_PARAMETER_BITS(3) +
737 BTE_SEQ_INTERMEDIATE_BITS(5) * parser->seq.n_intermediates++));
738
739 return BTE_SEQ_NONE;
740}
741
742static int
743parser_collect_parameter(bte_parser_t* parser,
744 uint32_t raw)
745{
746 assert(raw >= 0x3c && raw <= 0x3f)(static_cast <bool> (raw >= 0x3c && raw <=
0x3f) ? void (0) : __assert_fail ("raw >= 0x3c && raw <= 0x3f"
, "../src/parser.cc", 746, __extension__ __PRETTY_FUNCTION__)
)
;
747
748 /* CSI/DCS may optionally have one parameter byte from 3/12..3/15
749 * at the start of the parameters; we put that into the lowest
750 * part of @seq.intermediates.
751 * Note that there can only be *one* such byte; the state machine
752 * already enforces that, so we do not need any additional checks
753 * here.
754 */
755 parser->seq.intermediates |= BTE_SEQ_MAKE_PARAMETER(raw)('?' - (raw) + 1);
756
757 return BTE_SEQ_NONE;
758}
759
760static void
761parser_params_overflow(bte_parser_t* parser,
762 uint32_t raw)
763{
764 /* An overflow of the parameter number can only happen in
765 * STATE_{CSI,DCS}_PARAM, and it occurs when
766 * seq.n_arg == BTE_PARSER_ARG_MAX, and either an 0…9
767 * is encountered, starting the next param, or an
768 * explicit ':' or ';' terminating a (defaulted) (sub)param,
769 * or when the intermediates/final character(s) occur
770 * after a defaulted (sub)param.
771 *
772 * Transition to STATE_{CSI,DCS}_IGNORE to ignore the
773 * whole sequence.
774 */
775 parser_transition_no_action(parser,
776 raw,
777 parser->state == STATE_CSI_PARAM ?
778 STATE_CSI_IGNORE : STATE_DCS_IGNORE);
779}
780
781/* The next two functions are only called when encountering a ';' or ':',
782 * so if there's already MAX-1 parameters, the ';' or ':' would finish
783 * the MAXth parameter and there would be a default or non-default
784 * MAX+1th parameter following it.
785 */
786static int
787parser_finish_param(bte_parser_t* parser,
788 uint32_t raw)
789{
790 if (G_LIKELY(parser->seq.n_args < BTE_PARSER_ARG_MAX - 1)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
parser->seq.n_args < (32) - 1) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))
) {
791 bte_seq_arg_finish(&parser->seq.args[parser->seq.n_args], false);
792 ++parser->seq.n_args;
793 ++parser->seq.n_final_args;
794 } else
795 parser_params_overflow(parser, raw);
796
797 return BTE_SEQ_NONE;
798}
799
800static int
801parser_finish_subparam(bte_parser_t* parser,
802 uint32_t raw)
803{
804 if (G_LIKELY(parser->seq.n_args < BTE_PARSER_ARG_MAX - 1)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
parser->seq.n_args < (32) - 1) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))
) {
805 bte_seq_arg_finish(&parser->seq.args[parser->seq.n_args], true);
806 ++parser->seq.n_args;
807 } else
808 parser_params_overflow(parser, raw);
809
810 return BTE_SEQ_NONE;
811}
812
813static int
814parser_param(bte_parser_t* parser,
815 uint32_t raw)
816{
817 /* assert(raw >= '0' && raw <= '9'); */
818
819 if (G_LIKELY(parser->seq.n_args < BTE_PARSER_ARG_MAX)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
parser->seq.n_args < (32)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))
)
820 bte_seq_arg_push(&parser->seq.args[parser->seq.n_args], raw);
821 else
822 parser_params_overflow(parser, raw);
823
824 return BTE_SEQ_NONE;
825}
826
827static inline int
828parser_osc_start(bte_parser_t* parser,
829 uint32_t raw)
830{
831 parser_clear(parser, raw);
832
833 bte_seq_string_reset(&parser->seq.arg_str);
834
835 parser->seq.introducer = raw;
836 return BTE_SEQ_NONE;
837}
838
839static int
840parser_osc_collect(bte_parser_t* parser,
841 uint32_t raw)
842{
843 /*
844 * Only characters from 0x20..0x7e and >= 0xa0 are allowed here.
845 * Our state-machine already verifies those restrictions.
846 */
847
848 if (G_UNLIKELY(!bte_seq_string_push(&parser->seq.arg_str, raw))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
!bte_seq_string_push(&parser->seq.arg_str, raw)) _g_boolean_var_
= 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 0))
)
849 parser->state = STATE_ST_IGNORE;
850
851 return BTE_SEQ_NONE;
852}
853
854static int
855parser_dcs_start(bte_parser_t* parser,
856 uint32_t raw)
857{
858 parser_clear_int_and_params(parser, raw);
859
860 bte_seq_string_reset(&parser->seq.arg_str);
861
862 parser->seq.introducer = raw;
863 return BTE_SEQ_NONE;
864}
865
866static int
867parser_dcs_consume(bte_parser_t* parser,
868 uint32_t raw)
869{
870 /* parser->seq is cleared during DCS-START state, thus there's no need
871 * to clear invalid fields here. */
872
873 if (G_LIKELY(parser->seq.n_args < BTE_PARSER_ARG_MAX)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
parser->seq.n_args < (32)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))
) {
874 if (parser->seq.n_args > 0 ||
875 bte_seq_arg_started(parser->seq.args[parser->seq.n_args])) {
876 bte_seq_arg_finish(&parser->seq.args[parser->seq.n_args], false);
877 ++parser->seq.n_args;
878 ++parser->seq.n_final_args;
879 }
880 }
881
882 parser->seq.type = BTE_SEQ_DCS;
883 parser->seq.terminator = raw;
884 parser->seq.command = bte_parse_host_dcs(&parser->seq);
885
886 return BTE_SEQ_NONE;
887}
888
889static int
890parser_dcs_collect(bte_parser_t* parser,
891 uint32_t raw)
892{
893 if (G_UNLIKELY(!bte_seq_string_push(&parser->seq.arg_str, raw))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
!bte_seq_string_push(&parser->seq.arg_str, raw)) _g_boolean_var_
= 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 0))
)
894 parser->state = STATE_DCS_IGNORE;
895
896 return BTE_SEQ_NONE;
897}
898
899static int
900parser_esc(bte_parser_t* parser,
901 uint32_t raw)
902{
903 parser->seq.type = BTE_SEQ_ESCAPE;
904 parser->seq.terminator = raw;
905 parser->seq.charset = BTE_CHARSET_NONE;
906 parser->seq.command = bte_parse_host_escape(&parser->seq,
907 &parser->seq.charset);
908
909 return parser->seq.type;
910}
911
912static int
913parser_csi(bte_parser_t* parser,
914 uint32_t raw)
915{
916 /* parser->seq is cleared during CSI-ENTER state, thus there's no need
917 * to clear invalid fields here. */
918
919 if (G_LIKELY(parser->seq.n_args < BTE_PARSER_ARG_MAX)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
parser->seq.n_args < (32)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))
) {
920 if (parser->seq.n_args > 0 ||
921 bte_seq_arg_started(parser->seq.args[parser->seq.n_args])) {
922 bte_seq_arg_finish(&parser->seq.args[parser->seq.n_args], false);
923 ++parser->seq.n_args;
924 ++parser->seq.n_final_args;
925 }
926 }
927
928 parser->seq.type = BTE_SEQ_CSI;
929 parser->seq.terminator = raw;
930 parser->seq.command = bte_parse_host_csi(&parser->seq);
931
932 return parser->seq.type;
933}
934
935static int
936parser_osc(bte_parser_t* parser,
937 uint32_t raw)
938{
939 /* parser->seq is cleared during OSC_START state, thus there's no need
940 * to clear invalid fields here. */
941
942 bte_seq_string_finish(&parser->seq.arg_str);
943
944 /* We only dispatch a DCS if the introducer and string
945 * terminator are from the same control set, i.e. both
946 * C0 or both C1; we discard sequences with mixed controls.
947 */
948 if (!parser_check_matching_controls(parser->seq.introducer, raw))
949 return BTE_SEQ_IGNORE;
950
951 parser->seq.type = BTE_SEQ_OSC;
952 parser->seq.command = BTE_CMD_OSC;
953 parser->seq.terminator = raw;
954
955 return parser->seq.type;
956}
957
958static int
959parser_dcs(bte_parser_t* parser,
960 uint32_t raw)
961{
962 /* parser->seq was already filled in parser_dcs_consume() */
963
964 bte_seq_string_finish(&parser->seq.arg_str);
965
966 /* We only dispatch a DCS if the introducer and string
967 * terminator are from the same control set, i.e. both
968 * C0 or both C1; we discard sequences with mixed controls.
969 */
970 if (!parser_check_matching_controls(parser->seq.introducer, raw))
971 return BTE_SEQ_IGNORE;
972
973 return parser->seq.type;
974}
975
976static int
977parser_sci(bte_parser_t* parser,
978 uint32_t raw)
979{
980 parser->seq.type = BTE_SEQ_SCI;
981 parser->seq.terminator = raw;
982 parser->seq.command = bte_parse_host_sci(&parser->seq);
983
984 return parser->seq.type;
985}
986
987#define ACTION_CLEARparser_clear parser_clear
988#define ACTION_CLEAR_INTparser_clear_int parser_clear_int
989#define ACTION_CLEAR_INT_AND_PARAMSparser_clear_int_and_params parser_clear_int_and_params
990#define ACTION_CLEAR_PARAMS_ONLYparser_clear_params parser_clear_params
991#define ACTION_IGNOREparser_ignore parser_ignore
992#define ACTION_PRINTparser_print parser_print
993#define ACTION_EXECUTEparser_execute parser_execute
994#define ACTION_COLLECT_ESCparser_collect_esc parser_collect_esc
995#define ACTION_COLLECT_CSIparser_collect_csi parser_collect_csi
996#define ACTION_COLLECT_DCSparser_collect_csi ACTION_COLLECT_CSIparser_collect_csi
997#define ACTION_COLLECT_PARAMETERparser_collect_parameter parser_collect_parameter
998#define ACTION_PARAMparser_param parser_param
999#define ACTION_FINISH_PARAMparser_finish_param parser_finish_param
1000#define ACTION_FINISH_SUBPARAMparser_finish_subparam parser_finish_subparam
1001#define ACTION_ESC_DISPATCHparser_esc parser_esc
1002#define ACTION_CSI_DISPATCHparser_csi parser_csi
1003#define ACTION_DCS_STARTparser_dcs_start parser_dcs_start
1004#define ACTION_DCS_CONSUMEparser_dcs_consume parser_dcs_consume
1005#define ACTION_DCS_COLLECTparser_dcs_collect parser_dcs_collect
1006#define ACTION_DCS_DISPATCHparser_dcs parser_dcs
1007#define ACTION_OSC_STARTparser_osc_start parser_osc_start
1008#define ACTION_OSC_COLLECTparser_osc_collect parser_osc_collect
1009#define ACTION_OSC_DISPATCHparser_osc parser_osc
1010#define ACTION_SCI_DISPATCHparser_sci parser_sci
1011
1012static int
1013parser_feed_to_state(bte_parser_t* parser,
1014 uint32_t raw)
1015{
1016 switch (parser->state) {
1017 case STATE_GROUND:
1018 switch (raw) {
1019 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1020 case 0x1c ... 0x1f:
1021 case 0x80 ... 0x9f: /* C1 */
1022 return parser_action(parser, raw,
1023 ACTION_EXECUTEparser_execute);
1024 case 0x1b: /* ESC */
1025 return parser_transition(parser, raw, STATE_ESC,
1026 ACTION_CLEAR_INTparser_clear_int);
1027 }
1028
1029 return parser_action(parser, raw,
1030 ACTION_PRINTparser_print);
1031
1032 case STATE_DCS_PASS_ESC:
1033 case STATE_OSC_STRING_ESC:
1034 if (raw == 0x5c /* '\' */) {
1035 switch (parser->state) {
1036 case STATE_DCS_PASS_ESC:
1037 return parser_transition(parser, raw, STATE_GROUND,
1038 ACTION_DCS_DISPATCHparser_dcs);
1039 case STATE_OSC_STRING_ESC:
1040 return parser_transition(parser, raw, STATE_GROUND,
1041 ACTION_OSC_DISPATCHparser_osc);
1042 }
1043 }
1044
1045 /* Do the deferred clear and fallthrough to STATE_ESC */
1046 parser_transition(parser, 0x1b /* ESC */, STATE_ESC,
1047 ACTION_CLEAR_INTparser_clear_int);
1048
1049 [[fallthrough]];
1050 case STATE_ESC:
1051 switch (raw) {
1052 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1053 case 0x1c ... 0x1f:
1054 return parser_action(parser, raw,
1055 ACTION_EXECUTEparser_execute);
1056 case 0x1b: /* ESC */
1057 return parser_transition(parser, raw, STATE_ESC,
1058 ACTION_CLEAR_INTparser_clear_int);
1059 case 0x20 ... 0x2f: /* [' ' - '\'] */
1060 return parser_transition(parser, raw, STATE_ESC_INT,
1061 ACTION_COLLECT_ESCparser_collect_esc);
1062 case 0x30 ... 0x4f: /* ['0' - '~'] \ */
1063 case 0x51 ... 0x57: /* { 'P', 'X', 'Z' '[', ']', '^', '_' } */
1064 case 0x59:
1065 case 0x5c:
1066 case 0x60 ... 0x7e:
1067 return parser_transition(parser, raw, STATE_GROUND,
1068 ACTION_ESC_DISPATCHparser_esc);
1069 case 0x50: /* 'P' */
1070 return parser_transition(parser, raw, STATE_DCS_ENTRY,
1071 ACTION_DCS_STARTparser_dcs_start);
1072 case 0x5a: /* 'Z' */
1073 return parser_transition(parser, raw, STATE_SCI,
1074 ACTION_CLEARparser_clear);
1075 case 0x5b: /* '[' */
1076 return parser_transition(parser, raw, STATE_CSI_ENTRY,
1077 ACTION_CLEAR_PARAMS_ONLYparser_clear_params
1078 /* rest already cleaned on ESC state entry */);
1079 case 0x5d: /* ']' */
1080 return parser_transition(parser, raw, STATE_OSC_STRING,
1081 ACTION_OSC_STARTparser_osc_start);
1082 case 0x58: /* 'X' */
1083 case 0x5e: /* '^' */
1084 case 0x5f: /* '_' */
1085 return parser_transition_no_action(parser, raw, STATE_ST_IGNORE);
1086 case 0x9c: /* ST */
1087 return parser_transition(parser, raw, STATE_GROUND,
1088 ACTION_IGNOREparser_ignore);
1089 }
1090
1091 return parser_transition(parser, raw, STATE_GROUND,
1092 ACTION_IGNOREparser_ignore);
1093 case STATE_ESC_INT:
1094 switch (raw) {
1095 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1096 case 0x1c ... 0x1f:
1097 return parser_action(parser, raw,
1098 ACTION_EXECUTEparser_execute);
1099 case 0x1b: /* ESC */
1100 return parser_transition(parser, raw, STATE_ESC,
1101 ACTION_CLEAR_INTparser_clear_int);
1102 case 0x20 ... 0x2f: /* [' ' - '\'] */
1103 return parser_action(parser, raw,
1104 ACTION_COLLECT_ESCparser_collect_esc);
1105 case 0x30 ... 0x7e: /* ['0' - '~'] */
1106 return parser_transition(parser, raw, STATE_GROUND,
1107 ACTION_ESC_DISPATCHparser_esc);
1108 case 0x9c: /* ST */
1109 return parser_transition(parser, raw, STATE_GROUND,
1110 ACTION_IGNOREparser_ignore);
1111 }
1112
1113 return parser_transition(parser, raw, STATE_GROUND,
1114 ACTION_IGNOREparser_ignore);
1115 case STATE_CSI_ENTRY:
1116 switch (raw) {
1117 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1118 case 0x1c ... 0x1f:
1119 return parser_action(parser, raw,
1120 ACTION_EXECUTEparser_execute);
1121 case 0x1b: /* ESC */
1122 return parser_transition(parser, raw, STATE_ESC,
1123 ACTION_CLEAR_INTparser_clear_int);
1124 case 0x20 ... 0x2f: /* [' ' - '\'] */
1125 return parser_transition(parser, raw, STATE_CSI_INT,
1126 ACTION_COLLECT_CSIparser_collect_csi);
1127 case 0x30 ... 0x39: /* ['0' - '9'] */
1128 return parser_transition(parser, raw, STATE_CSI_PARAM,
1129 ACTION_PARAMparser_param);
1130 case 0x3a: /* ':' */
1131 return parser_transition(parser, raw, STATE_CSI_PARAM,
1132 ACTION_FINISH_SUBPARAMparser_finish_subparam);
1133 case 0x3b: /* ';' */
1134 return parser_transition(parser, raw, STATE_CSI_PARAM,
1135 ACTION_FINISH_PARAMparser_finish_param);
1136 case 0x3c ... 0x3f: /* ['<' - '?'] */
1137 return parser_transition(parser, raw, STATE_CSI_PARAM,
1138 ACTION_COLLECT_PARAMETERparser_collect_parameter);
1139 case 0x40 ... 0x7e: /* ['@' - '~'] */
1140 return parser_transition(parser, raw, STATE_GROUND,
1141 ACTION_CSI_DISPATCHparser_csi);
1142 case 0x9c: /* ST */
1143 return parser_transition(parser, raw, STATE_GROUND,
1144 ACTION_IGNOREparser_ignore);
1145 }
1146
1147 return parser_transition_no_action(parser, raw, STATE_CSI_IGNORE);
1148 case STATE_CSI_PARAM:
1149 switch (raw) {
1150 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1151 case 0x1c ... 0x1f:
1152 return parser_action(parser, raw,
1153 ACTION_EXECUTEparser_execute);
1154 case 0x1b: /* ESC */
1155 return parser_transition(parser, raw, STATE_ESC,
1156 ACTION_CLEAR_INTparser_clear_int);
1157 case 0x20 ... 0x2f: /* [' ' - '\'] */
1158 return parser_transition(parser, raw, STATE_CSI_INT,
1159 ACTION_COLLECT_CSIparser_collect_csi);
1160 case 0x30 ... 0x39: /* ['0' - '9'] */
1161 return parser_action(parser, raw,
1162 ACTION_PARAMparser_param);
1163 case 0x3a: /* ':' */
1164 return parser_action(parser, raw,
1165 ACTION_FINISH_SUBPARAMparser_finish_subparam);
1166 case 0x3b: /* ';' */
1167 return parser_action(parser, raw,
1168 ACTION_FINISH_PARAMparser_finish_param);
1169 case 0x3c ... 0x3f: /* ['<' - '?'] */
1170 return parser_transition_no_action(parser, raw, STATE_CSI_IGNORE);
1171 case 0x40 ... 0x7e: /* ['@' - '~'] */
1172 return parser_transition(parser, raw, STATE_GROUND,
1173 ACTION_CSI_DISPATCHparser_csi);
1174 case 0x9c: /* ST */
1175 return parser_transition(parser, raw, STATE_GROUND,
1176 ACTION_IGNOREparser_ignore);
1177 }
1178
1179 return parser_transition_no_action(parser, raw, STATE_CSI_IGNORE);
1180 case STATE_CSI_INT:
1181 switch (raw) {
1182 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1183 case 0x1c ... 0x1f:
1184 return parser_action(parser, raw,
1185 ACTION_EXECUTEparser_execute);
1186 case 0x1b: /* ESC */
1187 return parser_transition(parser, raw, STATE_ESC,
1188 ACTION_CLEAR_INTparser_clear_int);
1189 case 0x20 ... 0x2f: /* [' ' - '\'] */
1190 return parser_action(parser, raw,
1191 ACTION_COLLECT_CSIparser_collect_csi);
1192 case 0x30 ... 0x3f: /* ['0' - '?'] */
1193 return parser_transition_no_action(parser, raw, STATE_CSI_IGNORE);
1194 case 0x40 ... 0x7e: /* ['@' - '~'] */
1195 return parser_transition(parser, raw, STATE_GROUND,
1196 ACTION_CSI_DISPATCHparser_csi);
1197 case 0x9c: /* ST */
1198 return parser_transition(parser, raw, STATE_GROUND,
1199 ACTION_IGNOREparser_ignore);
1200 }
1201
1202 return parser_transition_no_action(parser, raw, STATE_CSI_IGNORE);
1203 case STATE_CSI_IGNORE:
1204 switch (raw) {
1205 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1206 case 0x1c ... 0x1f:
1207 return parser_action(parser, raw,
1208 ACTION_EXECUTEparser_execute);
1209 case 0x1b: /* ESC */
1210 return parser_transition(parser, raw, STATE_ESC,
1211 ACTION_CLEAR_INTparser_clear_int);
1212 case 0x20 ... 0x3f: /* [' ' - '?'] */
1213 return parser_nop(parser, raw);
1214 case 0x40 ... 0x7e: /* ['@' - '~'] */
1215 return parser_transition_no_action(parser, raw, STATE_GROUND);
1216 case 0x9c: /* ST */
1217 return parser_transition(parser, raw, STATE_GROUND,
1218 ACTION_IGNOREparser_ignore);
1219 }
1220
1221 return parser_nop(parser, raw);
1222 case STATE_DCS_ENTRY:
1223 switch (raw) {
1224 case 0x00 ... 0x1a: /* C0 \ ESC */
1225 case 0x1c ... 0x1f:
1226 return parser_action(parser, raw,
1227 ACTION_IGNOREparser_ignore);
1228 case 0x1b: /* ESC */
1229 return parser_transition(parser, raw, STATE_ESC,
1230 ACTION_CLEAR_INTparser_clear_int);
1231 case 0x20 ... 0x2f: /* [' ' - '\'] */
1232 return parser_transition(parser, raw, STATE_DCS_INT,
1233 ACTION_COLLECT_DCSparser_collect_csi);
1234 case 0x30 ... 0x39: /* ['0' - '9'] */
1235 return parser_transition(parser, raw, STATE_DCS_PARAM,
1236 ACTION_PARAMparser_param);
1237 case 0x3a: /* ':' */
1238 return parser_transition(parser, raw, STATE_DCS_PARAM,
1239 ACTION_FINISH_SUBPARAMparser_finish_subparam);
1240 case 0x3b: /* ';' */
1241 return parser_transition(parser, raw, STATE_DCS_PARAM,
1242 ACTION_FINISH_PARAMparser_finish_param);
1243 case 0x3c ... 0x3f: /* ['<' - '?'] */
1244 return parser_transition(parser, raw, STATE_DCS_PARAM,
1245 ACTION_COLLECT_PARAMETERparser_collect_parameter);
1246 case 0x40 ... 0x7e: /* ['@' - '~'] */
1247 return parser_transition(parser, raw, STATE_DCS_PASS,
1248 ACTION_DCS_CONSUMEparser_dcs_consume);
1249 case 0x9c: /* ST */
1250 return parser_transition(parser, raw, STATE_GROUND,
1251 ACTION_IGNOREparser_ignore);
1252 }
1253
1254 return parser_transition(parser, raw,
1255 STATE_DCS_PASS, ACTION_DCS_CONSUMEparser_dcs_consume);
1256 case STATE_DCS_PARAM:
1257 switch (raw) {
1258 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1259 case 0x1c ... 0x1f:
1260 return parser_action(parser, raw,
1261 ACTION_IGNOREparser_ignore);
1262 case 0x1b: /* ESC */
1263 return parser_transition(parser, raw, STATE_ESC,
1264 ACTION_CLEAR_INTparser_clear_int);
1265 case 0x20 ... 0x2f: /* [' ' - '\'] */
1266 return parser_transition(parser, raw, STATE_DCS_INT,
1267 ACTION_COLLECT_DCSparser_collect_csi);
1268 case 0x30 ... 0x39: /* ['0' - '9'] */
1269 return parser_action(parser, raw,
1270 ACTION_PARAMparser_param);
1271 case 0x3a: /* ':' */
1272 return parser_action(parser, raw,
1273 ACTION_FINISH_SUBPARAMparser_finish_subparam);
1274 case 0x3b: /* ';' */
1275 return parser_action(parser, raw,
1276 ACTION_FINISH_PARAMparser_finish_param);
1277 case 0x3c ... 0x3f: /* ['<' - '?'] */
1278 return parser_transition_no_action(parser, raw, STATE_DCS_IGNORE);
1279 case 0x40 ... 0x7e: /* ['@' - '~'] */
1280 return parser_transition(parser, raw, STATE_DCS_PASS,
1281 ACTION_DCS_CONSUMEparser_dcs_consume);
1282 case 0x9c: /* ST */
1283 return parser_transition(parser, raw, STATE_GROUND,
1284 ACTION_IGNOREparser_ignore);
1285 }
1286
1287 return parser_transition(parser, raw,
1288 STATE_DCS_PASS, ACTION_DCS_CONSUMEparser_dcs_consume);
1289 case STATE_DCS_INT:
1290 switch (raw) {
1291 case 0x00 ... 0x1a: /* C0 \ { ESC } */
1292 case 0x1c ... 0x1f:
1293 return parser_action(parser, raw,
1294 ACTION_IGNOREparser_ignore);
1295 case 0x1b: /* ESC */
1296 return parser_transition(parser, raw, STATE_ESC,
1297 ACTION_CLEAR_INTparser_clear_int);
1298 case 0x20 ... 0x2f: /* [' ' - '\'] */
1299 return parser_action(parser, raw,
1300 ACTION_COLLECT_DCSparser_collect_csi);
1301 case 0x30 ... 0x3f: /* ['0' - '?'] */
1302 return parser_transition_no_action(parser, raw, STATE_DCS_IGNORE);
1303 case 0x40 ... 0x7e: /* ['@' - '~'] */
1304 return parser_transition(parser, raw, STATE_DCS_PASS,
1305 ACTION_DCS_CONSUMEparser_dcs_consume);
1306 case 0x9c: /* ST */
1307 return parser_transition(parser, raw, STATE_GROUND,
1308 ACTION_IGNOREparser_ignore);
1309 }
1310
1311 return parser_transition(parser, raw,
1312 STATE_DCS_PASS, ACTION_DCS_CONSUMEparser_dcs_consume);
1313 case STATE_DCS_PASS:
1314 switch (raw) {
1315 case 0x00 ... 0x1a: /* ASCII \ { ESC } */
1316 case 0x1c ... 0x7f:
1317 return parser_action(parser, raw,
1318 ACTION_DCS_COLLECTparser_dcs_collect);
1319 case 0x1b: /* ESC */
1320 return parser_transition_no_action(parser, raw, STATE_DCS_PASS_ESC);
1321 case 0x9c: /* ST */
1322 return parser_transition(parser, raw, STATE_GROUND,
1323 ACTION_DCS_DISPATCHparser_dcs);
1324 }
1325
1326 return parser_action(parser, raw,
1327 ACTION_DCS_COLLECTparser_dcs_collect);
1328 case STATE_DCS_IGNORE:
1329 switch (raw) {
1330 case 0x00 ... 0x1a: /* ASCII \ { ESC } */
1331 case 0x1c ... 0x7f:
1332 return parser_nop(parser, raw);
1333 case 0x1b: /* ESC */
1334 return parser_transition(parser, raw, STATE_ESC,
1335 ACTION_CLEAR_INTparser_clear_int);
1336 case 0x9c: /* ST */
1337 return parser_transition_no_action(parser, raw, STATE_GROUND);
1338 }
1339
1340 return parser_nop(parser, raw);
1341 case STATE_OSC_STRING:
1342 switch (raw) {
1343 case 0x00 ... 0x06: /* C0 \ { BEL, ESC } */
1344 case 0x08 ... 0x1a:
1345 case 0x1c ... 0x1f:
1346 return parser_nop(parser, raw);
1347 case 0x1b: /* ESC */
1348 return parser_transition_no_action(parser, raw, STATE_OSC_STRING_ESC);
1349 case 0x20 ... 0x7f: /* [' ' - DEL] */
1350 return parser_action(parser, raw,
1351 ACTION_OSC_COLLECTparser_osc_collect);
1352 case 0x07: /* BEL */
1353 case 0x9c: /* ST */
1354 return parser_transition(parser, raw, STATE_GROUND,
1355 ACTION_OSC_DISPATCHparser_osc);
1356 }
1357
1358 return parser_action(parser, raw,
1359 ACTION_OSC_COLLECTparser_osc_collect);
1360 case STATE_ST_IGNORE:
1361 switch (raw) {
1362 case 0x00 ... 0x1a: /* ASCII \ { ESC } */
1363 case 0x1c ... 0x7f:
1364 return parser_nop(parser, raw);
1365 case 0x1b: /* ESC */
1366 return parser_transition(parser, raw, STATE_ESC,
1367 ACTION_CLEAR_INTparser_clear_int);
1368 case 0x9c: /* ST */
1369 return parser_transition(parser, raw,
1370 STATE_GROUND, ACTION_IGNOREparser_ignore);
1371 }
1372
1373 return parser_nop(parser, raw);
1374 case STATE_SCI:
1375 switch (raw) {
1376 case 0x1b: /* ESC */
1377 return parser_transition(parser, raw,
1378 STATE_ESC, ACTION_CLEAR_INTparser_clear_int);
1379 case 0x08 ... 0x0d: /* BS, HT, LF, VT, FF, CR */
1380 case 0x20 ... 0x7e: /* [' ' - '~'] */
1381 return parser_transition(parser, raw, STATE_GROUND,
1382 ACTION_SCI_DISPATCHparser_sci);
1383 }
1384
1385 return parser_transition(parser, raw, STATE_GROUND,
1386 ACTION_IGNOREparser_ignore);
1387 }
1388
1389 g_assert_not_reached()do { g_assertion_message_expr ("BTE", "../src/parser.cc", 1389
, ((const char*) (__PRETTY_FUNCTION__)), __null); } while (0)
;
This statement is never executed
1390 return BTE_SEQ_NONE;
1391}
1392
1393int
1394bte_parser_feed(bte_parser_t* parser,
1395 uint32_t raw)
1396{
1397 /*
1398 * Notes:
1399 * * DEC treats GR codes as GL. We don't do that as we require UTF-8
1400 * as charset and, thus, it doesn't make sense to treat GR special.
1401 * * During control sequences, unexpected C1 codes cancel the sequence
1402 * and immediately start a new one. C0 codes, however, may or may not
1403 * be ignored/executed depending on the sequence.
1404 */
1405
1406 switch (raw) {
1407 case 0x18: /* CAN */
1408 return parser_transition(parser, raw,
1409 STATE_GROUND, ACTION_IGNOREparser_ignore);
1410 case 0x1a: /* SUB */
1411 return parser_transition(parser, raw,
1412 STATE_GROUND, ACTION_EXECUTEparser_execute);
1413 case 0x7f: /* DEL */
1414 return parser_nop(parser, raw);
1415 case 0x80 ... 0x8f: /* C1 \ {DCS, SOS, SCI, CSI, ST, OSC, PM, APC} */
1416 case 0x91 ... 0x97:
1417 case 0x99:
1418 return parser_transition(parser, raw,
1419 STATE_GROUND, ACTION_EXECUTEparser_execute);
1420 case 0x98: /* SOS */
1421 case 0x9e: /* PM */
1422 case 0x9f: /* APC */
1423 return parser_transition_no_action(parser, raw, STATE_ST_IGNORE);
1424 // FIXMEchpe shouldn't this use ACTION_CLEAR?
1425 case 0x90: /* DCS */
1426 return parser_transition(parser, raw,
1427 STATE_DCS_ENTRY, ACTION_DCS_STARTparser_dcs_start);
1428 case 0x9a: /* SCI */
1429 return parser_transition(parser, raw,
1430 STATE_SCI, ACTION_CLEARparser_clear);
1431 case 0x9d: /* OSC */
1432 return parser_transition(parser, raw,
1433 STATE_OSC_STRING, ACTION_OSC_STARTparser_osc_start);
1434 case 0x9b: /* CSI */
1435 return parser_transition(parser, raw,
1436 STATE_CSI_ENTRY, ACTION_CLEAR_INT_AND_PARAMSparser_clear_int_and_params);
1437 default:
1438 return parser_feed_to_state(parser, raw);
1439 }
1440}
1441
1442void
1443bte_parser_reset(bte_parser_t* parser)
1444{
1445 parser_transition(parser, 0, STATE_GROUND, ACTION_IGNOREparser_ignore);
1446}