1 /*
2 * Copyright © 2017, 2018 Christian Persch
3 *
4 * This library is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <string.h>
21
22 #include <algorithm>
23 #include <cstddef>
24 #include <cstdint>
25 #include <string>
26 #include <vector>
27
28 using namespace std::literals;
29
30 #include <glib.h>
31
32 #include "parser.hh"
33 #include "parser-glue.hh"
34 #include "parser-charset-tables.hh"
35
36 #ifdef PARSER_INCLUDE_NOP
37 #define _VTE_NOP(...) _VTE_CMD(__VA_ARGS__)
38 #define _VTE_NOQ(...) _VTE_SEQ(__VA_ARGS__)
39 #else
40 #define _VTE_NOP(...)
41 #define _VTE_NOQ(...)
42 #endif
43
44 using namespace vte::parser;
45
46 Parser parser{};
47 Sequence seq{parser};
48
49 #if 0
50 static char const*
51 seq_to_str(unsigned int type)
52 {
53 switch (type) {
54 case VTE_SEQ_NONE: return "NONE";
55 case VTE_SEQ_IGNORE: return "IGNORE";
56 case VTE_SEQ_GRAPHIC: return "GRAPHIC";
57 case VTE_SEQ_CONTROL: return "CONTROL";
58 case VTE_SEQ_ESCAPE: return "ESCAPE";
59 case VTE_SEQ_CSI: return "CSI";
60 case VTE_SEQ_DCS: return "DCS";
61 case VTE_SEQ_OSC: return "OSC";
62 case VTE_SEQ_APC: return "APC";
63 case VTE_SEQ_PM: return "PM";
64 case VTE_SEQ_SOS: return "SOS";
65 case VTE_SEQ_SCI: return "SCI";
66 default:
67 g_assert_not_reached();
68 }
69 }
70
71 static char const*
72 cmd_to_str(unsigned int command)
73 {
74 switch (command) {
75 #define _VTE_CMD(cmd) case VTE_CMD_##cmd: return #cmd;
76 #include "parser-cmd.hh"
77 #undef _VTE_CMD
78 default:
79 static char buf[32];
80 snprintf(buf, sizeof(buf), "UNKOWN(%u)", command);
81 return buf;
82 }
83 }
84
85 static char const*
86 charset_to_str(unsigned int cs)
87 {
88 switch (cs) {
89 #define _VTE_CHARSET_PASTE(name) case VTE_CHARSET_##name: return #name;
90 #define _VTE_CHARSET(name) _VTE_CHARSET_PASTE(name)
91 #define _VTE_CHARSET_ALIAS_PASTE(name1,name2)
92 #define _VTE_CHARSET_ALIAS(name1,name2)
93 #include "parser-charset.hh"
94 #undef _VTE_CHARSET_PASTE
95 #undef _VTE_CHARSET
96 #undef _VTE_CHARSET_ALIAS_PASTE
97 #undef _VTE_CHARSET_ALIAS
98 default:
99 static char buf[32];
100 snprintf(buf, sizeof(buf), "UNKOWN(%u)", cs);
101 return buf;
102 }
103 }
104 #endif
105
106 static const char c0str[][6] = {
107 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
108 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
109 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
110 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
111 "SPACE"
112 };
113
114 static const char c1str[][5] = {
115 "DEL",
116 "0x80", "0x81", "BPH", "NBH", "0x84", "NEL", "SSA", "ESA",
117 "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
118 "DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA",
119 "SOS", "0x99", "SCI", "CSI", "ST", "OSC", "PM", "APC"
120 };
121
122 static void
print_escaped(std::u32string const & s)123 print_escaped(std::u32string const& s)
124 {
125 for (auto it : s) {
126 uint32_t c = (char32_t)it;
127
128 if (c <= 0x20)
129 g_print("%s ", c0str[c]);
130 else if (c < 0x7f)
131 g_print("%c ", c);
132 else if (c < 0xa0)
133 g_print("%s ", c1str[c - 0x7f]);
134 else
135 g_print("U+%04X", c);
136 }
137 g_print("\n");
138 }
139
140 #if 0
141 static void
142 print_seq()
143 {
144 auto c = seq.terminator();
145 if (seq.command() == VTE_CMD_GRAPHIC) {
146 char buf[7];
147 buf[g_unichar_to_utf8(c, buf)] = 0;
148 g_print("%s U+%04X [%s]\n", cmd_to_str(seq.command()),
149 c,
150 g_unichar_isprint(c) ? buf : "�");
151 } else {
152 g_print("%s", cmd_to_str(seq.command()));
153 if (seq.size()) {
154 g_print(" ");
155 for (unsigned int i = 0; i < seq.size(); i++) {
156 if (i > 0)
157 g_print(";");
158 g_print("%d", seq.param(i));
159 }
160 }
161 g_print("\n");
162 }
163 }
164 #endif
165
166 class vte_seq_builder : public u32SequenceBuilder {
167 public:
vte_seq_builder(unsigned int type,uint32_t f)168 vte_seq_builder(unsigned int type,
169 uint32_t f)
170 : u32SequenceBuilder(type, f)
171 {
172 }
173
vte_seq_builder(unsigned int type,u32SequenceBuilder::string_type const & str)174 vte_seq_builder(unsigned int type,
175 u32SequenceBuilder::string_type const& str)
176 : u32SequenceBuilder(type)
177 {
178 set_string(str);
179 }
180
set_intermediates(uint32_t * i,unsigned int ni)181 void set_intermediates(uint32_t* i,
182 unsigned int ni) noexcept
183 {
184 for (unsigned int n = 0; n < ni; ++n)
185 append_intermediate(i[n]);
186 }
187
188
set_params(int * params,unsigned int n)189 void set_params(int* params,
190 unsigned int n) noexcept
191 {
192 for (unsigned int i = 0; i < n; ++i)
193 append_param(params[i]);
194 }
195
print(bool c1=false) const196 void print(bool c1 = false) const noexcept
197 {
198 std::u32string s;
199 to_string(s, c1);
200 print_escaped(s);
201 }
202 };
203
204 static int
feed_parser(std::u32string const & s)205 feed_parser(std::u32string const& s)
206 {
207 int rv = VTE_SEQ_NONE;
208 for (auto it : s) {
209 rv = parser.feed((uint32_t)(char32_t)it);
210 if (rv < 0)
211 break;
212 }
213 return rv;
214 }
215
216 static int
feed_parser(vte_seq_builder & b,bool c1=false)217 feed_parser(vte_seq_builder& b,
218 bool c1 = false)
219 {
220 std::u32string s;
221 b.to_string(s, c1);
222
223 return feed_parser(s);
224 }
225
226 static void
test_seq_arg(void)227 test_seq_arg(void)
228 {
229 /* Basic test */
230 vte_seq_arg_t arg = VTE_SEQ_ARG_INIT_DEFAULT;
231 g_assert_false(vte_seq_arg_started(arg));
232 g_assert_true(vte_seq_arg_default(arg));
233
234 vte_seq_arg_push(&arg, '1');
235 vte_seq_arg_push(&arg, '2');
236 vte_seq_arg_push(&arg, '3');
237 vte_seq_arg_finish(&arg);
238
239 g_assert_cmpint(vte_seq_arg_value(arg), ==, 123);
240 g_assert_false(vte_seq_arg_default(arg));
241
242 /* Test max value */
243 arg = VTE_SEQ_ARG_INIT_DEFAULT;
244 vte_seq_arg_push(&arg, '6');
245 vte_seq_arg_push(&arg, '5');
246 vte_seq_arg_push(&arg, '5');
247 vte_seq_arg_push(&arg, '3');
248 vte_seq_arg_push(&arg, '6');
249 vte_seq_arg_finish(&arg);
250
251 g_assert_cmpint(vte_seq_arg_value(arg), ==, 65535);
252 }
253
254 static void
test_seq_string(void)255 test_seq_string(void)
256 {
257 vte_seq_string_t str;
258 vte_seq_string_init(&str);
259
260 size_t len;
261 auto buf = vte_seq_string_get(&str, &len);
262 g_assert_cmpuint(len, ==, 0);
263
264 for (unsigned int i = 0; i < VTE_SEQ_STRING_MAX_CAPACITY; ++i) {
265 auto rv = vte_seq_string_push(&str, 0xfffdU);
266 g_assert_true(rv);
267
268 buf = vte_seq_string_get(&str, &len);
269 g_assert_cmpuint(len, ==, i + 1);
270 }
271
272 /* Try one more */
273 auto rv = vte_seq_string_push(&str, 0xfffdU);
274 g_assert_false(rv);
275
276 buf = vte_seq_string_get(&str, &len);
277 for (unsigned int i = 0; i < len; i++)
278 g_assert_cmpuint(buf[i], ==, 0xfffdU);
279
280 vte_seq_string_reset(&str);
281 buf = vte_seq_string_get(&str, &len);
282 g_assert_cmpuint(len, ==, 0);
283
284 vte_seq_string_free(&str);
285 }
286
287 static void
test_seq_control(void)288 test_seq_control(void)
289 {
290 static struct {
291 uint32_t c;
292 unsigned int cmd;
293 } const controls [] = {
294 #define _VTE_SEQ(cmd,type,f,pi,ni,i0,flags) { f, VTE_CMD_##cmd },
295 #include "parser-c01.hh"
296 #undef _VTE_SEQ
297 };
298
299 for (unsigned int i = 0; i < G_N_ELEMENTS(controls); i++) {
300 parser.reset();
301 auto rv = parser.feed(controls[i].c);
302 g_assert_cmpuint(rv, ==, VTE_SEQ_CONTROL);
303 g_assert_cmpuint(controls[i].cmd, ==, seq.command());
304 }
305 }
306
307 static void
test_seq_esc_invalid(void)308 test_seq_esc_invalid(void)
309 {
310 /* Tests invalid ESC 0/n and ESC 1/n sequences, which should never result in
311 * an VTE_SEQ_ESCAPE type sequence, but instead always in the C0 control.
312 */
313 for (uint32_t f = 0x0; f < 0x20; f++) {
314 parser.reset();
315
316 vte_seq_builder b{VTE_SEQ_ESCAPE, f};
317 auto rv = feed_parser(b);
318 g_assert_cmpint(rv, !=, VTE_SEQ_ESCAPE);
319 }
320 }
321
322 static void
test_seq_esc(uint32_t f,uint32_t i[],unsigned int ni)323 test_seq_esc(uint32_t f,
324 uint32_t i[],
325 unsigned int ni)
326 {
327 vte_seq_builder b{VTE_SEQ_ESCAPE, f};
328 b.set_intermediates(i, ni);
329
330 parser.reset();
331 auto rv = feed_parser(b);
332 if (rv != VTE_SEQ_ESCAPE)
333 return;
334
335 b.assert_equal(seq);
336 }
337
338 static void
test_seq_esc_nF(void)339 test_seq_esc_nF(void)
340 {
341 /* Tests nF sequences, that is ESC 2/n [2/m..] F with F being 3/0..7/14.
342 * They could have any number of itermediates, but we only test up to 4.
343 */
344
345 uint32_t i[4];
346 for (uint32_t f = 0x30; f < 0x7f; f++) {
347 test_seq_esc(f, i, 0);
348 for (i[0] = 0x20; i[0] < 0x30; i[0]++) {
349 test_seq_esc(f, i, 1);
350 for (i[1] = 0x20; i[1] < 0x30; i[1]++) {
351 test_seq_esc(f, i, 2);
352 for (i[2] = 0x20; i[2] < 0x30; i[2]++) {
353 test_seq_esc(f, i, 3);
354 for (i[3] = 0x20; i[3] < 0x30; i[3]++) {
355 test_seq_esc(f, i, 4);
356 }
357 }
358 }
359 }
360 }
361 }
362
363 static void
test_seq_esc_charset(uint32_t f,uint32_t i[],unsigned int ni,unsigned int cmd,unsigned int cs,unsigned int slot)364 test_seq_esc_charset(uint32_t f, /* final */
365 uint32_t i[], /* intermediates */
366 unsigned int ni, /* number of intermediates */
367 unsigned int cmd, /* expected command */
368 unsigned int cs /* expected charset */,
369 unsigned int slot /* expected slot */)
370 {
371 vte_seq_builder b{VTE_SEQ_ESCAPE, f};
372 b.set_intermediates(i, ni);
373
374 parser.reset();
375 auto rv = feed_parser(b);
376 g_assert_cmpint(rv, ==, VTE_SEQ_ESCAPE);
377 b.assert_equal(seq);
378
379 g_assert_cmpint(seq.command(), ==, cmd);
380 g_assert_cmpint(seq.charset(), ==, cs);
381 g_assert_cmpint(seq.slot(), ==, slot);
382 }
383
384 static void
test_seq_esc_charset(uint32_t i[],unsigned int ni,uint8_t const * const table,unsigned int ntable,uint32_t ts,unsigned int cmd,unsigned int defaultcs,unsigned int slot)385 test_seq_esc_charset(uint32_t i[], /* intermediates */
386 unsigned int ni, /* number of intermediates */
387 uint8_t const* const table, /* table */
388 unsigned int ntable, /* number of table entries */
389 uint32_t ts, /* start of table */
390 unsigned int cmd, /* expected command */
391 unsigned int defaultcs /* default charset */,
392 unsigned int slot /* expected slot */)
393 {
394 for (uint32_t f = 0x30; f < 0x7f; f++) {
395 int cs;
396
397 if (f >= ts && f < (ts + ntable))
398 cs = table[f - ts];
399 else if (f == 0x7e &&
400 cmd != VTE_CMD_DOCS &&
401 defaultcs != VTE_CHARSET_DRCS)
402 cs = VTE_CHARSET_EMPTY;
403 else
404 cs = defaultcs;
405
406 test_seq_esc_charset(f, i, ni, cmd, cs, slot);
407 }
408 }
409
410 static void
test_seq_esc_charset_94(void)411 test_seq_esc_charset_94(void)
412 {
413 uint32_t i[4];
414
415 /* Single byte 94-sets */
416 for (i[0] = 0x28; i[0] <= 0x2b; i[0]++) {
417 int slot = i[0] - 0x28;
418
419 test_seq_esc_charset(i, 1,
420 charset_graphic_94,
421 G_N_ELEMENTS(charset_graphic_94),
422 0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
423
424 i[1] = 0x20;
425 test_seq_esc_charset(i, 2, nullptr, 0, 0,
426 VTE_CMD_GnDm, VTE_CHARSET_DRCS, slot);
427
428 i[1] = 0x21;
429 test_seq_esc_charset(i, 2,
430 charset_graphic_94_with_2_1,
431 G_N_ELEMENTS(charset_graphic_94_with_2_1),
432 0x40, VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
433
434 i[1] = 0x22;
435 test_seq_esc_charset(i, 2,
436 charset_graphic_94_with_2_2,
437 G_N_ELEMENTS(charset_graphic_94_with_2_2),
438 0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
439
440 i[1] = 0x23;
441 test_seq_esc_charset(i, 2, nullptr, 0,
442 0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
443
444 /* 2/4 is multibyte charsets */
445
446 i[1] = 0x25;
447 test_seq_esc_charset(i, 2,
448 charset_graphic_94_with_2_5,
449 G_N_ELEMENTS(charset_graphic_94_with_2_5),
450 0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
451
452 i[1] = 0x26;
453 test_seq_esc_charset(i, 2,
454 charset_graphic_94_with_2_6,
455 G_N_ELEMENTS(charset_graphic_94_with_2_6),
456 0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
457
458 i[1] = 0x27;
459 test_seq_esc_charset(i, 2, nullptr, 0, 0,
460 VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
461 }
462 }
463
464 static void
test_seq_esc_charset_96(void)465 test_seq_esc_charset_96(void)
466 {
467 uint32_t i[4];
468
469 /* Single byte 96-sets */
470 for (i[0] = 0x2d; i[0] <= 0x2f; i[0]++) {
471 int slot = i[0] - 0x2c;
472
473 test_seq_esc_charset(i, 1,
474 charset_graphic_96,
475 G_N_ELEMENTS(charset_graphic_96),
476 0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
477
478 i[1] = 0x20;
479 test_seq_esc_charset(i, 2, nullptr, 0, 0,
480 VTE_CMD_GnDm, VTE_CHARSET_DRCS, slot);
481
482 /* 2/4 is multibyte charsets, 2/5 is DOCS. Other indermediates may be present
483 * in Fp sequences, but none are actually in use.
484 */
485 for (i[1] = 0x21; i[1] < 0x28; i[1]++) {
486 if (i[1] == 0x24 || i[1] == 0x25)
487 continue;
488
489 test_seq_esc_charset(i, 2, nullptr, 0, 0,
490 VTE_CMD_GnDm, VTE_CHARSET_NONE, slot);
491 }
492 }
493 }
494
495 static void
test_seq_esc_charset_94_n(void)496 test_seq_esc_charset_94_n(void)
497 {
498 uint32_t i[4];
499
500 /* Multibyte 94-sets */
501 i[0] = 0x24;
502 for (i[1] = 0x28; i[1] <= 0x2b; i[1]++) {
503 int slot = i[1] - 0x28;
504
505 test_seq_esc_charset(i, 2,
506 charset_graphic_94_n,
507 G_N_ELEMENTS(charset_graphic_94_n),
508 0x30, VTE_CMD_GnDMm, VTE_CHARSET_NONE, slot);
509
510 i[2] = 0x20;
511 test_seq_esc_charset(i, 3, nullptr, 0, 0,
512 VTE_CMD_GnDMm, VTE_CHARSET_DRCS, slot);
513
514 i[2] = 0x21;
515 test_seq_esc_charset(i, 3,
516 charset_graphic_94_n_with_2_1,
517 G_N_ELEMENTS(charset_graphic_94_n_with_2_1),
518 0x30, VTE_CMD_GnDMm, VTE_CHARSET_NONE, slot);
519
520 /* There could be one more intermediate byte. */
521 for (i[2] = 0x22; i[2] < 0x28; i[2]++) {
522 if (i[2] == 0x24) /* TODO */
523 continue;
524
525 test_seq_esc_charset(i, 3, nullptr, 0, 0,
526 VTE_CMD_GnDMm, VTE_CHARSET_NONE, slot);
527 }
528 }
529
530 /* As a special exception, ESC 2/4 4/[012] are also possible */
531 test_seq_esc_charset(0x40, i, 1, VTE_CMD_GnDMm, charset_graphic_94_n[0x40 - 0x30], 0);
532 test_seq_esc_charset(0x41, i, 1, VTE_CMD_GnDMm, charset_graphic_94_n[0x41 - 0x30], 0);
533 test_seq_esc_charset(0x42, i, 1, VTE_CMD_GnDMm, charset_graphic_94_n[0x42 - 0x30], 0);
534 }
535
536 static void
test_seq_esc_charset_96_n(void)537 test_seq_esc_charset_96_n(void)
538 {
539 uint32_t i[4];
540
541 /* Multibyte 94-sets */
542 i[0] = 0x24;
543 for (i[1] = 0x2d; i[1] <= 0x2f; i[1]++) {
544 int slot = i[1] - 0x2c;
545
546 test_seq_esc_charset(i, 2, nullptr, 0, 0,
547 VTE_CMD_GnDMm, VTE_CHARSET_NONE, slot);
548
549 i[2] = 0x20;
550 test_seq_esc_charset(i, 3, nullptr, 0, 0,
551 VTE_CMD_GnDMm, VTE_CHARSET_DRCS, slot);
552
553 /* There could be one more intermediate byte. */
554 for (i[2] = 0x21; i[2] < 0x28; i[2]++) {
555 test_seq_esc_charset(i, 3, nullptr, 0, 0,
556 VTE_CMD_GnDMm, VTE_CHARSET_NONE, slot);
557 }
558 }
559 }
560
561 static void
test_seq_esc_charset_control(void)562 test_seq_esc_charset_control(void)
563 {
564 uint32_t i[4];
565
566 /* C0 controls: ESC 2/1 F */
567 i[0] = 0x21;
568 test_seq_esc_charset(i, 1,
569 charset_control_c0,
570 G_N_ELEMENTS(charset_control_c0),
571 0x40, VTE_CMD_CnD, VTE_CHARSET_NONE, 0);
572
573 /* C1 controls: ESC 2/2 F */
574 i[0] = 0x22;
575 test_seq_esc_charset(i, 1,
576 charset_control_c1,
577 G_N_ELEMENTS(charset_control_c1),
578 0x40, VTE_CMD_CnD, VTE_CHARSET_NONE, 1);
579 }
580
581 static void
test_seq_esc_charset_other(void)582 test_seq_esc_charset_other(void)
583 {
584 uint32_t i[4];
585
586 /* Other coding systems: ESC 2/5 F or ESC 2/5 I F */
587 i[0] = 0x25;
588 test_seq_esc_charset(i, 1,
589 charset_ocs,
590 G_N_ELEMENTS(charset_ocs),
591 0x30, VTE_CMD_DOCS, VTE_CHARSET_NONE, 0);
592
593 i[1] = 0x20;
594 test_seq_esc_charset(i, 2,
595 charset_ocs_with_2_0,
596 G_N_ELEMENTS(charset_ocs_with_2_0),
597 0x30, VTE_CMD_DOCS, VTE_CHARSET_NONE, 0);
598
599 i[1] = 0x2f;
600 test_seq_esc_charset(i, 2,
601 charset_ocs_with_2_15,
602 G_N_ELEMENTS(charset_ocs_with_2_15),
603 0x40, VTE_CMD_DOCS, VTE_CHARSET_NONE, 0);
604 }
605
606 static void
test_seq_esc_Fpes(void)607 test_seq_esc_Fpes(void)
608 {
609 /* Tests Fp, Fe and Ft sequences, that is ESC 3/n .. ESC 7/14 */
610
611 for (uint32_t f = 0x30; f < 0x7f; f++) {
612 parser.reset();
613
614 vte_seq_builder b{VTE_SEQ_ESCAPE, f};
615
616 auto rv = feed_parser(b);
617 int expected_rv;
618 switch (f) {
619 case 'P': /* DCS */
620 case 'X': /* SOS */
621 case 'Z': /* SCI */
622 case '_': /* APC */
623 case '[': /* CSI */
624 case ']': /* OSC */
625 case '^': /* PM */
626 expected_rv = VTE_SEQ_NONE;
627 break;
628 default:
629 expected_rv = VTE_SEQ_ESCAPE;
630 break;
631 }
632 g_assert_cmpint(rv, ==, expected_rv);
633 if (rv != VTE_SEQ_NONE)
634 b.assert_equal(seq);
635 }
636 }
637
638 static void
test_seq_esc_known(uint32_t f,uint32_t i,unsigned int cmd)639 test_seq_esc_known(uint32_t f,
640 uint32_t i,
641 unsigned int cmd)
642 {
643 vte_seq_builder b{VTE_SEQ_ESCAPE, f};
644 if (i != 0)
645 b.set_intermediates(&i, 1);
646
647 auto rv = feed_parser(b);
648 g_assert_cmpint(rv, ==, VTE_SEQ_ESCAPE);
649 g_assert_cmpint(seq.command(), ==, cmd);
650 }
651
652 static void
test_seq_esc_known(void)653 test_seq_esc_known(void)
654 {
655 parser.reset();
656
657 #define _VTE_SEQ(cmd,type,f,p,ni,i,flags) \
658 test_seq_esc_known(f, VTE_SEQ_INTERMEDIATE_CHAR_##i, VTE_CMD_##cmd);
659 #include "parser-esc.hh"
660 #undef _VTE_SEQ
661 }
662
663 static void
test_seq_csi(uint32_t f,uint32_t p,vte_seq_arg_t params[16],uint32_t i[4],unsigned int ni)664 test_seq_csi(uint32_t f,
665 uint32_t p,
666 vte_seq_arg_t params[16],
667 uint32_t i[4],
668 unsigned int ni)
669 {
670 vte_seq_builder b{VTE_SEQ_CSI, f};
671 b.set_intermediates(i, ni);
672 b.set_param_intro(p);
673
674 int expected_rv = (f & 0xF0) == 0x30 ? VTE_SEQ_NONE : VTE_SEQ_CSI;
675
676 for (unsigned int n = 0; n <= 16; n++) {
677 b.reset_params();
678 b.set_params(params, n);
679
680 parser.reset();
681 /* First with C0 CSI */
682 auto rv = feed_parser(b, false);
683 g_assert_cmpint(rv, ==, expected_rv);
684 if (rv != VTE_SEQ_NONE)
685 b.assert_equal_full(seq);
686
687 /* Now with C1 CSI */
688 rv = feed_parser(b, true);
689 if (rv != VTE_SEQ_NONE)
690 b.assert_equal_full(seq);
691 }
692 }
693
694 static void
test_seq_csi(uint32_t p,vte_seq_arg_t params[16])695 test_seq_csi(uint32_t p,
696 vte_seq_arg_t params[16])
697 {
698 uint32_t i[4];
699 for (uint32_t f = 0x30; f < 0x7f; f++) {
700 test_seq_csi(f, p, params, i, 0);
701 for (i[0] = 0x20; i[0] < 0x30; i[0]++) {
702 test_seq_csi(f, p, params, i, 1);
703 for (i[1] = 0x20; i[1] < 0x30; i[1]++) {
704 test_seq_csi(f, p, params, i, 2);
705 }
706 }
707 }
708 }
709
710 static void
test_seq_csi(vte_seq_arg_t params[16])711 test_seq_csi(vte_seq_arg_t params[16])
712 {
713 test_seq_csi(0, params);
714 for (uint32_t p = 0x3c; p <= 0x3f; p++)
715 test_seq_csi(p, params);
716 }
717
718 static void
test_seq_csi(void)719 test_seq_csi(void)
720 {
721 /* Tests CSI sequences, that is sequences of the form
722 * CSI P...P I...I F
723 * with parameter bytes P from 3/0..3/15, intermediate bytes I from 2/0..2/15 and
724 * final byte F from 4/0..7/14.
725 * There could be any number of intermediate bytes, but we only test up to 2.
726 * There could be any number of extra params bytes, but we only test up to 1.
727 * CSI can be either the C1 control itself, or ESC [
728 */
729 vte_seq_arg_t params1[16]{ -1, 0, 1, 9, 10, 99, 100, 999,
730 1000, 9999, 10000, 65534, 65535, 65536, -1, -1 };
731 test_seq_csi(params1);
732
733 vte_seq_arg_t params2[16]{ 1, -1, -1, -1, 1, -1, 1, 1,
734 1, -1, -1, -1, -1, 1, 1, 1 };
735 test_seq_csi(params2);
736 }
737
738 static void
test_seq_sci(uint32_t f,bool valid)739 test_seq_sci(uint32_t f,
740 bool valid)
741 {
742 vte_seq_builder b{VTE_SEQ_SCI, f};
743
744 /* First with C0 SCI */
745 auto rv = feed_parser(b, false);
746 if (valid) {
747 g_assert_cmpint(rv, ==, VTE_SEQ_SCI);
748 b.assert_equal_full(seq);
749 } else
750 g_assert_cmpint(rv, !=, VTE_SEQ_SCI);
751
752 /* Now with C1 SCI */
753 rv = feed_parser(b, true);
754 if (valid) {
755 g_assert_cmpint(rv, ==, VTE_SEQ_SCI);
756 b.assert_equal_full(seq);
757 } else
758 g_assert_cmpint(rv, !=, VTE_SEQ_SCI);
759 }
760
761 static void
test_seq_sci(void)762 test_seq_sci(void)
763 {
764 /* Tests SCI sequences, that is sequences of the form SCI F
765 * with final byte 0/8..0/13 or 2/0..7/14
766 * SCI can be either the C1 control itself, or ESC Z
767 */
768 parser.reset();
769
770 for (uint32_t f = 0x8; f <= 0xd; ++f)
771 test_seq_sci(f, true);
772 for (uint32_t f = 0x20; f <= 0x7e; ++f)
773 test_seq_sci(f, true);
774 for (uint32_t f = 0x7f; f <= 0xff; ++f)
775 test_seq_sci(f, false);
776 }
777
778 G_GNUC_UNUSED
779 static void
test_seq_sci_known(uint32_t f,unsigned int cmd)780 test_seq_sci_known(uint32_t f,
781 unsigned int cmd)
782 {
783 vte_seq_builder b{VTE_SEQ_SCI, f};
784
785 auto rv = feed_parser(b);
786 g_assert_cmpint(rv, ==, VTE_SEQ_SCI);
787 g_assert_cmpint(seq.command(), ==, cmd);
788 }
789
790 static void
test_seq_sci_known(void)791 test_seq_sci_known(void)
792 {
793 parser.reset();
794
795 #define _VTE_SEQ(cmd,type,f,p,ni,i,flags) \
796 test_seq_sci_known(f, VTE_CMD_##cmd);
797 #include "parser-sci.hh"
798 #undef _VTE_SEQ
799 }
800
801 static void
test_seq_csi_known(uint32_t f,uint32_t p,uint32_t i,unsigned int cmd)802 test_seq_csi_known(uint32_t f,
803 uint32_t p,
804 uint32_t i,
805 unsigned int cmd)
806 {
807 vte_seq_builder b{VTE_SEQ_CSI, f};
808 if (p != 0)
809 b.set_param_intro(p);
810 if (i != 0)
811 b.set_intermediates(&i, 1);
812
813 auto rv = feed_parser(b);
814 g_assert_cmpint(rv, ==, VTE_SEQ_CSI);
815 g_assert_cmpint(seq.command(), ==, cmd);
816 }
817
818 static void
test_seq_csi_known(void)819 test_seq_csi_known(void)
820 {
821 parser.reset();
822
823 #define _VTE_SEQ(cmd,type,f,p,ni,i,flags) \
824 test_seq_csi_known(f, VTE_SEQ_PARAMETER_CHAR_##p, VTE_SEQ_INTERMEDIATE_CHAR_##i, VTE_CMD_##cmd);
825 #include "parser-csi.hh"
826 #undef _VTE_SEQ
827 }
828
829 static void
test_seq_dcs(uint32_t f,uint32_t p,vte_seq_arg_t params[16],uint32_t i[4],unsigned int ni,std::u32string const & str,int expected_rv=VTE_SEQ_DCS)830 test_seq_dcs(uint32_t f,
831 uint32_t p,
832 vte_seq_arg_t params[16],
833 uint32_t i[4],
834 unsigned int ni,
835 std::u32string const& str,
836 int expected_rv = VTE_SEQ_DCS)
837 {
838 vte_seq_builder b{VTE_SEQ_DCS, f};
839 b.set_intermediates(i, ni);
840 b.set_param_intro(p);
841 b.set_string(str);
842
843 int expected_rv0 = (f & 0xF0) == 0x30 || expected_rv == VTE_SEQ_NONE ? VTE_SEQ_ESCAPE /* the C0 ST */ : expected_rv;
844 int expected_rv1 = (f & 0xF0) == 0x30 ? VTE_SEQ_NONE : expected_rv;
845
846 for (unsigned int n = 0; n <= 16; n++) {
847 b.reset_params();
848 b.set_params(params, n);
849
850 parser.reset();
851
852 /* First with C0 DCS */
853 auto rv0 = feed_parser(b, false);
854 g_assert_cmpint(rv0, ==, expected_rv0);
855 if (rv0 != VTE_SEQ_ESCAPE && rv0 != VTE_SEQ_NONE)
856 b.assert_equal_full(seq);
857 if (rv0 == VTE_SEQ_ESCAPE)
858 g_assert_cmpint(seq.command(), ==, VTE_CMD_ST);
859
860 /* Now with C1 DCS */
861 auto rv1 = feed_parser(b, true);
862 g_assert_cmpint(rv1, ==, expected_rv1);
863 if (rv1 != VTE_SEQ_NONE)
864 b.assert_equal_full(seq);
865 }
866 }
867
868 static void
test_seq_dcs(uint32_t p,vte_seq_arg_t params[16],std::u32string const & str,int expected_rv=VTE_SEQ_DCS)869 test_seq_dcs(uint32_t p,
870 vte_seq_arg_t params[16],
871 std::u32string const& str,
872 int expected_rv = VTE_SEQ_DCS)
873 {
874 uint32_t i[4];
875 for (uint32_t f = 0x40; f < 0x7f; f++) {
876 test_seq_dcs(f, p, params, i, 0, str, expected_rv);
877 }
878
879 for (uint32_t f = 0x30; f < 0x7f; f++) {
880 for (i[0] = 0x20; i[0] < 0x30; i[0]++) {
881 test_seq_dcs(f, p, params, i, 1, str, expected_rv);
882 for (i[1] = 0x20; i[1] < 0x30; i[1]++) {
883 test_seq_dcs(f, p, params, i, 2, str, expected_rv);
884 }
885 }
886 }
887 }
888
889 static void
test_seq_dcs(vte_seq_arg_t params[16],std::u32string const & str,int expected_rv=VTE_SEQ_DCS)890 test_seq_dcs(vte_seq_arg_t params[16],
891 std::u32string const& str,
892 int expected_rv = VTE_SEQ_DCS)
893 {
894 test_seq_dcs(0, params, str);
895 for (uint32_t p = 0x3c; p <= 0x3f; p++)
896 test_seq_dcs(p, params, str, expected_rv);
897 }
898
899 static void
test_seq_dcs(std::u32string const & str,int expected_rv=VTE_SEQ_DCS)900 test_seq_dcs(std::u32string const& str,
901 int expected_rv = VTE_SEQ_DCS)
902 {
903 /* Tests DCS sequences, that is sequences of the form
904 * DCS P...P I...I F D...D ST
905 * with parameter bytes P from 3/0..3/15, intermediate bytes I from 2/0..2/15 and
906 * final byte F from 4/0..7/14.
907 * There could be any number of intermediate bytes, but we only test up to 2.
908 * There could be any number of extra params bytes, but we only test up to 1.
909 * DCS can be either the C1 control itself, or ESC [; ST can be either the C1
910 * control itself, or ESC \\
911 */
912 vte_seq_arg_t params1[16]{ -1, 0, 1, 9, 10, 99, 100, 999,
913 1000, 9999, 10000, 65534, 65535, 65536, -1, -1 };
914 test_seq_dcs(params1, str, expected_rv);
915
916 vte_seq_arg_t params2[16]{ 1, -1, -1, -1, 1, -1, 1, 1,
917 1, -1, -1, -1, -1, 1, 1, 1 };
918 test_seq_dcs(params2, str, expected_rv);
919 }
920
921 static void
test_seq_dcs_simple(std::u32string const & str,int expected_rv=VTE_SEQ_DCS)922 test_seq_dcs_simple(std::u32string const& str,
923 int expected_rv = VTE_SEQ_DCS)
924 {
925 vte_seq_arg_t params[16]{ 1, -1, -1, -1, 1, -1, 1, 1,
926 1, -1, -1, -1, -1, 1, 1, 1 };
927 uint32_t i[4];
928
929 test_seq_dcs(0x40, 0, params, i, 0, str, expected_rv);
930 }
931
932 static void
test_seq_dcs(void)933 test_seq_dcs(void)
934 {
935 /* Length exceeded */
936 test_seq_dcs_simple(std::u32string(VTE_SEQ_STRING_MAX_CAPACITY + 1, 0x100000), VTE_SEQ_NONE);
937
938 test_seq_dcs(U""s);
939 test_seq_dcs(U"123;TESTING"s);
940 }
941
942 static void
test_seq_dcs_known(uint32_t f,uint32_t p,uint32_t i,unsigned int cmd)943 test_seq_dcs_known(uint32_t f,
944 uint32_t p,
945 uint32_t i,
946 unsigned int cmd)
947 {
948 vte_seq_builder b{VTE_SEQ_DCS, f};
949 if (p != 0)
950 b.set_param_intro(p);
951 if (i != 0)
952 b.set_intermediates(&i, 1);
953
954 auto rv = feed_parser(b);
955 g_assert_cmpint(rv, ==, VTE_SEQ_DCS);
956 g_assert_cmpint(seq.command(), ==, cmd);
957 }
958
959 static void
test_seq_dcs_known(void)960 test_seq_dcs_known(void)
961 {
962 parser.reset();
963
964 #define _VTE_SEQ(cmd,type,f,p,ni,i,flags) \
965 test_seq_dcs_known(f, VTE_SEQ_PARAMETER_CHAR_##p, VTE_SEQ_INTERMEDIATE_CHAR_##i, VTE_CMD_##cmd);
966 #include "parser-dcs.hh"
967 #undef _VTE_SEQ
968 }
969
970 static void
test_seq_parse(char const * str)971 test_seq_parse(char const* str)
972 {
973 std::u32string s;
974 s.push_back(0x9B); /* CSI */
975 for (unsigned int i = 0; str[i]; i++)
976 s.push_back(str[i]);
977 s.push_back(0x6d); /* m = SGR */
978
979 parser.reset();
980 auto rv = feed_parser(s);
981 g_assert_cmpint(rv, ==, VTE_SEQ_CSI);
982 }
983
984 static void
test_seq_csi_param(char const * str,std::vector<int> args,std::vector<bool> args_nonfinal)985 test_seq_csi_param(char const* str,
986 std::vector<int> args,
987 std::vector<bool> args_nonfinal)
988 {
989 g_assert_cmpuint(args.size(), ==, args_nonfinal.size());
990
991 test_seq_parse(str);
992
993 if (seq.size() < VTE_PARSER_ARG_MAX)
994 g_assert_cmpuint(seq.size(), ==, args.size());
995
996 unsigned int n_final_args = 0;
997 for (unsigned int i = 0; i < seq.size(); i++) {
998 g_assert_cmpint(seq.param(i), ==, args[i]);
999
1000 auto is_nonfinal = args_nonfinal[i];
1001 if (!is_nonfinal)
1002 n_final_args++;
1003
1004 g_assert_cmpint(seq.param_nonfinal(i), ==, is_nonfinal);
1005 }
1006
1007 g_assert_cmpuint(seq.size_final(), ==, n_final_args);
1008 }
1009
1010 static void
test_seq_csi_param(void)1011 test_seq_csi_param(void)
1012 {
1013 /* Tests that CSI parameters and subparameters are parsed correctly. */
1014
1015 test_seq_csi_param("", { }, { });
1016 test_seq_csi_param(";", { -1, -1 }, { false, false });
1017 test_seq_csi_param(":", { -1, -1 }, { true, false });
1018 test_seq_csi_param(";:", { -1, -1, -1 }, { false, true, false });
1019 test_seq_csi_param("::;;", { -1, -1, -1, -1, -1 }, { true, true, false, false, false });
1020
1021 test_seq_csi_param("1;2:3:4:5:6;7:8;9:0",
1022 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 },
1023 { false, true, true, true, true, false, true, false, true, false });
1024
1025 test_seq_csi_param("1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1",
1026 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1027 { false, false, false, false, false, false, false, false,
1028 false, false, false, false, false, false, false, false });
1029
1030 test_seq_csi_param("1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
1031 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1032 { true, true, true, true, true, true, true, true,
1033 true, true, true, true, true, true, true, false });
1034
1035 }
1036
1037 static void
test_seq_csi_clear(void)1038 test_seq_csi_clear(void)
1039 {
1040 /* Check that parameters are cleared from when a sequence was aborted. */
1041
1042 vte_seq_builder b0{VTE_SEQ_CSI, 'm'};
1043 b0.set_param_intro(VTE_SEQ_PARAMETER_CHAR_WHAT);
1044 for (unsigned int i = 0; i < VTE_PARSER_ARG_MAX; ++i)
1045 b0.append_param(127 * i + 17);
1046
1047 std::u32string str0;
1048 b0.to_string(str0);
1049
1050 parser.reset();
1051 for (size_t len0 = 1; len0 <= str0.size(); ++len0) {
1052 for (unsigned int n_args = 0; n_args < VTE_PARSER_ARG_MAX; ++n_args) {
1053 feed_parser(str0.substr(0, len0));
1054
1055 vte_seq_builder b1{VTE_SEQ_CSI, 'n'};
1056 b1.set_param_intro(VTE_SEQ_PARAMETER_CHAR_GT);
1057 for (unsigned int i = 0; i < n_args; ++i)
1058 b1.append_param(257 * i + 31);
1059
1060 std::u32string str1;
1061 b1.to_string(str1);
1062
1063 auto rv = feed_parser(str1);
1064 g_assert_cmpint(rv, ==, VTE_SEQ_CSI);
1065 b1.assert_equal_full(seq);
1066 for (unsigned int n = seq.size(); n < VTE_PARSER_ARG_MAX; n++)
1067 g_assert_true(seq.param_default(n));
1068 }
1069 }
1070 }
1071
1072 static void
test_seq_csi_max(std::u32string const & start,std::u32string const & more,int expected_rv=VTE_SEQ_NONE)1073 test_seq_csi_max(std::u32string const& start,
1074 std::u32string const& more,
1075 int expected_rv = VTE_SEQ_NONE)
1076 {
1077 parser.reset();
1078 feed_parser(start);
1079 feed_parser(more);
1080 auto rv = feed_parser(U"m"s); /* final character */
1081 g_assert_cmpint(rv, ==, expected_rv);
1082 }
1083
1084 static void
test_seq_csi_max(void)1085 test_seq_csi_max(void)
1086 {
1087 /* Check that an excessive number of parameters causes the
1088 * sequence to be ignored.
1089 *
1090 * Since SequenceBuilder is limited in the same number of
1091 * parameters as the parser, can't use it directly to
1092 * produce a sequence with too may parameters.
1093 */
1094
1095 vte_seq_builder b{VTE_SEQ_CSI, 'm'};
1096 b.set_param_intro(VTE_SEQ_PARAMETER_CHAR_WHAT);
1097 for (unsigned int i = 0; i < VTE_PARSER_ARG_MAX; ++i)
1098 b.append_param(i);
1099
1100 std::u32string str;
1101 b.to_string(str);
1102
1103 /* The sequence with VTE_PARSER_ARG_MAX args must be parsed */
1104 auto rv = feed_parser(str);
1105 g_assert_cmpint(rv, ==, VTE_SEQ_CSI);
1106
1107 /* Now test that adding one more parameter (whether with an
1108 * explicit value, or default, causes the sequence to be ignored.
1109 */
1110 str.pop_back(); /* erase final character */
1111 test_seq_csi_max(str, U":"s);
1112 test_seq_csi_max(str, U";"s);
1113 test_seq_csi_max(str, U":12345"s);
1114 test_seq_csi_max(str, U";12345"s);
1115 test_seq_csi_max(str, U":12345;"s);
1116 test_seq_csi_max(str, U";12345:"s);
1117 test_seq_csi_max(str, U":12345;"s);
1118 test_seq_csi_max(str, U":12345:"s);
1119 }
1120
1121 static void
test_seq_glue_arg(char const * str,unsigned int n_args,unsigned int n_final_args)1122 test_seq_glue_arg(char const* str,
1123 unsigned int n_args,
1124 unsigned int n_final_args)
1125 {
1126 test_seq_parse(str);
1127
1128 auto raw_seq = *seq.seq_ptr();
1129 g_assert_cmpuint(seq.size(), ==, n_args);
1130 g_assert_cmpuint(raw_seq->n_args, ==, n_args);
1131 g_assert_cmpuint(seq.size_final(), ==, n_final_args);
1132 g_assert_cmpuint(raw_seq->n_final_args, ==, n_final_args);
1133
1134 g_assert_cmpuint(seq.type(), ==, raw_seq->type);
1135 g_assert_cmpuint(seq.command(), ==, raw_seq->command);
1136 g_assert_cmpuint(seq.terminator(), ==, raw_seq->terminator);
1137
1138 for (unsigned int i = 0; i < raw_seq->n_args; i++)
1139 g_assert_cmpuint(seq.param(i), ==, vte_seq_arg_value(raw_seq->args[i]));
1140 }
1141
1142 static void
test_seq_glue_arg(void)1143 test_seq_glue_arg(void)
1144 {
1145 test_seq_glue_arg(":0:1000;2;3;4;:;", 9, 6);
1146 g_assert_cmpuint(seq.cbegin(), ==, 0);
1147 g_assert_cmpuint(seq.cend(), ==, 9);
1148
1149 auto it = seq.cbegin();
1150 g_assert_cmpuint(it, ==, 0);
1151 it = seq.next(it);
1152 g_assert_cmpuint(it, ==, 3);
1153 it = seq.next(it);
1154 g_assert_cmpuint(it, ==, 4);
1155 it = seq.next(it);
1156 g_assert_cmpuint(it, ==, 5);
1157 it = seq.next(it);
1158 g_assert_cmpuint(it, ==, 6);
1159 it = seq.next(it);
1160 g_assert_cmpuint(it, ==, 8);
1161 it = seq.next(it);
1162 g_assert_cmpuint(it, ==, 9);
1163
1164 it = seq.cbegin();
1165 g_assert_cmpint(seq.param(it++), ==, -1);
1166 g_assert_cmpint(seq.param(it++), ==, 0);
1167 g_assert_cmpint(seq.param(it++), ==, 1000);
1168 g_assert_cmpint(seq.param(it++), ==, 2);
1169 g_assert_cmpint(seq.param(it++), ==, 3);
1170 g_assert_cmpint(seq.param(it++), ==, 4);
1171 g_assert_cmpint(seq.param(it++), ==, -1);
1172 g_assert_cmpint(seq.param(it++), ==, -1);
1173 g_assert_cmpint(seq.param(it++), ==, -1);
1174 g_assert_cmpint(it, ==, seq.cend());
1175
1176 it = seq.cbegin();
1177 g_assert_cmpint(seq.param(it, -2), ==, -2);
1178 g_assert_cmpint(seq.param(it, -2, 0, 100), ==, 0);
1179 it++; it++;
1180 g_assert_cmpint(seq.param(it, -2), ==, seq.param(it));
1181 g_assert_cmpint(seq.param(it, -2, 20, 100), ==, 100);
1182 g_assert_cmpint(seq.param(it, -2, 200, 2000), ==, 1000);
1183 g_assert_cmpint(seq.param(it, -2, 2000, 4000), ==, 2000);
1184
1185 int a, b, c,d ;
1186 it = seq.cbegin();
1187 g_assert_false(seq.collect(it, {&a, &b, &c}));
1188 g_assert_true(seq.collect_subparams(it, {&a}));
1189 g_assert_true(seq.collect_subparams(it, {&a, &b}));
1190 g_assert_true(seq.collect_subparams(it, {&a, &b, &c}));
1191 g_assert_cmpint(a, ==, -1);
1192 g_assert_cmpint(b, ==, 0);
1193 g_assert_cmpint(c, ==, 1000);
1194 g_assert_false(seq.collect_subparams(it, {&a, &b, &c, &d}));
1195
1196 it = seq.next(it);
1197 g_assert_true(seq.collect(it, {&a}));
1198 g_assert_true(seq.collect(it, {&a, &b}));
1199 g_assert_true(seq.collect(it, {&a, &b, &c}));
1200 g_assert_cmpint(a, ==, 2);
1201 g_assert_cmpint(b, ==, 3);
1202 g_assert_cmpint(c, ==, 4);
1203 g_assert_false(seq.collect(it, {&a, &b, &c, &d}));
1204
1205 it = seq.next(it);
1206 it = seq.next(it);
1207 it = seq.next(it);
1208 g_assert_false(seq.collect(it, {&a}));
1209 g_assert_true(seq.collect_subparams(it, {&a}));
1210 g_assert_true(seq.collect_subparams(it, {&a, &b}));
1211 g_assert_cmpint(a, ==, -1);
1212 g_assert_cmpint(b, ==, -1);
1213 g_assert_false(seq.collect_subparams(it, {&a, &b, &c}));
1214 it = seq.next(it);
1215 g_assert_true(seq.collect(it, {&a}));
1216 g_assert_cmpint(a, ==, -1);
1217 g_assert_true(seq.collect(it, {&a, &b})); /* past-the-end params are final and default */
1218 g_assert_cmpint(a, ==, -1);
1219 g_assert_cmpint(b, ==, -1);
1220 g_assert_true(seq.collect(it, {&a, &b, &c})); /* past-the-end params are final and default */
1221 g_assert_cmpint(a, ==, -1);
1222 g_assert_cmpint(b, ==, -1);
1223 g_assert_cmpint(c, ==, -1);
1224
1225 it = seq.cbegin();
1226 g_assert_cmpint(seq.collect1(it, -2), ==, -2);
1227 it = seq.next(it);
1228 g_assert_cmpint(seq.collect1(it), ==, 2);
1229 g_assert_cmpint(seq.collect1(it), ==, 2);
1230 it = seq.next(it);
1231 g_assert_cmpint(seq.collect1(it), ==, 3);
1232 it = seq.next(it);
1233 g_assert_cmpint(seq.collect1(it), ==, 4);
1234 it = seq.next(it);
1235 g_assert_cmpint(seq.collect1(it, -3), ==, -3);
1236 it = seq.next(it);
1237 g_assert_cmpint(seq.collect1(it), ==, -1);
1238 g_assert_cmpint(seq.collect1(it, 42), ==, 42);
1239 g_assert_cmpint(seq.collect1(it, -1, 0, 100), ==, 0);
1240 g_assert_cmpint(seq.collect1(it, 42, 0, 100), ==, 42);
1241 g_assert_cmpint(seq.collect1(it, 42, 0, 10), ==, 10);
1242 g_assert_cmpint(seq.collect1(it, 42, 100, 200), ==, 100);
1243 }
1244
1245 static int
feed_parser_st(vte_seq_builder & b,bool c1=false,ssize_t max_arg_str_len=-1,u32SequenceBuilder::Introducer introducer=u32SequenceBuilder::Introducer::DEFAULT,u32SequenceBuilder::ST st=u32SequenceBuilder::ST::DEFAULT)1246 feed_parser_st(vte_seq_builder& b,
1247 bool c1 = false,
1248 ssize_t max_arg_str_len = -1,
1249 u32SequenceBuilder::Introducer introducer = u32SequenceBuilder::Introducer::DEFAULT,
1250 u32SequenceBuilder::ST st = u32SequenceBuilder::ST::DEFAULT)
1251 {
1252 std::u32string s;
1253 b.to_string(s, c1, max_arg_str_len, introducer, st);
1254
1255 auto rv = feed_parser(s);
1256 if (rv != VTE_SEQ_OSC)
1257 return rv;
1258
1259 switch (st) {
1260 case u32SequenceBuilder::ST::NONE:
1261 g_assert_cmpuint(seq.st(), ==, 0);
1262 break;
1263 case u32SequenceBuilder::ST::DEFAULT:
1264 g_assert_cmpuint(seq.st(), ==, c1 ? 0x9c /* ST */ : 0x5c /* BACKSLASH */);
1265 break;
1266 case u32SequenceBuilder::ST::C0:
1267 g_assert_cmpuint(seq.st(), ==, 0x5c /* BACKSLASH */);
1268 break;
1269 case u32SequenceBuilder::ST::C1:
1270 g_assert_cmpuint(seq.st(), ==, 0x9c /* ST */);
1271 break;
1272 case u32SequenceBuilder::ST::BEL:
1273 g_assert_cmpuint(seq.st(), ==, 0x7 /* BEL */);
1274 break;
1275 }
1276
1277 return rv;
1278 }
1279
1280 static void
test_seq_osc(std::u32string const & str,int expected_rv=VTE_SEQ_OSC,bool c1=true,ssize_t max_arg_str_len=-1,u32SequenceBuilder::Introducer introducer=u32SequenceBuilder::Introducer::DEFAULT,u32SequenceBuilder::ST st=u32SequenceBuilder::ST::DEFAULT)1281 test_seq_osc(std::u32string const& str,
1282 int expected_rv = VTE_SEQ_OSC,
1283 bool c1 = true,
1284 ssize_t max_arg_str_len = -1,
1285 u32SequenceBuilder::Introducer introducer = u32SequenceBuilder::Introducer::DEFAULT,
1286 u32SequenceBuilder::ST st = u32SequenceBuilder::ST::DEFAULT)
1287 {
1288 vte_seq_builder b{VTE_SEQ_OSC, str};
1289
1290 parser.reset();
1291 auto rv = feed_parser_st(b, c1, max_arg_str_len, introducer, st);
1292 g_assert_cmpint(rv, ==, expected_rv);
1293 #if 0
1294 if (rv != VTE_SEQ_NONE)
1295 b.assert_equal(seq);
1296 #endif
1297
1298 if (expected_rv != VTE_SEQ_OSC)
1299 return;
1300
1301 if (max_arg_str_len < 0 || size_t(max_arg_str_len) == str.size())
1302 g_assert_true(seq.string() == str);
1303 else
1304 g_assert_true(seq.string() == str.substr(0, max_arg_str_len));
1305 }
1306
1307 static int
controls_match(bool c1,u32SequenceBuilder::Introducer introducer,u32SequenceBuilder::ST st,bool allow_bel,int expected_rv)1308 controls_match(bool c1,
1309 u32SequenceBuilder::Introducer introducer,
1310 u32SequenceBuilder::ST st,
1311 bool allow_bel,
1312 int expected_rv)
1313 {
1314 if (introducer == u32SequenceBuilder::Introducer::DEFAULT)
1315 introducer = c1 ? u32SequenceBuilder::Introducer::C1 : u32SequenceBuilder::Introducer::C0;
1316 if (st == u32SequenceBuilder::ST::DEFAULT)
1317 st = c1 ? u32SequenceBuilder::ST::C1 : u32SequenceBuilder::ST::C0;
1318 if ((introducer == u32SequenceBuilder::Introducer::C0 &&
1319 (st == u32SequenceBuilder::ST::C0 || (allow_bel && st == u32SequenceBuilder::ST::BEL))) ||
1320 (introducer == u32SequenceBuilder::Introducer::C1 &&
1321 st == u32SequenceBuilder::ST::C1))
1322 return expected_rv;
1323 return VTE_SEQ_IGNORE;
1324 }
1325
1326 static void
test_seq_osc(void)1327 test_seq_osc(void)
1328 {
1329 /* Simple */
1330 test_seq_osc(U""s);
1331 test_seq_osc(U"TEST"s);
1332
1333 /* String of any supported length */
1334 for (unsigned int len = 0; len < VTE_SEQ_STRING_MAX_CAPACITY; ++len)
1335 test_seq_osc(std::u32string(len, 0x10000+len));
1336
1337 /* Length exceeded */
1338 test_seq_osc(std::u32string(VTE_SEQ_STRING_MAX_CAPACITY + 1, 0x100000), VTE_SEQ_IGNORE);
1339
1340 /* Test all introducer/ST combinations */
1341 for (auto introducer : { u32SequenceBuilder::Introducer::DEFAULT,
1342 u32SequenceBuilder::Introducer::C0,
1343 u32SequenceBuilder::Introducer::C1 }) {
1344 for (auto st : {u32SequenceBuilder::ST::DEFAULT,
1345 u32SequenceBuilder::ST::C0,
1346 u32SequenceBuilder::ST::C1,
1347 u32SequenceBuilder::ST::BEL }) {
1348 for (auto c1 : { false, true }) {
1349 int expected_rv = controls_match(c1, introducer, st, true, VTE_SEQ_OSC);
1350 test_seq_osc(U"TEST"s, expected_rv, c1, -1, introducer, st);
1351 }
1352 }
1353 }
1354 }
1355
1356 static void
test_seq_glue_string(void)1357 test_seq_glue_string(void)
1358 {
1359 std::u32string str{U"TEST"s};
1360 test_seq_osc(str);
1361
1362 g_assert_true(seq.string() == str);
1363 }
1364
1365 static void
test_seq_glue_string_tokeniser(void)1366 test_seq_glue_string_tokeniser(void)
1367 {
1368 std::string str{"a;1b:17:test::b:;3;5;def;17 a;ghi;"s};
1369
1370 StringTokeniser tokeniser{str, ';'};
1371
1372 auto start = tokeniser.cbegin();
1373 auto end = tokeniser.cend();
1374
1375 auto pit = start;
1376 for (auto it : {"a"s, "1b:17:test::b:"s, "3"s, "5"s, "def"s, "17 a"s, "ghi"s, ""s}) {
1377 g_assert_true(it == *pit);
1378
1379 /* Use std::find to see if the InputIterator implementation
1380 * is complete and correct.
1381 */
1382 auto fit = std::find(start, end, it);
1383 g_assert_true(fit == pit);
1384
1385 ++pit;
1386 }
1387 g_assert_true(pit == end);
1388
1389 auto len = str.size();
1390 size_t pos = 0;
1391 pit = start;
1392 for (auto it : {1, 14, 1, 1, 3, 4, 3, 0}) {
1393 g_assert_cmpuint(it, ==, pit.size());
1394 g_assert_cmpuint(len, ==, pit.size_remaining());
1395
1396 g_assert_true(pit.string_remaining() == str.substr(pos, std::string::npos));
1397
1398 len -= it + 1;
1399 pos += it + 1;
1400
1401 ++pit;
1402 }
1403 g_assert_cmpuint(len + 1, ==, 0);
1404 g_assert_cmpuint(pos, ==, str.size() + 1);
1405
1406 pit = start;
1407 for (auto it : {-2, -2, 3, 5, -2, -2, -2, -1}) {
1408 int num;
1409 bool v = pit.number(num);
1410 if (it == -2)
1411 g_assert_false(v);
1412 else
1413 g_assert_cmpint(it, ==, num);
1414
1415 ++pit;
1416 }
1417
1418 /* Test range for */
1419 for (auto it : tokeniser)
1420 ;
1421
1422 /* Test different separator */
1423 pit = start;
1424 ++pit;
1425
1426 auto substr = *pit;
1427 StringTokeniser subtokeniser{substr, ':'};
1428
1429 auto subpit = subtokeniser.cbegin();
1430 for (auto it : {"1b"s, "17"s, "test"s, ""s, "b"s, ""s}) {
1431 g_assert_true(it == *subpit);
1432
1433 ++subpit;
1434 }
1435 g_assert_true(subpit == subtokeniser.cend());
1436
1437 /* Test another string, one that doesn't end with an empty token */
1438 std::string str2{"abc;defghi"s};
1439 StringTokeniser tokeniser2{str2, ';'};
1440
1441 g_assert_cmpint(std::distance(tokeniser2.cbegin(), tokeniser2.cend()), ==, 2);
1442 auto pit2 = tokeniser2.cbegin();
1443 g_assert_true(*pit2 == "abc"s);
1444 ++pit2;
1445 g_assert_true(*pit2 == "defghi"s);
1446 ++pit2;
1447 g_assert_true(pit2 == tokeniser2.cend());
1448
1449 /* Test another string, one that starts with an empty token */
1450 std::string str3{";abc"s};
1451 StringTokeniser tokeniser3{str3, ';'};
1452
1453 g_assert_cmpint(std::distance(tokeniser3.cbegin(), tokeniser3.cend()), ==, 2);
1454 auto pit3 = tokeniser3.cbegin();
1455 g_assert_true(*pit3 == ""s);
1456 ++pit3;
1457 g_assert_true(*pit3 == "abc"s);
1458 ++pit3;
1459 g_assert_true(pit3 == tokeniser3.cend());
1460
1461 /* And try an empty string, which should split into one empty token */
1462 std::string str4{""s};
1463 StringTokeniser tokeniser4{str4, ';'};
1464
1465 g_assert_cmpint(std::distance(tokeniser4.cbegin(), tokeniser4.cend()), ==, 1);
1466 auto pit4 = tokeniser4.cbegin();
1467 g_assert_true(*pit4 == ""s);
1468 ++pit4;
1469 g_assert_true(pit4 == tokeniser4.cend());
1470 }
1471
1472 static void
test_seq_glue_sequence_builder(void)1473 test_seq_glue_sequence_builder(void)
1474 {
1475 /* This is sufficiently tested by being used in all the other tests,
1476 * but if there's anything remaining to be tested, do it here.
1477 */
1478 }
1479
1480 static void
test_seq_glue_reply_builder(void)1481 test_seq_glue_reply_builder(void)
1482 {
1483 /* Nothing to test here; ReplyBuilder is just a constructor for
1484 * SequenceBuilder.
1485 */
1486 }
1487
1488 int
main(int argc,char * argv[])1489 main(int argc,
1490 char* argv[])
1491 {
1492 g_test_init(&argc, &argv, nullptr);
1493
1494 g_test_add_func("/vte/parser/sequences/arg", test_seq_arg);
1495 g_test_add_func("/vte/parser/sequences/string", test_seq_string);
1496 g_test_add_func("/vte/parser/sequences/glue/arg", test_seq_glue_arg);
1497 g_test_add_func("/vte/parser/sequences/glue/string", test_seq_glue_string);
1498 g_test_add_func("/vte/parser/sequences/glue/string-tokeniser", test_seq_glue_string_tokeniser);
1499 g_test_add_func("/vte/parser/sequences/glue/sequence-builder", test_seq_glue_sequence_builder);
1500 g_test_add_func("/vte/parser/sequences/glue/reply-builder", test_seq_glue_reply_builder);
1501 g_test_add_func("/vte/parser/sequences/control", test_seq_control);
1502 g_test_add_func("/vte/parser/sequences/escape/invalid", test_seq_esc_invalid);
1503 g_test_add_func("/vte/parser/sequences/escape/charset/94", test_seq_esc_charset_94);
1504 g_test_add_func("/vte/parser/sequences/escape/charset/96", test_seq_esc_charset_96);
1505 g_test_add_func("/vte/parser/sequences/escape/charset/94^n", test_seq_esc_charset_94_n);
1506 g_test_add_func("/vte/parser/sequences/escape/charset/96^n", test_seq_esc_charset_96_n);
1507 g_test_add_func("/vte/parser/sequences/escape/charset/control", test_seq_esc_charset_control);
1508 g_test_add_func("/vte/parser/sequences/escape/charset/other", test_seq_esc_charset_other);
1509 g_test_add_func("/vte/parser/sequences/escape/nF", test_seq_esc_nF);
1510 g_test_add_func("/vte/parser/sequences/escape/F[pes]", test_seq_esc_Fpes);
1511 g_test_add_func("/vte/parser/sequences/escape/known", test_seq_esc_known);
1512 g_test_add_func("/vte/parser/sequences/csi", test_seq_csi);
1513 g_test_add_func("/vte/parser/sequences/csi/known", test_seq_csi_known);
1514 g_test_add_func("/vte/parser/sequences/csi/parameters", test_seq_csi_param);
1515 g_test_add_func("/vte/parser/sequences/csi/clear", test_seq_csi_clear);
1516 g_test_add_func("/vte/parser/sequences/csi/max", test_seq_csi_max);
1517 g_test_add_func("/vte/parser/sequences/sci", test_seq_sci);
1518 g_test_add_func("/vte/parser/sequences/sci/known", test_seq_sci_known);
1519 g_test_add_func("/vte/parser/sequences/dcs", test_seq_dcs);
1520 g_test_add_func("/vte/parser/sequences/dcs/known", test_seq_dcs_known);
1521 g_test_add_func("/vte/parser/sequences/osc", test_seq_osc);
1522
1523 return g_test_run();
1524 }
1525