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