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