mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
initial import of openbios--main--1.0--patch-26
git-svn-id: svn://coreboot.org/openbios/openbios-devel@1 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
368
modules/cmdline.c
Normal file
368
modules/cmdline.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Creation Date: <2003/12/28 14:16:31 samuel>
|
||||
* Time-stamp: <2004/01/07 10:37:40 samuel>
|
||||
*
|
||||
* <cmdline.c>
|
||||
*
|
||||
* OpenFirmwware User Interface
|
||||
*
|
||||
* Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2
|
||||
*
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/bindings.h"
|
||||
#include "modules.h"
|
||||
#include "libc/vsprintf.h"
|
||||
|
||||
typedef struct {
|
||||
char *buf; /* size: ncol+1 */
|
||||
char *killbuf; /* size: ncol+1 */
|
||||
char *history;
|
||||
int hsize; /* size of history buffer */
|
||||
int ncol; /* #columns */
|
||||
} cmdline_info_t;
|
||||
|
||||
DECLARE_NODE( cmdline, INSTALL_OPEN, sizeof(cmdline_info_t),
|
||||
"+/packages/cmdline" );
|
||||
|
||||
static void
|
||||
emit( int ch )
|
||||
{
|
||||
PUSH( ch );
|
||||
fword("emit");
|
||||
}
|
||||
|
||||
static int
|
||||
emit_str( const char *str )
|
||||
{
|
||||
int n = 0;
|
||||
while( *str ) {
|
||||
n++;
|
||||
emit( *str++ );
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
move_cursor( int n )
|
||||
{
|
||||
if( n >= 0 ) {
|
||||
while( n-- )
|
||||
emit( '\f' );
|
||||
} else {
|
||||
while( n++ )
|
||||
emit( 8 );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear( int n )
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<n; i++ )
|
||||
emit(' ');
|
||||
move_cursor( -n );
|
||||
}
|
||||
|
||||
static void
|
||||
clearline( int pos, int n )
|
||||
{
|
||||
move_cursor( -pos );
|
||||
clear( n );
|
||||
}
|
||||
|
||||
static int
|
||||
key( void )
|
||||
{
|
||||
fword("key");
|
||||
return POP();
|
||||
}
|
||||
|
||||
/* ( -- flag ) */
|
||||
static void
|
||||
cmdline_open( cmdline_info_t *ci )
|
||||
{
|
||||
ci->ncol = 80;
|
||||
ci->buf = malloc( ci->ncol + 1 );
|
||||
ci->killbuf = malloc( ci->ncol + 1 );
|
||||
|
||||
ci->hsize = 40;
|
||||
ci->history = malloc( ci->hsize );
|
||||
ci->history[0] = 0;
|
||||
|
||||
RET( -1 );
|
||||
}
|
||||
|
||||
/* ( -- ) */
|
||||
static void
|
||||
cmdline_close( cmdline_info_t *ci )
|
||||
{
|
||||
free( ci->buf );
|
||||
free( ci->killbuf );
|
||||
free( ci->history );
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
history_get( cmdline_info_t *ci, int n )
|
||||
{
|
||||
char *p = ci->history;
|
||||
int len;
|
||||
|
||||
while( n-- && p )
|
||||
if( (p=strchr(p,'\n')) )
|
||||
p++;
|
||||
|
||||
ci->buf[0] = 0;
|
||||
if( !p )
|
||||
return 0;
|
||||
|
||||
for( len=0; len <= ci->ncol && p[len] != '\n' && p[len] ; len++ )
|
||||
;
|
||||
memcpy( ci->buf, p, len );
|
||||
ci->buf[len] = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
static int
|
||||
history_remove( cmdline_info_t *ci, int line )
|
||||
{
|
||||
char *s, *p = history_get( ci, line );
|
||||
|
||||
if( !p || !(s=strchr(p, '\n')) )
|
||||
return 1;
|
||||
s++;
|
||||
memmove( p, s, strlen(s)+1 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int /* ( -- ) */
|
||||
add_to_history( cmdline_info_t *ci, char *str )
|
||||
{
|
||||
int n, len;
|
||||
|
||||
if( !ci->history )
|
||||
return 0;
|
||||
len = strlen(str);
|
||||
if( !len )
|
||||
return 0;
|
||||
|
||||
/* make room for line in history */
|
||||
for( ;; ) {
|
||||
char *p;
|
||||
n = strlen(ci->history) + 1;
|
||||
|
||||
if( n + len + 1 <= ci->hsize )
|
||||
break;
|
||||
|
||||
if( !(p=strrchr(ci->history,'\n')) )
|
||||
return 0;
|
||||
*p = 0;
|
||||
if( !(p=strrchr(ci->history, '\n')) )
|
||||
p = ci->history-1;
|
||||
p[1] = 0;
|
||||
}
|
||||
|
||||
memmove( ci->history + len + 1, ci->history, n );
|
||||
memcpy( ci->history, str, len );
|
||||
ci->history[ len ] = '\n';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void /* ( -- ) */
|
||||
cmdline_prompt( cmdline_info_t *ci )
|
||||
{
|
||||
int cur_added=0, histind=0, ch, i, pos=0, n=0, prompt=1;
|
||||
char *buf = ci->buf;
|
||||
|
||||
buf = ci->buf;
|
||||
selfword("prepare");
|
||||
|
||||
emit('\n');
|
||||
#ifdef NOLEAVE
|
||||
for (;;)
|
||||
#else
|
||||
while (rstackcnt)
|
||||
#endif
|
||||
{
|
||||
int drop = 0;
|
||||
|
||||
if( prompt ) {
|
||||
fword("print-prompt");
|
||||
buf[0] = 0;
|
||||
cur_added = prompt = histind = pos = n = 0;
|
||||
}
|
||||
|
||||
switch( (ch=key()) ) {
|
||||
case 27:
|
||||
switch( key() ) {
|
||||
case 'f':
|
||||
while( buf[pos] == ' ' )
|
||||
emit( buf[pos++] );
|
||||
while( buf[pos] && buf[pos] != ' ' )
|
||||
emit( buf[pos++] );
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
while( pos && buf[pos-1] == ' ' ) {
|
||||
move_cursor( -1 );
|
||||
pos--;
|
||||
}
|
||||
while( pos && buf[pos-1] != ' ' ) {
|
||||
move_cursor( -1 );
|
||||
pos--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
if( cur_added )
|
||||
history_remove( ci, 0 );
|
||||
add_to_history( ci, ci->buf );
|
||||
|
||||
emit_str( &buf[pos] );
|
||||
emit(' ');
|
||||
PUSH( feval(buf) );
|
||||
fword("print-status");
|
||||
prompt = 1;
|
||||
break;
|
||||
|
||||
case 3: /* ^c */
|
||||
emit_str("\n");
|
||||
prompt = 1;
|
||||
if( cur_added )
|
||||
history_remove( ci, 0 );
|
||||
break;
|
||||
|
||||
case 4: /* ^d */
|
||||
if( pos == n )
|
||||
break;
|
||||
emit( buf[pos++] );
|
||||
/* fall through */
|
||||
|
||||
case 8: /* ^h */
|
||||
case 127: /* backspace */
|
||||
drop = 1;
|
||||
if( !pos )
|
||||
break;
|
||||
move_cursor( -1 );
|
||||
emit_str( &buf[pos] );
|
||||
emit(' ');
|
||||
memmove( &buf[pos-1], &buf[pos], n+1-pos );
|
||||
move_cursor( pos-n-1 );
|
||||
pos--;
|
||||
n--;
|
||||
break;
|
||||
|
||||
case 1: /* ^a */
|
||||
move_cursor( -pos );
|
||||
pos = 0;
|
||||
break;
|
||||
|
||||
case 5: /* ^e */
|
||||
pos += emit_str( &buf[pos] );
|
||||
break;
|
||||
|
||||
case 68: /* left */
|
||||
drop = 1;
|
||||
case 2: /* ^b */
|
||||
if( pos ) {
|
||||
move_cursor( -1 );
|
||||
pos--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 67: /* right */
|
||||
drop = 1;
|
||||
case 6: /* ^f */
|
||||
if( pos < n )
|
||||
emit( buf[pos++] );
|
||||
break;
|
||||
|
||||
case 11: /* ^k */
|
||||
strcpy( ci->killbuf, &buf[pos] );
|
||||
clear( n-pos );
|
||||
n = pos;
|
||||
buf[pos] = 0;
|
||||
break;
|
||||
|
||||
case 25: /* ^y */
|
||||
for( i=0; n < ci->ncol && ci->killbuf[i] ; i++, n++ ) {
|
||||
memmove( &buf[pos+1], &buf[pos], n+1-pos );
|
||||
buf[pos] = ci->killbuf[i];
|
||||
move_cursor( 1-emit_str(&buf[pos++]) );
|
||||
}
|
||||
break;
|
||||
|
||||
case 9: /* TAB */
|
||||
for( i=0; n < ci->ncol && (!i || (pos%4)) ; i++, n++ ) {
|
||||
memmove( &buf[pos+1], &buf[pos], n+1-pos );
|
||||
buf[pos] = ' ';
|
||||
move_cursor( 1-emit_str(&buf[pos++]) );
|
||||
}
|
||||
break;
|
||||
|
||||
case 12: /* ^l */
|
||||
move_cursor( -ci->ncol -pos );
|
||||
fword("print-prompt");
|
||||
move_cursor( pos-emit_str(buf) );
|
||||
break;
|
||||
|
||||
case 66: /* down */
|
||||
drop = 1;
|
||||
case 14: /* ^n */
|
||||
if( !histind )
|
||||
break;
|
||||
history_get( ci, --histind );
|
||||
clearline( pos, n );
|
||||
emit_str( buf );
|
||||
pos = n = strlen( buf );
|
||||
if( !histind && cur_added ) {
|
||||
cur_added = 0;
|
||||
history_remove( ci, 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case 65: /* up */
|
||||
drop = 1;
|
||||
case 16: /* ^p */
|
||||
if( !histind && add_to_history(ci, ci->buf) ) {
|
||||
cur_added = 1;
|
||||
histind++;
|
||||
}
|
||||
if( history_get(ci, histind) )
|
||||
histind++;
|
||||
clearline( pos, n );
|
||||
emit_str( buf );
|
||||
pos = n = strlen( buf );
|
||||
break;
|
||||
}
|
||||
if( (uint)ch < 32 )
|
||||
drop = 1;
|
||||
|
||||
if( !drop && n < ci->ncol ) {
|
||||
memmove( &buf[pos+1], &buf[pos], n+1-pos );
|
||||
n++;
|
||||
buf[pos] = ch;
|
||||
move_cursor( 1-emit_str(&buf[pos++]) );
|
||||
}
|
||||
}
|
||||
/* won't come here; if we ever do we should close ourselves */
|
||||
}
|
||||
|
||||
NODE_METHODS( cmdline ) = {
|
||||
{ "open", cmdline_open },
|
||||
{ "close", cmdline_close },
|
||||
{ "cmdline", cmdline_prompt },
|
||||
};
|
||||
|
||||
void
|
||||
cmdline_init( void )
|
||||
{
|
||||
REGISTER_NODE( cmdline );
|
||||
}
|
||||
Reference in New Issue
Block a user