iPXE
ansiesc.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <string.h>
00027 #include <assert.h>
00028 #include <ipxe/ansiesc.h>
00029 
00030 /** @file
00031  *
00032  * ANSI escape sequences
00033  *
00034  */
00035 
00036 /**
00037  * Call ANSI escape sequence handler
00038  *
00039  * @v ctx               ANSI escape sequence context
00040  * @v function          Control function identifier
00041  * @v count             Parameter count
00042  * @v params            Parameter list
00043  */
00044 static void ansiesc_call_handler ( struct ansiesc_context *ctx,
00045                                    unsigned int function, int count,
00046                                    int params[] ) {
00047         struct ansiesc_handler *handlers = ctx->handlers;
00048         struct ansiesc_handler *handler;
00049 
00050         for ( handler = handlers ; handler->function ; handler++ ) {
00051                 if ( handler->function == function ) {
00052                         handler->handle ( ctx, count, params );
00053                         break;
00054                 }
00055         }
00056 }
00057 
00058 /**
00059  * Process character that may be part of ANSI escape sequence
00060  *
00061  * @v ctx               ANSI escape sequence context
00062  * @v c                 Character
00063  * @ret c               Original character if not part of escape sequence
00064  * @ret <0              Character was part of escape sequence
00065  *
00066  * ANSI escape sequences will be plucked out of the character stream
00067  * and interpreted; once complete they will be passed to the
00068  * appropriate handler if one exists in this ANSI escape sequence
00069  * context.
00070  *
00071  * In the interests of code size, we are rather liberal about the
00072  * sequences we are prepared to accept as valid.
00073  */
00074 int ansiesc_process ( struct ansiesc_context *ctx, int c ) {
00075 
00076         if ( ctx->count == 0 ) {
00077                 if ( c == ESC ) {
00078                         /* First byte of CSI : begin escape sequence */
00079                         ctx->count = 1;
00080                         memset ( ctx->params, 0xff, sizeof ( ctx->params ) );
00081                         ctx->function = 0;
00082                         return -1;
00083                 } else {
00084                         /* Normal character */
00085                         return c;
00086                 }
00087         } else {
00088                 if ( c == '[' ) {
00089                         /* Second byte of CSI : do nothing */
00090                 } else if ( ( c >= '0' ) && ( c <= '9' ) ) {
00091                         /* Parameter Byte : part of a parameter value */
00092                         int *param = &ctx->params[ctx->count - 1];
00093                         if ( *param < 0 )
00094                                 *param = 0;
00095                         *param = ( ( *param * 10 ) + ( c - '0' ) );
00096                 } else if ( c == ';' ) {
00097                         /* Parameter Byte : parameter delimiter */
00098                         ctx->count++;
00099                         if ( ctx->count > ( sizeof ( ctx->params ) /
00100                                             sizeof ( ctx->params[0] ) ) ) {
00101                                 /* Excessive parameters : abort sequence */
00102                                 ctx->count = 0;
00103                                 DBG ( "Too many parameters in ANSI escape "
00104                                       "sequence\n" );
00105                         }
00106                 } else if ( ( ( c >= 0x20 ) && ( c <= 0x2f ) ) ||
00107                             ( c == '?' ) ) {
00108                         /* Intermediate Byte */
00109                         ctx->function <<= 8;
00110                         ctx->function |= c;
00111                 } else {
00112                         /* Treat as Final Byte.  Zero ctx->count before 
00113                          * calling handler to avoid potential infinite loops.
00114                          */
00115                         int count = ctx->count;
00116                         ctx->count = 0;
00117                         ctx->function <<= 8;
00118                         ctx->function |= c;
00119                         ansiesc_call_handler ( ctx, ctx->function,
00120                                                count, ctx->params );
00121                 }
00122                 return -1;
00123         }
00124 }