main ansi.c
 1#include "in_all.h"
 2#include "ansi.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] == '^' ||
69	    s[1] == '_') {
70		*kind = ANSI_DISCARD;
71		return consume_string(s, next);
72	}
73	*kind = ANSI_DISCARD;
74	return consume_esc(s, next);
75}