Browse Source

Added support for interpreting ANSI escape sequences on behalf of

non-ANSI-capable consoles.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
1cd45decc4
2 changed files with 217 additions and 0 deletions
  1. 114
    0
      src/core/ansiesc.c
  2. 103
    0
      src/include/gpxe/ansiesc.h

+ 114
- 0
src/core/ansiesc.c View File

@@ -0,0 +1,114 @@
1
+/*
2
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <string.h>
20
+#include <assert.h>
21
+#include <gpxe/ansiesc.h>
22
+
23
+/** @file
24
+ *
25
+ * ANSI escape sequences
26
+ *
27
+ */
28
+
29
+/**
30
+ * Call ANSI escape sequence handler
31
+ *
32
+ * @v handlers		List of escape sequence handlers
33
+ * @v function		Control function identifier
34
+ * @v count		Parameter count
35
+ * @v params		Parameter list
36
+ */
37
+static void ansiesc_call_handler ( struct ansiesc_handler *handlers,
38
+				   unsigned int function, int count,
39
+				   int params[] ) {
40
+	struct ansiesc_handler *handler;
41
+
42
+	for ( handler = handlers ; handler->function ; handler++ ) {
43
+		if ( handler->function == function ) {
44
+			handler->handle ( count, params );
45
+			break;
46
+		}
47
+	}
48
+}
49
+
50
+/**
51
+ * Process character that may be part of ANSI escape sequence
52
+ *
53
+ * @v ctx		ANSI escape sequence context
54
+ * @v c			Character
55
+ * @ret c		Original character if not part of escape sequence
56
+ * @ret <0		Character was part of escape sequence
57
+ *
58
+ * ANSI escape sequences will be plucked out of the character stream
59
+ * and interpreted; once complete they will be passed to the
60
+ * appropriate handler if one exists in this ANSI escape sequence
61
+ * context.
62
+ *
63
+ * In the interests of code size, we are rather liberal about the
64
+ * sequences we are prepared to accept as valid.
65
+ */
66
+int ansiesc_process ( struct ansiesc_context *ctx, int c ) {
67
+	if ( ctx->count == 0 ) {
68
+		if ( c == ESC ) {
69
+			/* First byte of CSI : begin escape sequence */
70
+			ctx->count = 1;
71
+			memset ( ctx->params, 0xff, sizeof ( ctx->params ) );
72
+			ctx->function = 0;
73
+			return -1;
74
+		} else {
75
+			/* Normal character */
76
+			return c;
77
+		}
78
+	} else {
79
+		if ( c == '[' ) {
80
+			/* Second byte of CSI : do nothing */
81
+		} else if ( ( c >= '0' ) && ( c <= '9' ) ) {
82
+			/* Parameter Byte : part of a parameter value */
83
+			int *param = &ctx->params[ctx->count - 1];
84
+			if ( *param < 0 )
85
+				*param = 0;
86
+			*param = ( ( *param * 10 ) + ( c - '0' ) );
87
+		} else if ( c == ';' ) {
88
+			/* Parameter Byte : parameter delimiter */
89
+			ctx->count++;
90
+			if ( ctx->count > ( sizeof ( ctx->params ) /
91
+					    sizeof ( ctx->params[0] ) ) ) {
92
+				/* Excessive parameters : abort sequence */
93
+				ctx->count = 0;
94
+				DBG ( "Too many parameters in ANSI escape "
95
+				      "sequence\n" );
96
+			}
97
+		} else if ( ( c >= 0x20 ) && ( c <= 0x2f ) ) {
98
+			/* Intermediate Byte */
99
+			ctx->function <<= 8;
100
+			ctx->function |= c;
101
+		} else {
102
+			/* Treat as Final Byte.  Zero ctx->count before 
103
+			 * calling handler to avoid potential infinite loops.
104
+			 */
105
+			int count = ctx->count;
106
+			ctx->count = 0;
107
+			ctx->function <<= 8;
108
+			ctx->function |= c;
109
+			ansiesc_call_handler ( ctx->handlers, ctx->function,
110
+					       count, ctx->params );
111
+		}
112
+		return -1;
113
+	}
114
+}

+ 103
- 0
src/include/gpxe/ansiesc.h View File

@@ -0,0 +1,103 @@
1
+#ifndef _GPXE_ANSIESC_H
2
+#define _GPXE_ANSIESC_H
3
+
4
+/** @file
5
+ *
6
+ * ANSI escape sequences
7
+ *
8
+ * ANSI X3.64 (aka ECMA-48 or ISO/IEC 6429, available from
9
+ * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf)
10
+ * defines escape sequences consisting of:
11
+ *
12
+ *     A Control Sequence Introducer (CSI)
13
+ *
14
+ *     Zero or more Parameter Bytes (P)
15
+ *
16
+ *     Zero or more Intermediate Bytes (I)
17
+ *
18
+ *     A Final Byte (F)
19
+ *
20
+ * The CSI consists of ESC (0x1b) followed by "[" (0x5b).  The
21
+ * Parameter Bytes, for a standardised (i.e. not private or
22
+ * experimental) sequence, consist of a list of ASCII decimal integers
23
+ * separated by semicolons.  The Intermediate Bytes (in the range 0x20
24
+ * to 0x2f) and the Final Byte (in the range 0x40 to 0x4f) determine
25
+ * the control function.
26
+ * 
27
+ */
28
+
29
+/** A handler for an escape sequence */
30
+struct ansiesc_handler {
31
+	/** The control function identifier
32
+	 *
33
+	 * The control function identifier consists of the
34
+	 * Intermediate Bytes (if any) and the Final Byte.  In
35
+	 * practice, no more than one immediate byte is ever used, so
36
+	 * the byte combination can be efficiently expressed as a
37
+	 * single integer, in the obvious way (with the Final Byte
38
+	 * being the least significant byte).
39
+	 */
40
+	unsigned int function;
41
+	/** Handle escape sequence
42
+	 *
43
+	 * @v count		Parameter count
44
+	 * @v params		Parameter list
45
+	 *
46
+	 * A negative parameter value indicates that the parameter was
47
+	 * omitted and that the default value for this control
48
+	 * function should be used.
49
+	 *
50
+	 * Since all parameters are optional, there is no way to
51
+	 * distinguish between "zero parameters" and "single parameter
52
+	 * omitted".  Consequently, the parameter list will always
53
+	 * contain at least one item.
54
+	 */
55
+	void ( * handle ) ( unsigned int count, int params[] );
56
+};
57
+
58
+/** Maximum number of parameters within a single escape sequence */
59
+#define ANSIESC_MAX_PARAMS 4
60
+
61
+/**
62
+ * ANSI escape sequence context
63
+ *
64
+ * This provides temporary storage for processing escape sequences,
65
+ * and points to the list of escape sequence handlers.
66
+ */
67
+struct ansiesc_context {
68
+	/** Array of handlers
69
+	 *
70
+	 * Must be terminated by a handler with @c function set to
71
+	 * zero.
72
+	 */
73
+	struct ansiesc_handler *handlers;
74
+	/** Parameter count
75
+	 *
76
+	 * Will be zero when not currently in an escape sequence.
77
+	 */
78
+	unsigned int count;
79
+	/** Parameter list */ 
80
+	int params[ANSIESC_MAX_PARAMS];
81
+	/** Control function identifier */
82
+	unsigned int function;
83
+};
84
+
85
+/** Escape character */
86
+#define ESC 0x1b
87
+
88
+/** Control Sequence Introducer */
89
+#define CSI "\033["
90
+
91
+/**
92
+ * @defgroup ansifuncs ANSI escape sequence function identifiers
93
+ * @{
94
+ */
95
+
96
+/** Character and line position */
97
+#define ANSIESC_HVP 'f'
98
+
99
+/** @} */
100
+
101
+extern int ansiesc_process ( struct ansiesc_context *ctx, int c );
102
+
103
+#endif /* _GPXE_ANSIESC_H */

Loading…
Cancel
Save