master xplshn/aruu / cmd / extra / yap / ansi.c
 1#include "ansi.h"
 2#include "in_all.h"
 3
 4static int
 5consume_csi(const char *s, const char **next, enum ansi_kind *kind)
 6{
 7  const unsigned char *p = (const unsigned char *)s + 2;
 8
 9  while (*p >= 0x30 && *p <= 0x3f) {
10    p++;
11  }
12  while (*p >= 0x20 && *p <= 0x2f) {
13    p++;
14  }
15  if (*p >= 0x40 && *p <= 0x7e) {
16    *kind = (*p == 'm') ? ANSI_SGR : ANSI_DISCARD;
17    *next = (const char *)p + 1;
18    return 1;
19  }
20  return 0;
21}
22
23static int
24consume_string(const char *s, const char **next)
25{
26  const unsigned char *p = (const unsigned char *)s + 2;
27
28  while (*p) {
29    if (*p == '\a') {
30      *next = (const char *)p + 1;
31      return 1;
32    }
33    if (*p == '\x1b' && p[1] == '\\') {
34      *next = (const char *)p + 2;
35      return 1;
36    }
37    p++;
38  }
39  return 0;
40}
41
42static int
43consume_esc(const char *s, const char **next)
44{
45  const unsigned char *p = (const unsigned char *)s + 1;
46
47  while (*p >= 0x20 && *p <= 0x2f) {
48    p++;
49  }
50  if (*p >= 0x30 && *p <= 0x7e) {
51    *next = (const char *)p + 1;
52    return 1;
53  }
54  return 0;
55}
56
57int
58ansi_escape(const char *s, const char **next, enum ansi_kind *kind)
59{
60  *kind = ANSI_NONE;
61  *next = s;
62  if ((unsigned char)s[0] != 0x1b || s[1] == '\0') {
63    return 0;
64  }
65  if (s[1] == '[') {
66    return consume_csi(s, next, kind);
67  }
68  if (s[1] == ']' || s[1] == 'P' || s[1] == 'X' || s[1] == '^' || s[1] == '_') {
69    *kind = ANSI_DISCARD;
70    return consume_string(s, next);
71  }
72  *kind = ANSI_DISCARD;
73  return consume_esc(s, next);
74}