chiark / gitweb /
terminal/grdev: simplify DRM event parsing
[elogind.git] / src / libsystemd-terminal / term-parser.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 /*
23  * Terminal Parser
24  * This file contains a bunch of UTF-8 helpers and the main ctlseq-parser. The
25  * parser is a simple state-machine that correctly parses all CSI, DCS, OSC, ST
26  * control sequences and generic escape sequences.
27  * The parser itself does not perform any actions but lets the caller react to
28  * detected sequences.
29  */
30
31 #include <stdbool.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include "macro.h"
35 #include "term-internal.h"
36 #include "util.h"
37
38 /**
39  * term_utf8_encode() - Encode single UCS-4 character as UTF-8
40  * @out_utf8: output buffer of at least 4 bytes or NULL
41  * @g: UCS-4 character to encode
42  *
43  * This encodes a single UCS-4 character as UTF-8 and writes it into @out_utf8.
44  * The length of the character is returned. It is not zero-terminated! If the
45  * output buffer is NULL, only the length is returned.
46  *
47  * Returns: The length in bytes that the UTF-8 representation does or would
48  *          occupy.
49  */
50 size_t term_utf8_encode(char *out_utf8, uint32_t g) {
51         if (g < (1 << 7)) {
52                 if (out_utf8)
53                         out_utf8[0] = g & 0x7f;
54                 return 1;
55         } else if (g < (1 << 11)) {
56                 if (out_utf8) {
57                         out_utf8[0] = 0xc0 | ((g >> 6) & 0x1f);
58                         out_utf8[1] = 0x80 | (g & 0x3f);
59                 }
60                 return 2;
61         } else if (g < (1 << 16)) {
62                 if (out_utf8) {
63                         out_utf8[0] = 0xe0 | ((g >> 12) & 0x0f);
64                         out_utf8[1] = 0x80 | ((g >> 6) & 0x3f);
65                         out_utf8[2] = 0x80 | (g & 0x3f);
66                 }
67                 return 3;
68         } else if (g < (1 << 21)) {
69                 if (out_utf8) {
70                         out_utf8[0] = 0xf0 | ((g >> 18) & 0x07);
71                         out_utf8[1] = 0x80 | ((g >> 12) & 0x3f);
72                         out_utf8[2] = 0x80 | ((g >> 6) & 0x3f);
73                         out_utf8[3] = 0x80 | (g & 0x3f);
74                 }
75                 return 4;
76         } else {
77                 return 0;
78         }
79 }
80
81 /**
82  * term_utf8_decode() - Try decoding the next UCS-4 character
83  * @p: decoder object to operate on or NULL
84  * @out_len: output storage for pointer to decoded UCS-4 string or NULL
85  * @c: next char to push into decoder
86  *
87  * This decodes a UTF-8 stream. It must be called for each input-byte of the
88  * UTF-8 stream and returns a UCS-4 stream. A pointer to the parsed UCS-4
89  * string is stored in @out_buf if non-NULL. The length of this string (number
90  * of parsed UCS4 characters) is returned as result. The string is not
91  * zero-terminated! Furthermore, the string is only valid until the next
92  * invocation of this function. It is also bound to the parser state @p and
93  * must not be freed nor written to by the caller.
94  *
95  * This function is highly optimized to work with terminal-emulators. Instead
96  * of being strict about UTF-8 validity, this tries to perform a fallback to
97  * ISO-8859-1 in case a wrong series was detected. Therefore, this function
98  * might return multiple UCS-4 characters by parsing just a single UTF-8 byte.
99  *
100  * The parser state @p should be allocated and managed by the caller. There're
101  * no helpers to do that for you. To initialize it, simply reset it to all
102  * zero. You can reset or free the object at any point in time.
103  *
104  * Returns: Number of parsed UCS4 characters
105  */
106 size_t term_utf8_decode(term_utf8 *p, uint32_t **out_buf, char c) {
107         static uint32_t ucs4_null = 0;
108         uint32_t t, *res = NULL;
109         uint8_t byte;
110         size_t len = 0;
111
112         if (!p)
113                 goto out;
114
115         byte = c;
116
117         if (!p->valid || p->i_bytes >= p->n_bytes) {
118                 /*
119                  * If the previous sequence was invalid or fully parsed, start
120                  * parsing a fresh new sequence.
121                  */
122
123                 if ((byte & 0xE0) == 0xC0) {
124                         /* start of two byte sequence */
125                         t = byte & 0x1F;
126                         p->n_bytes = 2;
127                         p->i_bytes = 1;
128                         p->valid = 1;
129                 } else if ((byte & 0xF0) == 0xE0) {
130                         /* start of three byte sequence */
131                         t = byte & 0x0F;
132                         p->n_bytes = 3;
133                         p->i_bytes = 1;
134                         p->valid = 1;
135                 } else if ((byte & 0xF8) == 0xF0) {
136                         /* start of four byte sequence */
137                         t = byte & 0x07;
138                         p->n_bytes = 4;
139                         p->i_bytes = 1;
140                         p->valid = 1;
141                 } else {
142                         /* Either of:
143                          *  - single ASCII 7-bit char
144                          *  - out-of-sync continuation byte
145                          *  - overlong encoding
146                          * All of them are treated as single byte ISO-8859-1 */
147                         t = byte;
148                         p->n_bytes = 1;
149                         p->i_bytes = 1;
150                         p->valid = 0;
151                 }
152
153                 p->chars[0] = byte;
154                 p->ucs4 = t << (6 * (p->n_bytes - p->i_bytes));
155         } else {
156                 /*
157                  * ..otherwise, try to continue the previous sequence..
158                  */
159
160                 if ((byte & 0xC0) == 0x80) {
161                         /*
162                          * Valid continuation byte. Append to sequence and
163                          * update the ucs4 cache accordingly.
164                          */
165
166                         t = byte & 0x3F;
167                         p->chars[p->i_bytes++] = byte;
168                         p->ucs4 |= t << (6 * (p->n_bytes - p->i_bytes));
169                 } else {
170                         /*
171                          * Invalid continuation? Treat cached sequence as
172                          * ISO-8859-1, but parse the new char as valid new
173                          * starting character. If it's a new single-byte UTF-8
174                          * sequence, we immediately return it in the same run,
175                          * otherwise, we might suffer from starvation.
176                          */
177
178                         if ((byte & 0xE0) == 0xC0 ||
179                             (byte & 0xF0) == 0xE0 ||
180                             (byte & 0xF8) == 0xF0) {
181                                 /*
182                                  * New multi-byte sequence. Move to-be-returned
183                                  * data at the end and start new sequence. Only
184                                  * return the old sequence.
185                                  */
186
187                                 memmove(p->chars + 1,
188                                         p->chars,
189                                         sizeof(*p->chars) * p->i_bytes);
190                                 res = p->chars + 1;
191                                 len = p->i_bytes;
192
193                                 if ((byte & 0xE0) == 0xC0) {
194                                         /* start of two byte sequence */
195                                         t = byte & 0x1F;
196                                         p->n_bytes = 2;
197                                         p->i_bytes = 1;
198                                         p->valid = 1;
199                                 } else if ((byte & 0xF0) == 0xE0) {
200                                         /* start of three byte sequence */
201                                         t = byte & 0x0F;
202                                         p->n_bytes = 3;
203                                         p->i_bytes = 1;
204                                         p->valid = 1;
205                                 } else if ((byte & 0xF8) == 0xF0) {
206                                         /* start of four byte sequence */
207                                         t = byte & 0x07;
208                                         p->n_bytes = 4;
209                                         p->i_bytes = 1;
210                                         p->valid = 1;
211                                 } else
212                                         assert_not_reached("Should not happen");
213
214                                 p->chars[0] = byte;
215                                 p->ucs4 = t << (6 * (p->n_bytes - p->i_bytes));
216
217                                 goto out;
218                         } else {
219                                 /*
220                                  * New single byte sequence, append to output
221                                  * and return combined sequence.
222                                  */
223
224                                 p->chars[p->i_bytes++] = byte;
225                                 p->valid = 0;
226                         }
227                 }
228         }
229
230         /*
231          * Check whether a full sequence (valid or invalid) has been parsed and
232          * then return it. Otherwise, return nothing.
233          */
234         if (p->valid) {
235                 /* still parsing? then bail out */
236                 if (p->i_bytes < p->n_bytes)
237                         goto out;
238
239                 res = &p->ucs4;
240                 len = 1;
241         } else {
242                 res = p->chars;
243                 len = p->i_bytes;
244         }
245
246         p->valid = 0;
247         p->i_bytes = 0;
248         p->n_bytes = 0;
249
250 out:
251         if (out_buf)
252                 *out_buf = res ? : &ucs4_null;
253         return len;
254 }
255
256 /*
257  * Command Parser
258  * The ctl-seq parser "term_parser" only detects whole sequences, it does not
259  * detect the specific command. Once a sequence is parsed, the command-parsers
260  * are used to figure out their meaning. Note that this depends on whether we
261  * run on the host or terminal side.
262  */
263
264 static unsigned int term_parse_host_control(const term_seq *seq) {
265         assert_return(seq, TERM_CMD_NONE);
266
267         switch (seq->terminator) {
268         case 0x00: /* NUL */
269                 return TERM_CMD_NULL;
270         case 0x05: /* ENQ */
271                 return TERM_CMD_ENQ;
272         case 0x07: /* BEL */
273                 return TERM_CMD_BEL;
274         case 0x08: /* BS */
275                 return TERM_CMD_BS;
276         case 0x09: /* HT */
277                 return TERM_CMD_HT;
278         case 0x0a: /* LF */
279                 return TERM_CMD_LF;
280         case 0x0b: /* VT */
281                 return TERM_CMD_VT;
282         case 0x0c: /* FF */
283                 return TERM_CMD_FF;
284         case 0x0d: /* CR */
285                 return TERM_CMD_CR;
286         case 0x0e: /* SO */
287                 return TERM_CMD_SO;
288         case 0x0f: /* SI */
289                 return TERM_CMD_SI;
290         case 0x11: /* DC1 */
291                 return TERM_CMD_DC1;
292         case 0x13: /* DC3 */
293                 return TERM_CMD_DC3;
294         case 0x18: /* CAN */
295                 /* this is already handled by the state-machine */
296                 break;
297         case 0x1a: /* SUB */
298                 return TERM_CMD_SUB;
299         case 0x1b: /* ESC */
300                 /* this is already handled by the state-machine */
301                 break;
302         case 0x1f: /* DEL */
303                 /* this is already handled by the state-machine */
304                 break;
305         case 0x84: /* IND */
306                 return TERM_CMD_IND;
307         case 0x85: /* NEL */
308                 return TERM_CMD_NEL;
309         case 0x88: /* HTS */
310                 return TERM_CMD_HTS;
311         case 0x8d: /* RI */
312                 return TERM_CMD_RI;
313         case 0x8e: /* SS2 */
314                 return TERM_CMD_SS2;
315         case 0x8f: /* SS3 */
316                 return TERM_CMD_SS3;
317         case 0x90: /* DCS */
318                 /* this is already handled by the state-machine */
319                 break;
320         case 0x96: /* SPA */
321                 return TERM_CMD_SPA;
322         case 0x97: /* EPA */
323                 return TERM_CMD_EPA;
324         case 0x98: /* SOS */
325                 /* this is already handled by the state-machine */
326                 break;
327         case 0x9a: /* DECID */
328                 return TERM_CMD_DECID;
329         case 0x9b: /* CSI */
330                 /* this is already handled by the state-machine */
331                 break;
332         case 0x9c: /* ST */
333                 return TERM_CMD_ST;
334         case 0x9d: /* OSC */
335                 /* this is already handled by the state-machine */
336                 break;
337         case 0x9e: /* PM */
338                 /* this is already handled by the state-machine */
339                 break;
340         case 0x9f: /* APC */
341                 /* this is already handled by the state-machine */
342                 break;
343         }
344
345         return TERM_CMD_NONE;
346 }
347
348 static inline int charset_from_cmd(uint32_t raw, unsigned int flags, bool require_96) {
349         static const struct {
350                 uint32_t raw;
351                 unsigned int flags;
352         } charset_cmds[] = {
353                 /* 96-compat charsets */
354                 [TERM_CHARSET_ISO_LATIN1_SUPPLEMENTAL]   = { .raw = 'A', .flags = 0 },
355                 [TERM_CHARSET_ISO_LATIN2_SUPPLEMENTAL]   = { .raw = 'B', .flags = 0 },
356                 [TERM_CHARSET_ISO_LATIN5_SUPPLEMENTAL]   = { .raw = 'M', .flags = 0 },
357                 [TERM_CHARSET_ISO_GREEK_SUPPLEMENTAL]    = { .raw = 'F', .flags = 0 },
358                 [TERM_CHARSET_ISO_HEBREW_SUPPLEMENTAL]   = { .raw = 'H', .flags = 0 },
359                 [TERM_CHARSET_ISO_LATIN_CYRILLIC]        = { .raw = 'L', .flags = 0 },
360
361                 /* 94-compat charsets */
362                 [TERM_CHARSET_DEC_SPECIAL_GRAPHIC]       = { .raw = '0', .flags = 0 },
363                 [TERM_CHARSET_DEC_SUPPLEMENTAL]          = { .raw = '5', .flags = TERM_SEQ_FLAG_PERCENT },
364                 [TERM_CHARSET_DEC_TECHNICAL]             = { .raw = '>', .flags = 0 },
365                 [TERM_CHARSET_CYRILLIC_DEC]              = { .raw = '4', .flags = TERM_SEQ_FLAG_AND },
366                 [TERM_CHARSET_DUTCH_NRCS]                = { .raw = '4', .flags = 0 },
367                 [TERM_CHARSET_FINNISH_NRCS]              = { .raw = '5', .flags = 0 },
368                 [TERM_CHARSET_FRENCH_NRCS]               = { .raw = 'R', .flags = 0 },
369                 [TERM_CHARSET_FRENCH_CANADIAN_NRCS]      = { .raw = '9', .flags = 0 },
370                 [TERM_CHARSET_GERMAN_NRCS]               = { .raw = 'K', .flags = 0 },
371                 [TERM_CHARSET_GREEK_DEC]                 = { .raw = '?', .flags = TERM_SEQ_FLAG_DQUOTE },
372                 [TERM_CHARSET_GREEK_NRCS]                = { .raw = '>', .flags = TERM_SEQ_FLAG_DQUOTE },
373                 [TERM_CHARSET_HEBREW_DEC]                = { .raw = '4', .flags = TERM_SEQ_FLAG_DQUOTE },
374                 [TERM_CHARSET_HEBREW_NRCS]               = { .raw = '=', .flags = TERM_SEQ_FLAG_PERCENT },
375                 [TERM_CHARSET_ITALIAN_NRCS]              = { .raw = 'Y', .flags = 0 },
376                 [TERM_CHARSET_NORWEGIAN_DANISH_NRCS]     = { .raw = '`', .flags = 0 },
377                 [TERM_CHARSET_PORTUGUESE_NRCS]           = { .raw = '6', .flags = TERM_SEQ_FLAG_PERCENT },
378                 [TERM_CHARSET_RUSSIAN_NRCS]              = { .raw = '5', .flags = TERM_SEQ_FLAG_AND },
379                 [TERM_CHARSET_SCS_NRCS]                  = { .raw = '3', .flags = TERM_SEQ_FLAG_PERCENT },
380                 [TERM_CHARSET_SPANISH_NRCS]              = { .raw = 'Z', .flags = 0 },
381                 [TERM_CHARSET_SWEDISH_NRCS]              = { .raw = '7', .flags = 0 },
382                 [TERM_CHARSET_SWISS_NRCS]                = { .raw = '=', .flags = 0 },
383                 [TERM_CHARSET_TURKISH_DEC]               = { .raw = '0', .flags = TERM_SEQ_FLAG_PERCENT },
384                 [TERM_CHARSET_TURKISH_NRCS]              = { .raw = '2', .flags = TERM_SEQ_FLAG_PERCENT },
385
386                 /* special charsets */
387                 [TERM_CHARSET_USERPREF_SUPPLEMENTAL]     = { .raw = '<', .flags = 0 },
388
389                 /* secondary choices */
390                 [TERM_CHARSET_CNT + TERM_CHARSET_FINNISH_NRCS]            = { .raw = 'C', .flags = 0 },
391                 [TERM_CHARSET_CNT + TERM_CHARSET_FRENCH_NRCS]             = { .raw = 'f', .flags = 0 },
392                 [TERM_CHARSET_CNT + TERM_CHARSET_FRENCH_CANADIAN_NRCS]    = { .raw = 'Q', .flags = 0 },
393                 [TERM_CHARSET_CNT + TERM_CHARSET_NORWEGIAN_DANISH_NRCS]   = { .raw = 'E', .flags = 0 },
394                 [TERM_CHARSET_CNT + TERM_CHARSET_SWEDISH_NRCS]            = { .raw = 'H', .flags = 0 }, /* unused; conflicts with ISO_HEBREW */
395
396                 /* tertiary choices */
397                 [TERM_CHARSET_CNT + TERM_CHARSET_CNT + TERM_CHARSET_NORWEGIAN_DANISH_NRCS] = { .raw = '6', .flags = 0 },
398         };
399         size_t i, cs;
400
401         /*
402          * Secondary choice on SWEDISH_NRCS and primary choice on
403          * ISO_HEBREW_SUPPLEMENTAL have a conflict: raw=="H", flags==0.
404          * We always choose the ISO 96-compat set, which is what VT510 does.
405          */
406
407         for (i = 0; i < ELEMENTSOF(charset_cmds); ++i) {
408                 if (charset_cmds[i].raw == raw && charset_cmds[i].flags == flags) {
409                         cs = i;
410                         while (cs >= TERM_CHARSET_CNT)
411                                 cs -= TERM_CHARSET_CNT;
412
413                         if (!require_96 || cs < TERM_CHARSET_96_CNT || cs >= TERM_CHARSET_94_CNT)
414                                 return cs;
415                 }
416         }
417
418         return -ENOENT;
419 }
420
421 /* true if exactly one bit in @value is set */
422 static inline bool exactly_one_bit_set(unsigned int value) {
423         return __builtin_popcount(value) == 1;
424 }
425
426 static unsigned int term_parse_host_escape(const term_seq *seq, unsigned int *cs_out) {
427         unsigned int t, flags;
428         int cs;
429
430         assert_return(seq, TERM_CMD_NONE);
431
432         flags = seq->intermediates;
433         t = TERM_SEQ_FLAG_POPEN | TERM_SEQ_FLAG_PCLOSE | TERM_SEQ_FLAG_MULT |
434             TERM_SEQ_FLAG_PLUS  | TERM_SEQ_FLAG_MINUS  | TERM_SEQ_FLAG_DOT  |
435             TERM_SEQ_FLAG_SLASH;
436
437         if (exactly_one_bit_set(flags & t)) {
438                 switch (flags & t) {
439                 case TERM_SEQ_FLAG_POPEN:
440                 case TERM_SEQ_FLAG_PCLOSE:
441                 case TERM_SEQ_FLAG_MULT:
442                 case TERM_SEQ_FLAG_PLUS:
443                         cs = charset_from_cmd(seq->terminator, flags & ~t, false);
444                         break;
445                 case TERM_SEQ_FLAG_MINUS:
446                 case TERM_SEQ_FLAG_DOT:
447                 case TERM_SEQ_FLAG_SLASH:
448                         cs = charset_from_cmd(seq->terminator, flags & ~t, true);
449                         break;
450                 default:
451                         cs = -ENOENT;
452                         break;
453                 }
454
455                 if (cs >= 0) {
456                         if (cs_out)
457                                 *cs_out = cs;
458                         return TERM_CMD_SCS;
459                 }
460
461                 /* looked like a charset-cmd but wasn't; continue */
462         }
463
464         switch (seq->terminator) {
465         case '3':
466                 if (flags == TERM_SEQ_FLAG_HASH) /* DECDHL top-half */
467                         return TERM_CMD_DECDHL_TH;
468                 break;
469         case '4':
470                 if (flags == TERM_SEQ_FLAG_HASH) /* DECDHL bottom-half */
471                         return TERM_CMD_DECDHL_BH;
472                 break;
473         case '5':
474                 if (flags == TERM_SEQ_FLAG_HASH) /* DECSWL */
475                         return TERM_CMD_DECSWL;
476                 break;
477         case '6':
478                 if (flags == 0) /* DECBI */
479                         return TERM_CMD_DECBI;
480                 else if (flags == TERM_SEQ_FLAG_HASH) /* DECDWL */
481                         return TERM_CMD_DECDWL;
482                 break;
483         case '7':
484                 if (flags == 0) /* DECSC */
485                         return TERM_CMD_DECSC;
486                 break;
487         case '8':
488                 if (flags == 0) /* DECRC */
489                         return TERM_CMD_DECRC;
490                 else if (flags == TERM_SEQ_FLAG_HASH) /* DECALN */
491                         return TERM_CMD_DECALN;
492                 break;
493         case '9':
494                 if (flags == 0) /* DECFI */
495                         return TERM_CMD_DECFI;
496                 break;
497         case '<':
498                 if (flags == 0) /* DECANM */
499                         return TERM_CMD_DECANM;
500                 break;
501         case '=':
502                 if (flags == 0) /* DECKPAM */
503                         return TERM_CMD_DECKPAM;
504                 break;
505         case '>':
506                 if (flags == 0) /* DECKPNM */
507                         return TERM_CMD_DECKPNM;
508                 break;
509         case '@':
510                 if (flags == TERM_SEQ_FLAG_PERCENT) {
511                         /* Select default character set */
512                         return TERM_CMD_XTERM_SDCS;
513                 }
514                 break;
515         case 'D':
516                 if (flags == 0) /* IND */
517                         return TERM_CMD_IND;
518                 break;
519         case 'E':
520                 if (flags == 0) /* NEL */
521                         return TERM_CMD_NEL;
522                 break;
523         case 'F':
524                 if (flags == 0) /* Cursor to lower-left corner of screen */
525                         return TERM_CMD_XTERM_CLLHP;
526                 else if (flags == TERM_SEQ_FLAG_SPACE) /* S7C1T */
527                         return TERM_CMD_S7C1T;
528                 break;
529         case 'G':
530                 if (flags == TERM_SEQ_FLAG_SPACE) { /* S8C1T */
531                         return TERM_CMD_S8C1T;
532                 } else if (flags == TERM_SEQ_FLAG_PERCENT) {
533                         /* Select UTF-8 character set */
534                         return TERM_CMD_XTERM_SUCS;
535                 }
536                 break;
537         case 'H':
538                 if (flags == 0) /* HTS */
539                         return TERM_CMD_HTS;
540                 break;
541         case 'L':
542                 if (flags == TERM_SEQ_FLAG_SPACE) {
543                         /* Set ANSI conformance level 1 */
544                         return TERM_CMD_XTERM_SACL1;
545                 }
546                 break;
547         case 'M':
548                 if (flags == 0) { /* RI */
549                         return TERM_CMD_RI;
550                 } else if (flags == TERM_SEQ_FLAG_SPACE) {
551                         /* Set ANSI conformance level 2 */
552                         return TERM_CMD_XTERM_SACL2;
553                 }
554                 break;
555         case 'N':
556                 if (flags == 0) { /* SS2 */
557                         return TERM_CMD_SS2;
558                 } else if (flags == TERM_SEQ_FLAG_SPACE) {
559                         /* Set ANSI conformance level 3 */
560                         return TERM_CMD_XTERM_SACL3;
561                 }
562                 break;
563         case 'O':
564                 if (flags == 0) /* SS3 */
565                         return TERM_CMD_SS3;
566                 break;
567         case 'P':
568                 if (flags == 0) /* DCS: this is already handled by the state-machine */
569                         return 0;
570                 break;
571         case 'V':
572                 if (flags == 0) /* SPA */
573                         return TERM_CMD_SPA;
574                 break;
575         case 'W':
576                 if (flags == 0) /* EPA */
577                         return TERM_CMD_EPA;
578                 break;
579         case 'X':
580                 if (flags == 0) { /* SOS */
581                         /* this is already handled by the state-machine */
582                         break;
583                 }
584                 break;
585         case 'Z':
586                 if (flags == 0) /* DECID */
587                         return TERM_CMD_DECID;
588                 break;
589         case '[':
590                 if (flags == 0) { /* CSI */
591                         /* this is already handled by the state-machine */
592                         break;
593                 }
594                 break;
595         case '\\':
596                 if (flags == 0) /* ST */
597                         return TERM_CMD_ST;
598                 break;
599         case ']':
600                 if (flags == 0) { /* OSC */
601                         /* this is already handled by the state-machine */
602                         break;
603                 }
604                 break;
605         case '^':
606                 if (flags == 0) { /* PM */
607                         /* this is already handled by the state-machine */
608                         break;
609                 }
610                 break;
611         case '_':
612                 if (flags == 0) { /* APC */
613                         /* this is already handled by the state-machine */
614                         break;
615                 }
616                 break;
617         case 'c':
618                 if (flags == 0) /* RIS */
619                         return TERM_CMD_RIS;
620                 break;
621         case 'l':
622                 if (flags == 0) /* Memory lock */
623                         return TERM_CMD_XTERM_MLHP;
624                 break;
625         case 'm':
626                 if (flags == 0) /* Memory unlock */
627                         return TERM_CMD_XTERM_MUHP;
628                 break;
629         case 'n':
630                 if (flags == 0) /* LS2 */
631                         return TERM_CMD_LS2;
632                 break;
633         case 'o':
634                 if (flags == 0) /* LS3 */
635                         return TERM_CMD_LS3;
636                 break;
637         case '|':
638                 if (flags == 0) /* LS3R */
639                         return TERM_CMD_LS3R;
640                 break;
641         case '}':
642                 if (flags == 0) /* LS2R */
643                         return TERM_CMD_LS2R;
644                 break;
645         case '~':
646                 if (flags == 0) /* LS1R */
647                         return TERM_CMD_LS1R;
648                 break;
649         }
650
651         return TERM_CMD_NONE;
652 }
653
654 static unsigned int term_parse_host_csi(const term_seq *seq) {
655         unsigned int flags;
656
657         assert_return(seq, TERM_CMD_NONE);
658
659         flags = seq->intermediates;
660
661         switch (seq->terminator) {
662         case 'A':
663                 if (flags == 0) /* CUU */
664                         return TERM_CMD_CUU;
665                 break;
666         case 'a':
667                 if (flags == 0) /* HPR */
668                         return TERM_CMD_HPR;
669                 break;
670         case 'B':
671                 if (flags == 0) /* CUD */
672                         return TERM_CMD_CUD;
673                 break;
674         case 'b':
675                 if (flags == 0) /* REP */
676                         return TERM_CMD_REP;
677                 break;
678         case 'C':
679                 if (flags == 0) /* CUF */
680                         return TERM_CMD_CUF;
681                 break;
682         case 'c':
683                 if (flags == 0) /* DA1 */
684                         return TERM_CMD_DA1;
685                 else if (flags == TERM_SEQ_FLAG_GT) /* DA2 */
686                         return TERM_CMD_DA2;
687                 else if (flags == TERM_SEQ_FLAG_EQUAL) /* DA3 */
688                         return TERM_CMD_DA3;
689                 break;
690         case 'D':
691                 if (flags == 0) /* CUB */
692                         return TERM_CMD_CUB;
693                 break;
694         case 'd':
695                 if (flags == 0) /* VPA */
696                         return TERM_CMD_VPA;
697                 break;
698         case 'E':
699                 if (flags == 0) /* CNL */
700                         return TERM_CMD_CNL;
701                 break;
702         case 'e':
703                 if (flags == 0) /* VPR */
704                         return TERM_CMD_VPR;
705                 break;
706         case 'F':
707                 if (flags == 0) /* CPL */
708                         return TERM_CMD_CPL;
709                 break;
710         case 'f':
711                 if (flags == 0) /* HVP */
712                         return TERM_CMD_HVP;
713                 break;
714         case 'G':
715                 if (flags == 0) /* CHA */
716                         return TERM_CMD_CHA;
717                 break;
718         case 'g':
719                 if (flags == 0) /* TBC */
720                         return TERM_CMD_TBC;
721                 else if (flags == TERM_SEQ_FLAG_MULT) /* DECLFKC */
722                         return TERM_CMD_DECLFKC;
723                 break;
724         case 'H':
725                 if (flags == 0) /* CUP */
726                         return TERM_CMD_CUP;
727                 break;
728         case 'h':
729                 if (flags == 0) /* SM ANSI */
730                         return TERM_CMD_SM_ANSI;
731                 else if (flags == TERM_SEQ_FLAG_WHAT) /* SM DEC */
732                         return TERM_CMD_SM_DEC;
733                 break;
734         case 'I':
735                 if (flags == 0) /* CHT */
736                         return TERM_CMD_CHT;
737                 break;
738         case 'i':
739                 if (flags == 0) /* MC ANSI */
740                         return TERM_CMD_MC_ANSI;
741                 else if (flags == TERM_SEQ_FLAG_WHAT) /* MC DEC */
742                         return TERM_CMD_MC_DEC;
743                 break;
744         case 'J':
745                 if (flags == 0) /* ED */
746                         return TERM_CMD_ED;
747                 else if (flags == TERM_SEQ_FLAG_WHAT) /* DECSED */
748                         return TERM_CMD_DECSED;
749                 break;
750         case 'K':
751                 if (flags == 0) /* EL */
752                         return TERM_CMD_EL;
753                 else if (flags == TERM_SEQ_FLAG_WHAT) /* DECSEL */
754                         return TERM_CMD_DECSEL;
755                 break;
756         case 'L':
757                 if (flags == 0) /* IL */
758                         return TERM_CMD_IL;
759                 break;
760         case 'l':
761                 if (flags == 0) /* RM ANSI */
762                         return TERM_CMD_RM_ANSI;
763                 else if (flags == TERM_SEQ_FLAG_WHAT) /* RM DEC */
764                         return TERM_CMD_RM_DEC;
765                 break;
766         case 'M':
767                 if (flags == 0) /* DL */
768                         return TERM_CMD_DL;
769                 break;
770         case 'm':
771                 if (flags == 0) /* SGR */
772                         return TERM_CMD_SGR;
773                 else if (flags == TERM_SEQ_FLAG_GT) /* XTERM SMR */
774                         return TERM_CMD_XTERM_SRV;
775                 break;
776         case 'n':
777                 if (flags == 0) /* DSR ANSI */
778                         return TERM_CMD_DSR_ANSI;
779                 else if (flags == TERM_SEQ_FLAG_GT) /* XTERM RMR */
780                         return TERM_CMD_XTERM_RRV;
781                 else if (flags == TERM_SEQ_FLAG_WHAT) /* DSR DEC */
782                         return TERM_CMD_DSR_DEC;
783                 break;
784         case 'P':
785                 if (flags == 0) /* DCH */
786                         return TERM_CMD_DCH;
787                 else if (flags == TERM_SEQ_FLAG_SPACE) /* PPA */
788                         return TERM_CMD_PPA;
789                 break;
790         case 'p':
791                 if (flags == 0) /* DECSSL */
792                         return TERM_CMD_DECSSL;
793                 else if (flags == TERM_SEQ_FLAG_SPACE) /* DECSSCLS */
794                         return TERM_CMD_DECSSCLS;
795                 else if (flags == TERM_SEQ_FLAG_BANG) /* DECSTR */
796                         return TERM_CMD_DECSTR;
797                 else if (flags == TERM_SEQ_FLAG_DQUOTE) /* DECSCL */
798                         return TERM_CMD_DECSCL;
799                 else if (flags == TERM_SEQ_FLAG_CASH) /* DECRQM-ANSI */
800                         return TERM_CMD_DECRQM_ANSI;
801                 else if (flags == (TERM_SEQ_FLAG_CASH | TERM_SEQ_FLAG_WHAT)) /* DECRQM-DEC */
802                         return TERM_CMD_DECRQM_DEC;
803                 else if (flags == TERM_SEQ_FLAG_PCLOSE) /* DECSDPT */
804                         return TERM_CMD_DECSDPT;
805                 else if (flags == TERM_SEQ_FLAG_MULT) /* DECSPPCS */
806                         return TERM_CMD_DECSPPCS;
807                 else if (flags == TERM_SEQ_FLAG_PLUS) /* DECSR */
808                         return TERM_CMD_DECSR;
809                 else if (flags == TERM_SEQ_FLAG_COMMA) /* DECLTOD */
810                         return TERM_CMD_DECLTOD;
811                 else if (flags == TERM_SEQ_FLAG_GT) /* XTERM SPM */
812                         return TERM_CMD_XTERM_SPM;
813                 break;
814         case 'Q':
815                 if (flags == TERM_SEQ_FLAG_SPACE) /* PPR */
816                         return TERM_CMD_PPR;
817                 break;
818         case 'q':
819                 if (flags == 0) /* DECLL */
820                         return TERM_CMD_DECLL;
821                 else if (flags == TERM_SEQ_FLAG_SPACE) /* DECSCUSR */
822                         return TERM_CMD_DECSCUSR;
823                 else if (flags == TERM_SEQ_FLAG_DQUOTE) /* DECSCA */
824                         return TERM_CMD_DECSCA;
825                 else if (flags == TERM_SEQ_FLAG_CASH) /* DECSDDT */
826                         return TERM_CMD_DECSDDT;
827                 else if (flags == TERM_SEQ_FLAG_MULT) /* DECSRC */
828                         return TERM_CMD_DECSR;
829                 else if (flags == TERM_SEQ_FLAG_PLUS) /* DECELF */
830                         return TERM_CMD_DECELF;
831                 else if (flags == TERM_SEQ_FLAG_COMMA) /* DECTID */
832                         return TERM_CMD_DECTID;
833                 break;
834         case 'R':
835                 if (flags == TERM_SEQ_FLAG_SPACE) /* PPB */
836                         return TERM_CMD_PPB;
837                 break;
838         case 'r':
839                 if (flags == 0) {
840                         /* DECSTBM */
841                         return TERM_CMD_DECSTBM;
842                 } else if (flags == TERM_SEQ_FLAG_SPACE) {
843                         /* DECSKCV */
844                         return TERM_CMD_DECSKCV;
845                 } else if (flags == TERM_SEQ_FLAG_CASH) {
846                         /* DECCARA */
847                         return TERM_CMD_DECCARA;
848                 } else if (flags == TERM_SEQ_FLAG_MULT) {
849                         /* DECSCS */
850                         return TERM_CMD_DECSCS;
851                 } else if (flags == TERM_SEQ_FLAG_PLUS) {
852                         /* DECSMKR */
853                         return TERM_CMD_DECSMKR;
854                 } else if (flags == TERM_SEQ_FLAG_WHAT) {
855                         /*
856                          * There's a conflict between DECPCTERM and XTERM-RPM.
857                          * XTERM-RPM takes a single argument, DECPCTERM takes 2.
858                          * Split both up and forward the call to the closer
859                          * match.
860                          */
861                         if (seq->n_args <= 1) /* XTERM RPM */
862                                 return TERM_CMD_XTERM_RPM;
863                         else if (seq->n_args >= 2) /* DECPCTERM */
864                                 return TERM_CMD_DECPCTERM;
865                 }
866                 break;
867         case 'S':
868                 if (flags == 0) /* SU */
869                         return TERM_CMD_SU;
870                 else if (flags == TERM_SEQ_FLAG_WHAT) /* XTERM SGFX */
871                         return TERM_CMD_XTERM_SGFX;
872                 break;
873         case 's':
874                 if (flags == 0) {
875                         /*
876                          * There's a conflict between DECSLRM and SC-ANSI which
877                          * cannot be resolved without knowing the state of
878                          * DECLRMM. We leave that decision up to the caller.
879                          */
880                         return TERM_CMD_DECSLRM_OR_SC;
881                 } else if (flags == TERM_SEQ_FLAG_CASH) {
882                         /* DECSPRTT */
883                         return TERM_CMD_DECSPRTT;
884                 } else if (flags == TERM_SEQ_FLAG_MULT) {
885                         /* DECSFC */
886                         return TERM_CMD_DECSFC;
887                 } else if (flags == TERM_SEQ_FLAG_WHAT) {
888                         /* XTERM SPM */
889                         return TERM_CMD_XTERM_SPM;
890                 }
891                 break;
892         case 'T':
893                 if (flags == 0) {
894                         /*
895                          * Awesome: There's a conflict between SD and XTERM IHMT
896                          * that we have to resolve by checking the parameter
897                          * count.. XTERM_IHMT needs exactly 5 arguments, SD
898                          * takes 0 or 1. We're conservative here and give both
899                          * a wider range to allow unused arguments (compat...).
900                          */
901                         if (seq->n_args >= 5) {
902                                 /* XTERM IHMT */
903                                 return TERM_CMD_XTERM_IHMT;
904                         } else if (seq->n_args < 5) {
905                                 /* SD */
906                                 return TERM_CMD_SD;
907                         }
908                 } else if (flags == TERM_SEQ_FLAG_GT) {
909                         /* XTERM RTM */
910                         return TERM_CMD_XTERM_RTM;
911                 }
912                 break;
913         case 't':
914                 if (flags == 0) {
915                         if (seq->n_args > 0 && seq->args[0] < 24) {
916                                 /* XTERM WM */
917                                 return TERM_CMD_XTERM_WM;
918                         } else {
919                                 /* DECSLPP */
920                                 return TERM_CMD_DECSLPP;
921                         }
922                 } else if (flags == TERM_SEQ_FLAG_SPACE) {
923                         /* DECSWBV */
924                         return TERM_CMD_DECSWBV;
925                 } else if (flags == TERM_SEQ_FLAG_DQUOTE) {
926                         /* DECSRFR */
927                         return TERM_CMD_DECSRFR;
928                 } else if (flags == TERM_SEQ_FLAG_CASH) {
929                         /* DECRARA */
930                         return TERM_CMD_DECRARA;
931                 } else if (flags == TERM_SEQ_FLAG_GT) {
932                         /* XTERM STM */
933                         return TERM_CMD_XTERM_STM;
934                 }
935                 break;
936         case 'U':
937                 if (flags == 0) /* NP */
938                         return TERM_CMD_NP;
939                 break;
940         case 'u':
941                 if (flags == 0) {
942                         /* RC */
943                         return TERM_CMD_RC;
944                 } else if (flags == TERM_SEQ_FLAG_SPACE) {
945                         /* DECSMBV */
946                         return TERM_CMD_DECSMBV;
947                 } else if (flags == TERM_SEQ_FLAG_DQUOTE) {
948                         /* DECSTRL */
949                         return TERM_CMD_DECSTRL;
950                 } else if (flags == TERM_SEQ_FLAG_WHAT) {
951                         /* DECRQUPSS */
952                         return TERM_CMD_DECRQUPSS;
953                 } else if (seq->args[0] == 1 && flags == TERM_SEQ_FLAG_CASH) {
954                         /* DECRQTSR */
955                         return TERM_CMD_DECRQTSR;
956                 } else if (flags == TERM_SEQ_FLAG_MULT) {
957                         /* DECSCP */
958                         return TERM_CMD_DECSCP;
959                 } else if (flags == TERM_SEQ_FLAG_COMMA) {
960                         /* DECRQKT */
961                         return TERM_CMD_DECRQKT;
962                 }
963                 break;
964         case 'V':
965                 if (flags == 0) /* PP */
966                         return TERM_CMD_PP;
967                 break;
968         case 'v':
969                 if (flags == TERM_SEQ_FLAG_SPACE) /* DECSLCK */
970                         return TERM_CMD_DECSLCK;
971                 else if (flags == TERM_SEQ_FLAG_DQUOTE) /* DECRQDE */
972                         return TERM_CMD_DECRQDE;
973                 else if (flags == TERM_SEQ_FLAG_CASH) /* DECCRA */
974                         return TERM_CMD_DECCRA;
975                 else if (flags == TERM_SEQ_FLAG_COMMA) /* DECRPKT */
976                         return TERM_CMD_DECRPKT;
977                 break;
978         case 'W':
979                 if (seq->args[0] == 5 && flags == TERM_SEQ_FLAG_WHAT) {
980                         /* DECST8C */
981                         return TERM_CMD_DECST8C;
982                 }
983                 break;
984         case 'w':
985                 if (flags == TERM_SEQ_FLAG_CASH) /* DECRQPSR */
986                         return TERM_CMD_DECRQPSR;
987                 else if (flags == TERM_SEQ_FLAG_SQUOTE) /* DECEFR */
988                         return TERM_CMD_DECEFR;
989                 else if (flags == TERM_SEQ_FLAG_PLUS) /* DECSPP */
990                         return TERM_CMD_DECSPP;
991                 break;
992         case 'X':
993                 if (flags == 0) /* ECH */
994                         return TERM_CMD_ECH;
995                 break;
996         case 'x':
997                 if (flags == 0) /* DECREQTPARM */
998                         return TERM_CMD_DECREQTPARM;
999                 else if (flags == TERM_SEQ_FLAG_CASH) /* DECFRA */
1000                         return TERM_CMD_DECFRA;
1001                 else if (flags == TERM_SEQ_FLAG_MULT) /* DECSACE */
1002                         return TERM_CMD_DECSACE;
1003                 else if (flags == TERM_SEQ_FLAG_PLUS) /* DECRQPKFM */
1004                         return TERM_CMD_DECRQPKFM;
1005                 break;
1006         case 'y':
1007                 if (flags == 0) /* DECTST */
1008                         return TERM_CMD_DECTST;
1009                 else if (flags == TERM_SEQ_FLAG_MULT) /* DECRQCRA */
1010                         return TERM_CMD_DECRQCRA;
1011                 else if (flags == TERM_SEQ_FLAG_PLUS) /* DECPKFMR */
1012                         return TERM_CMD_DECPKFMR;
1013                 break;
1014         case 'Z':
1015                 if (flags == 0) /* CBT */
1016                         return TERM_CMD_CBT;
1017                 break;
1018         case 'z':
1019                 if (flags == TERM_SEQ_FLAG_CASH) /* DECERA */
1020                         return TERM_CMD_DECERA;
1021                 else if (flags == TERM_SEQ_FLAG_SQUOTE) /* DECELR */
1022                         return TERM_CMD_DECELR;
1023                 else if (flags == TERM_SEQ_FLAG_MULT) /* DECINVM */
1024                         return TERM_CMD_DECINVM;
1025                 else if (flags == TERM_SEQ_FLAG_PLUS) /* DECPKA */
1026                         return TERM_CMD_DECPKA;
1027                 break;
1028         case '@':
1029                 if (flags == 0) /* ICH */
1030                         return TERM_CMD_ICH;
1031                 break;
1032         case '`':
1033                 if (flags == 0) /* HPA */
1034                         return TERM_CMD_HPA;
1035                 break;
1036         case '{':
1037                 if (flags == TERM_SEQ_FLAG_CASH) /* DECSERA */
1038                         return TERM_CMD_DECSERA;
1039                 else if (flags == TERM_SEQ_FLAG_SQUOTE) /* DECSLE */
1040                         return TERM_CMD_DECSLE;
1041                 break;
1042         case '|':
1043                 if (flags == TERM_SEQ_FLAG_CASH) /* DECSCPP */
1044                         return TERM_CMD_DECSCPP;
1045                 else if (flags == TERM_SEQ_FLAG_SQUOTE) /* DECRQLP */
1046                         return TERM_CMD_DECRQLP;
1047                 else if (flags == TERM_SEQ_FLAG_MULT) /* DECSNLS */
1048                         return TERM_CMD_DECSNLS;
1049                 break;
1050         case '}':
1051                 if (flags == TERM_SEQ_FLAG_SPACE) /* DECKBD */
1052                         return TERM_CMD_DECKBD;
1053                 else if (flags == TERM_SEQ_FLAG_CASH) /* DECSASD */
1054                         return TERM_CMD_DECSASD;
1055                 else if (flags == TERM_SEQ_FLAG_SQUOTE) /* DECIC */
1056                         return TERM_CMD_DECIC;
1057                 break;
1058         case '~':
1059                 if (flags == TERM_SEQ_FLAG_SPACE) /* DECTME */
1060                         return TERM_CMD_DECTME;
1061                 else if (flags == TERM_SEQ_FLAG_CASH) /* DECSSDT */
1062                         return TERM_CMD_DECSSDT;
1063                 else if (flags == TERM_SEQ_FLAG_SQUOTE) /* DECDC */
1064                         return TERM_CMD_DECDC;
1065                 break;
1066         }
1067
1068         return TERM_CMD_NONE;
1069 }
1070
1071 /*
1072  * State Machine
1073  * This parser controls the parser-state and returns any detected sequence to
1074  * the caller. The parser is based on this state-diagram from Paul Williams:
1075  *   http://vt100.net/emu/
1076  * It was written from scratch and extended where needed.
1077  * This parser is fully compatible up to the vt500 series. We expect UCS-4 as
1078  * input. It's the callers responsibility to do any UTF-8 parsing.
1079  */
1080
1081 enum parser_state {
1082         STATE_NONE,             /* placeholder */
1083         STATE_GROUND,           /* initial state and ground */
1084         STATE_ESC,              /* ESC sequence was started */
1085         STATE_ESC_INT,          /* intermediate escape characters */
1086         STATE_CSI_ENTRY,        /* starting CSI sequence */
1087         STATE_CSI_PARAM,        /* CSI parameters */
1088         STATE_CSI_INT,          /* intermediate CSI characters */
1089         STATE_CSI_IGNORE,       /* CSI error; ignore this CSI sequence */
1090         STATE_DCS_ENTRY,        /* starting DCS sequence */
1091         STATE_DCS_PARAM,        /* DCS parameters */
1092         STATE_DCS_INT,          /* intermediate DCS characters */
1093         STATE_DCS_PASS,         /* DCS data passthrough */
1094         STATE_DCS_IGNORE,       /* DCS error; ignore this DCS sequence */
1095         STATE_OSC_STRING,       /* parsing OSC sequence */
1096         STATE_ST_IGNORE,        /* unimplemented seq; ignore until ST */
1097         STATE_NUM
1098 };
1099
1100 enum parser_action {
1101         ACTION_NONE,            /* placeholder */
1102         ACTION_CLEAR,           /* clear parameters */
1103         ACTION_IGNORE,          /* ignore the character entirely */
1104         ACTION_PRINT,           /* print the character on the console */
1105         ACTION_EXECUTE,         /* execute single control character (C0/C1) */
1106         ACTION_COLLECT,         /* collect intermediate character */
1107         ACTION_PARAM,           /* collect parameter character */
1108         ACTION_ESC_DISPATCH,    /* dispatch escape sequence */
1109         ACTION_CSI_DISPATCH,    /* dispatch csi sequence */
1110         ACTION_DCS_START,       /* start of DCS data */
1111         ACTION_DCS_COLLECT,     /* collect DCS data */
1112         ACTION_DCS_CONSUME,     /* consume DCS terminator */
1113         ACTION_DCS_DISPATCH,    /* dispatch dcs sequence */
1114         ACTION_OSC_START,       /* start of OSC data */
1115         ACTION_OSC_COLLECT,     /* collect OSC data */
1116         ACTION_OSC_CONSUME,     /* consume OSC terminator */
1117         ACTION_OSC_DISPATCH,    /* dispatch osc sequence */
1118         ACTION_NUM
1119 };
1120
1121 int term_parser_new(term_parser **out, bool host) {
1122         _term_parser_free_ term_parser *parser = NULL;
1123
1124         assert_return(out, -EINVAL);
1125
1126         parser = new0(term_parser, 1);
1127         if (!parser)
1128                 return -ENOMEM;
1129
1130         parser->is_host = host;
1131         parser->st_alloc = 64;
1132         parser->seq.st = new0(char, parser->st_alloc + 1);
1133         if (!parser->seq.st)
1134                 return -ENOMEM;
1135
1136         *out = parser;
1137         parser = NULL;
1138         return 0;
1139 }
1140
1141 term_parser *term_parser_free(term_parser *parser) {
1142         if (!parser)
1143                 return NULL;
1144
1145         free(parser->seq.st);
1146         free(parser);
1147         return NULL;
1148 }
1149
1150 static inline void parser_clear(term_parser *parser) {
1151         unsigned int i;
1152
1153         parser->seq.command = TERM_CMD_NONE;
1154         parser->seq.terminator = 0;
1155         parser->seq.intermediates = 0;
1156         parser->seq.charset = TERM_CHARSET_NONE;
1157         parser->seq.n_args = 0;
1158         for (i = 0; i < TERM_PARSER_ARG_MAX; ++i)
1159                 parser->seq.args[i] = -1;
1160
1161         parser->seq.n_st = 0;
1162         parser->seq.st[0] = 0;
1163 }
1164
1165 static int parser_ignore(term_parser *parser, uint32_t raw) {
1166         parser_clear(parser);
1167         parser->seq.type = TERM_SEQ_IGNORE;
1168         parser->seq.command = TERM_CMD_NONE;
1169         parser->seq.terminator = raw;
1170         parser->seq.charset = TERM_CHARSET_NONE;
1171
1172         return parser->seq.type;
1173 }
1174
1175 static int parser_print(term_parser *parser, uint32_t raw) {
1176         parser_clear(parser);
1177         parser->seq.type = TERM_SEQ_GRAPHIC;
1178         parser->seq.command = TERM_CMD_GRAPHIC;
1179         parser->seq.terminator = raw;
1180         parser->seq.charset = TERM_CHARSET_NONE;
1181
1182         return parser->seq.type;
1183 }
1184
1185 static int parser_execute(term_parser *parser, uint32_t raw) {
1186         parser_clear(parser);
1187         parser->seq.type = TERM_SEQ_CONTROL;
1188         parser->seq.command = TERM_CMD_GRAPHIC;
1189         parser->seq.terminator = raw;
1190         parser->seq.charset = TERM_CHARSET_NONE;
1191         if (!parser->is_host)
1192                 parser->seq.command = term_parse_host_control(&parser->seq);
1193
1194         return parser->seq.type;
1195 }
1196
1197 static void parser_collect(term_parser *parser, uint32_t raw) {
1198         /*
1199          * Usually, characters from 0x30 to 0x3f are only allowed as leading
1200          * markers (or as part of the parameters), characters from 0x20 to 0x2f
1201          * are only allowed as trailing markers. However, our state-machine
1202          * already verifies those restrictions so we can handle them the same
1203          * way here. Note that we safely allow markers to be specified multiple
1204          * times.
1205          */
1206
1207         if (raw >= 0x20 && raw <= 0x3f)
1208                 parser->seq.intermediates |= 1 << (raw - 0x20);
1209 }
1210
1211 static void parser_param(term_parser *parser, uint32_t raw) {
1212         int new;
1213
1214         if (raw == ';') {
1215                 if (parser->seq.n_args < TERM_PARSER_ARG_MAX)
1216                         ++parser->seq.n_args;
1217
1218                 return;
1219         }
1220
1221         if (parser->seq.n_args >= TERM_PARSER_ARG_MAX)
1222                 return;
1223
1224         if (raw >= '0' && raw <= '9') {
1225                 new = parser->seq.args[parser->seq.n_args];
1226                 if (new < 0)
1227                         new = 0;
1228                 new = new * 10 + raw - '0';
1229
1230                 /* VT510 tells us to clamp all values to [0, 9999], however, it
1231                  * also allows commands with values up to 2^15-1. We simply use
1232                  * 2^16 as maximum here to be compatible to all commands, but
1233                  * avoid overflows in any calculations. */
1234                 if (new > 0xffff)
1235                         new = 0xffff;
1236
1237                 parser->seq.args[parser->seq.n_args] = new;
1238         }
1239 }
1240
1241 static int parser_esc(term_parser *parser, uint32_t raw) {
1242         parser->seq.type = TERM_SEQ_ESCAPE;
1243         parser->seq.command = TERM_CMD_NONE;
1244         parser->seq.terminator = raw;
1245         parser->seq.charset = TERM_CHARSET_NONE;
1246         if (!parser->is_host)
1247                 parser->seq.command = term_parse_host_escape(&parser->seq, &parser->seq.charset);
1248
1249         return parser->seq.type;
1250 }
1251
1252 static int parser_csi(term_parser *parser, uint32_t raw) {
1253         /* parser->seq is cleared during CSI-ENTER state, thus there's no need
1254          * to clear invalid fields here. */
1255
1256         if (parser->seq.n_args < TERM_PARSER_ARG_MAX) {
1257                 if (parser->seq.n_args > 0 ||
1258                     parser->seq.args[parser->seq.n_args] >= 0)
1259                         ++parser->seq.n_args;
1260         }
1261
1262         parser->seq.type = TERM_SEQ_CSI;
1263         parser->seq.command = TERM_CMD_NONE;
1264         parser->seq.terminator = raw;
1265         parser->seq.charset = TERM_CHARSET_NONE;
1266         if (!parser->is_host)
1267                 parser->seq.command = term_parse_host_csi(&parser->seq);
1268
1269         return parser->seq.type;
1270 }
1271
1272 /* perform state transition and dispatch related actions */
1273 static int parser_transition(term_parser *parser, uint32_t raw, unsigned int state, unsigned int action) {
1274         if (state != STATE_NONE)
1275                 parser->state = state;
1276
1277         switch (action) {
1278         case ACTION_NONE:
1279                 return TERM_SEQ_NONE;
1280         case ACTION_CLEAR:
1281                 parser_clear(parser);
1282                 return TERM_SEQ_NONE;
1283         case ACTION_IGNORE:
1284                 return parser_ignore(parser, raw);
1285         case ACTION_PRINT:
1286                 return parser_print(parser, raw);
1287         case ACTION_EXECUTE:
1288                 return parser_execute(parser, raw);
1289         case ACTION_COLLECT:
1290                 parser_collect(parser, raw);
1291                 return TERM_SEQ_NONE;
1292         case ACTION_PARAM:
1293                 parser_param(parser, raw);
1294                 return TERM_SEQ_NONE;
1295         case ACTION_ESC_DISPATCH:
1296                 return parser_esc(parser, raw);
1297         case ACTION_CSI_DISPATCH:
1298                 return parser_csi(parser, raw);
1299         case ACTION_DCS_START:
1300                 /* not implemented */
1301                 return TERM_SEQ_NONE;
1302         case ACTION_DCS_COLLECT:
1303                 /* not implemented */
1304                 return TERM_SEQ_NONE;
1305         case ACTION_DCS_CONSUME:
1306                 /* not implemented */
1307                 return TERM_SEQ_NONE;
1308         case ACTION_DCS_DISPATCH:
1309                 /* not implemented */
1310                 return TERM_SEQ_NONE;
1311         case ACTION_OSC_START:
1312                 /* not implemented */
1313                 return TERM_SEQ_NONE;
1314         case ACTION_OSC_COLLECT:
1315                 /* not implemented */
1316                 return TERM_SEQ_NONE;
1317         case ACTION_OSC_CONSUME:
1318                 /* not implemented */
1319                 return TERM_SEQ_NONE;
1320         case ACTION_OSC_DISPATCH:
1321                 /* not implemented */
1322                 return TERM_SEQ_NONE;
1323         default:
1324                 assert_not_reached("invalid vte-parser action");
1325                 return TERM_SEQ_NONE;
1326         }
1327 }
1328
1329 static int parser_feed_to_state(term_parser *parser, uint32_t raw) {
1330         switch (parser->state) {
1331         case STATE_NONE:
1332                 /*
1333                  * During initialization, parser->state is cleared. Treat this
1334                  * as STATE_GROUND. We will then never get to STATE_NONE again.
1335                  */
1336         case STATE_GROUND:
1337                 switch (raw) {
1338                 case 0x00 ... 0x1f:     /* C0 */
1339                 case 0x80 ... 0x9b:     /* C1 \ { ST } */
1340                 case 0x9d ... 0x9f:
1341                         return parser_transition(parser, raw, STATE_NONE, ACTION_EXECUTE);
1342                 case 0x9c:              /* ST */
1343                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1344                 }
1345
1346                 return parser_transition(parser, raw, STATE_NONE, ACTION_PRINT);
1347         case STATE_ESC:
1348                 switch (raw) {
1349                 case 0x00 ... 0x1f:     /* C0 */
1350                         return parser_transition(parser, raw, STATE_NONE, ACTION_EXECUTE);
1351                 case 0x20 ... 0x2f:     /* [' ' - '\'] */
1352                         return parser_transition(parser, raw, STATE_ESC_INT, ACTION_COLLECT);
1353                 case 0x30 ... 0x4f:     /* ['0' - '~'] \ { 'P', 'X', '[', ']', '^', '_' } */
1354                 case 0x51 ... 0x57:
1355                 case 0x59 ... 0x5a:
1356                 case 0x5c:
1357                 case 0x60 ... 0x7e:
1358                         return parser_transition(parser, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1359                 case 0x50:              /* 'P' */
1360                         return parser_transition(parser, raw, STATE_DCS_ENTRY, ACTION_CLEAR);
1361                 case 0x5b:              /* '[' */
1362                         return parser_transition(parser, raw, STATE_CSI_ENTRY, ACTION_CLEAR);
1363                 case 0x5d:              /* ']' */
1364                         return parser_transition(parser, raw, STATE_OSC_STRING, ACTION_CLEAR);
1365                 case 0x58:              /* 'X' */
1366                 case 0x5e:              /* '^' */
1367                 case 0x5f:              /* '_' */
1368                         return parser_transition(parser, raw, STATE_ST_IGNORE, ACTION_NONE);
1369                 case 0x7f:              /* DEL */
1370                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1371                 case 0x9c:              /* ST */
1372                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1373                 }
1374
1375                 return parser_transition(parser, raw, STATE_ESC_INT, ACTION_COLLECT);
1376         case STATE_ESC_INT:
1377                 switch (raw) {
1378                 case 0x00 ... 0x1f:     /* C0 */
1379                         return parser_transition(parser, raw, STATE_NONE, ACTION_EXECUTE);
1380                 case 0x20 ... 0x2f:     /* [' ' - '\'] */
1381                         return parser_transition(parser, raw, STATE_NONE, ACTION_COLLECT);
1382                 case 0x30 ... 0x7e:     /* ['0' - '~'] */
1383                         return parser_transition(parser, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1384                 case 0x7f:              /* DEL */
1385                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1386                 case 0x9c:              /* ST */
1387                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1388                 }
1389
1390                 return parser_transition(parser, raw, STATE_NONE, ACTION_COLLECT);
1391         case STATE_CSI_ENTRY:
1392                 switch (raw) {
1393                 case 0x00 ... 0x1f:     /* C0 */
1394                         return parser_transition(parser, raw, STATE_NONE, ACTION_EXECUTE);
1395                 case 0x20 ... 0x2f:     /* [' ' - '\'] */
1396                         return parser_transition(parser, raw, STATE_CSI_INT, ACTION_COLLECT);
1397                 case 0x3a:              /* ':' */
1398                         return parser_transition(parser, raw, STATE_CSI_IGNORE, ACTION_NONE);
1399                 case 0x30 ... 0x39:     /* ['0' - '9'] */
1400                 case 0x3b:              /* ';' */
1401                         return parser_transition(parser, raw, STATE_CSI_PARAM, ACTION_PARAM);
1402                 case 0x3c ... 0x3f:     /* ['<' - '?'] */
1403                         return parser_transition(parser, raw, STATE_CSI_PARAM, ACTION_COLLECT);
1404                 case 0x40 ... 0x7e:     /* ['@' - '~'] */
1405                         return parser_transition(parser, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1406                 case 0x7f:              /* DEL */
1407                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1408                 case 0x9c:              /* ST */
1409                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1410                 }
1411
1412                 return parser_transition(parser, raw, STATE_CSI_IGNORE, ACTION_NONE);
1413         case STATE_CSI_PARAM:
1414                 switch (raw) {
1415                 case 0x00 ... 0x1f:     /* C0 */
1416                         return parser_transition(parser, raw, STATE_NONE, ACTION_EXECUTE);
1417                 case 0x20 ... 0x2f:     /* [' ' - '\'] */
1418                         return parser_transition(parser, raw, STATE_CSI_INT, ACTION_COLLECT);
1419                 case 0x30 ... 0x39:     /* ['0' - '9'] */
1420                 case 0x3b:              /* ';' */
1421                         return parser_transition(parser, raw, STATE_NONE, ACTION_PARAM);
1422                 case 0x3a:              /* ':' */
1423                 case 0x3c ... 0x3f:     /* ['<' - '?'] */
1424                         return parser_transition(parser, raw, STATE_CSI_IGNORE, ACTION_NONE);
1425                 case 0x40 ... 0x7e:     /* ['@' - '~'] */
1426                         return parser_transition(parser, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1427                 case 0x7f:              /* DEL */
1428                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1429                 case 0x9c:              /* ST */
1430                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1431                 }
1432
1433                 return parser_transition(parser, raw, STATE_CSI_IGNORE, ACTION_NONE);
1434         case STATE_CSI_INT:
1435                 switch (raw) {
1436                 case 0x00 ... 0x1f:     /* C0 */
1437                         return parser_transition(parser, raw, STATE_NONE, ACTION_EXECUTE);
1438                 case 0x20 ... 0x2f:     /* [' ' - '\'] */
1439                         return parser_transition(parser, raw, STATE_NONE, ACTION_COLLECT);
1440                 case 0x30 ... 0x3f:     /* ['0' - '?'] */
1441                         return parser_transition(parser, raw, STATE_CSI_IGNORE, ACTION_NONE);
1442                 case 0x40 ... 0x7e:     /* ['@' - '~'] */
1443                         return parser_transition(parser, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1444                 case 0x7f:              /* DEL */
1445                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1446                 case 0x9c:              /* ST */
1447                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1448                 }
1449
1450                 return parser_transition(parser, raw, STATE_CSI_IGNORE, ACTION_NONE);
1451         case STATE_CSI_IGNORE:
1452                 switch (raw) {
1453                 case 0x00 ... 0x1f:     /* C0 */
1454                         return parser_transition(parser, raw, STATE_NONE, ACTION_EXECUTE);
1455                 case 0x20 ... 0x3f:     /* [' ' - '?'] */
1456                         return parser_transition(parser, raw, STATE_NONE, ACTION_NONE);
1457                 case 0x40 ... 0x7e:     /* ['@' - '~'] */
1458                         return parser_transition(parser, raw, STATE_GROUND, ACTION_NONE);
1459                 case 0x7f:              /* DEL */
1460                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1461                 case 0x9c:              /* ST */
1462                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1463                 }
1464
1465                 return parser_transition(parser, raw, STATE_NONE, ACTION_NONE);
1466         case STATE_DCS_ENTRY:
1467                 switch (raw) {
1468                 case 0x00 ... 0x1f:     /* C0 */
1469                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1470                 case 0x20 ... 0x2f:     /* [' ' - '\'] */
1471                         return parser_transition(parser, raw, STATE_DCS_INT, ACTION_COLLECT);
1472                 case 0x3a:              /* ':' */
1473                         return parser_transition(parser, raw, STATE_DCS_IGNORE, ACTION_NONE);
1474                 case 0x30 ... 0x39:     /* ['0' - '9'] */
1475                 case 0x3b:              /* ';' */
1476                         return parser_transition(parser, raw, STATE_DCS_PARAM, ACTION_PARAM);
1477                 case 0x3c ... 0x3f:     /* ['<' - '?'] */
1478                         return parser_transition(parser, raw, STATE_DCS_PARAM, ACTION_COLLECT);
1479                 case 0x40 ... 0x7e:     /* ['@' - '~'] */
1480                         return parser_transition(parser, raw, STATE_DCS_PASS, ACTION_DCS_CONSUME);
1481                 case 0x7f:              /* DEL */
1482                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1483                 case 0x9c:              /* ST */
1484                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1485                 }
1486
1487                 return parser_transition(parser, raw, STATE_DCS_PASS, ACTION_DCS_CONSUME);
1488         case STATE_DCS_PARAM:
1489                 switch (raw) {
1490                 case 0x00 ... 0x1f:     /* C0 */
1491                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1492                 case 0x20 ... 0x2f:     /* [' ' - '\'] */
1493                         return parser_transition(parser, raw, STATE_DCS_INT, ACTION_COLLECT);
1494                 case 0x30 ... 0x39:     /* ['0' - '9'] */
1495                 case 0x3b:              /* ';' */
1496                         return parser_transition(parser, raw, STATE_NONE, ACTION_PARAM);
1497                 case 0x3a:              /* ':' */
1498                 case 0x3c ... 0x3f:     /* ['<' - '?'] */
1499                         return parser_transition(parser, raw, STATE_DCS_IGNORE, ACTION_NONE);
1500                 case 0x40 ... 0x7e:     /* ['@' - '~'] */
1501                         return parser_transition(parser, raw, STATE_DCS_PASS, ACTION_DCS_CONSUME);
1502                 case 0x7f:              /* DEL */
1503                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1504                 case 0x9c:              /* ST */
1505                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1506                 }
1507
1508                 return parser_transition(parser, raw, STATE_DCS_PASS, ACTION_DCS_CONSUME);
1509         case STATE_DCS_INT:
1510                 switch (raw) {
1511                 case 0x00 ... 0x1f:     /* C0 */
1512                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1513                 case 0x20 ... 0x2f:     /* [' ' - '\'] */
1514                         return parser_transition(parser, raw, STATE_NONE, ACTION_COLLECT);
1515                 case 0x30 ... 0x3f:     /* ['0' - '?'] */
1516                         return parser_transition(parser, raw, STATE_DCS_IGNORE, ACTION_NONE);
1517                 case 0x40 ... 0x7e:     /* ['@' - '~'] */
1518                         return parser_transition(parser, raw, STATE_DCS_PASS, ACTION_DCS_CONSUME);
1519                 case 0x7f:              /* DEL */
1520                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1521                 case 0x9c:              /* ST */
1522                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1523                 }
1524
1525                 return parser_transition(parser, raw, STATE_DCS_PASS, ACTION_DCS_CONSUME);
1526         case STATE_DCS_PASS:
1527                 switch (raw) {
1528                 case 0x00 ... 0x7e:     /* ASCII \ { DEL } */
1529                         return parser_transition(parser, raw, STATE_NONE, ACTION_DCS_COLLECT);
1530                 case 0x7f:              /* DEL */
1531                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1532                 case 0x9c:              /* ST */
1533                         return parser_transition(parser, raw, STATE_GROUND, ACTION_DCS_DISPATCH);
1534                 }
1535
1536                 return parser_transition(parser, raw, STATE_NONE, ACTION_DCS_COLLECT);
1537         case STATE_DCS_IGNORE:
1538                 switch (raw) {
1539                 case 0x00 ... 0x7f:     /* ASCII */
1540                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1541                 case 0x9c:              /* ST */
1542                         return parser_transition(parser, raw, STATE_GROUND, ACTION_NONE);
1543                 }
1544
1545                 return parser_transition(parser, raw, STATE_NONE, ACTION_NONE);
1546         case STATE_OSC_STRING:
1547                 switch (raw) {
1548                 case 0x00 ... 0x06:     /* C0 \ { BEL } */
1549                 case 0x08 ... 0x1f:
1550                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1551                 case 0x20 ... 0x7f:     /* [' ' - DEL] */
1552                         return parser_transition(parser, raw, STATE_NONE, ACTION_OSC_COLLECT);
1553                 case 0x07:              /* BEL */
1554                 case 0x9c:              /* ST */
1555                         return parser_transition(parser, raw, STATE_GROUND, ACTION_OSC_DISPATCH);
1556                 }
1557
1558                 return parser_transition(parser, raw, STATE_NONE, ACTION_OSC_COLLECT);
1559         case STATE_ST_IGNORE:
1560                 switch (raw) {
1561                 case 0x00 ... 0x7f:     /* ASCII */
1562                         return parser_transition(parser, raw, STATE_NONE, ACTION_IGNORE);
1563                 case 0x9c:              /* ST */
1564                         return parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1565                 }
1566
1567                 return parser_transition(parser, raw, STATE_NONE, ACTION_NONE);
1568         }
1569
1570         assert_not_reached("bad vte-parser state");
1571         return -EINVAL;
1572 }
1573
1574 int term_parser_feed(term_parser *parser, const term_seq **seq_out, uint32_t raw) {
1575         int r;
1576
1577         assert_return(parser, -EINVAL);
1578         assert_return(seq_out, -EINVAL);
1579
1580         /*
1581          * Notes:
1582          *  * DEC treats GR codes as GL. We don't do that as we require UTF-8
1583          *    as charset and, thus, it doesn't make sense to treat GR special.
1584          *  * During control sequences, unexpected C1 codes cancel the sequence
1585          *    and immediately start a new one. C0 codes, however, may or may not
1586          *    be ignored/executed depending on the sequence.
1587          */
1588
1589         switch (raw) {
1590         case 0x18:              /* CAN */
1591                 r = parser_transition(parser, raw, STATE_GROUND, ACTION_IGNORE);
1592                 break;
1593         case 0x1a:              /* SUB */
1594                 r = parser_transition(parser, raw, STATE_GROUND, ACTION_EXECUTE);
1595                 break;
1596         case 0x80 ... 0x8f:     /* C1 \ {DCS, SOS, CSI, ST, OSC, PM, APC} */
1597         case 0x91 ... 0x97:
1598         case 0x99 ... 0x9a:
1599                 r = parser_transition(parser, raw, STATE_GROUND, ACTION_EXECUTE);
1600                 break;
1601         case 0x1b:              /* ESC */
1602                 r = parser_transition(parser, raw, STATE_ESC, ACTION_CLEAR);
1603                 break;
1604         case 0x98:              /* SOS */
1605         case 0x9e:              /* PM */
1606         case 0x9f:              /* APC */
1607                 r = parser_transition(parser, raw, STATE_ST_IGNORE, ACTION_NONE);
1608                 break;
1609         case 0x90:              /* DCS */
1610                 r = parser_transition(parser, raw, STATE_DCS_ENTRY, ACTION_CLEAR);
1611                 break;
1612         case 0x9d:              /* OSC */
1613                 r = parser_transition(parser, raw, STATE_OSC_STRING, ACTION_CLEAR);
1614                 break;
1615         case 0x9b:              /* CSI */
1616                 r = parser_transition(parser, raw, STATE_CSI_ENTRY, ACTION_CLEAR);
1617                 break;
1618         default:
1619                 r = parser_feed_to_state(parser, raw);
1620                 break;
1621         }
1622
1623         if (r <= 0)
1624                 *seq_out = NULL;
1625         else
1626                 *seq_out = &parser->seq;
1627
1628         return r;
1629 }