char_io.c revision a5602e1bdcf9570fa24684b54cf57a3f22e05ae1
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/* char_io.c - basic console input and output */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * GRUB -- GRand Unified Bootloader
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * This program is free software; you can redistribute it and/or modify
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * it under the terms of the GNU General Public License as published by
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * the Free Software Foundation; either version 2 of the License, or
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * (at your option) any later version.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * This program is distributed in the hope that it will be useful,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * but WITHOUT ANY WARRANTY; without even the implied warranty of
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * GNU General Public License for more details.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * You should have received a copy of the GNU General Public License
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * along with this program; if not, write to the Free Software
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Use is subject to license terms.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <shared.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <term.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifdef SUPPORT_HERCULES
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe# include <hercules.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifdef SUPPORT_SERIAL
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe# include <serial.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestruct term_entry term_table[] =
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe "console",
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 24,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_putchar,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_checkkey,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_getkey,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_getxy,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_gotoxy,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_cls,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_setcolorstate,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_setcolor,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_setcursor,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe },
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifdef SUPPORT_SERIAL
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe "serial",
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* A serial device must be initialized. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe TERM_NEED_INIT,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 24,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe serial_putchar,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe serial_checkkey,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe serial_getkey,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe serial_getxy,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe serial_gotoxy,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe serial_cls,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe serial_setcolorstate,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe },
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe "composite",
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe TERM_NEED_INIT,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 24,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe composite_putchar,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe composite_checkkey,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe composite_getkey,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe serial_getxy,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe composite_gotoxy,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe composite_cls,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe composite_setcolorstate,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_setcolor,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_setcursor,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe },
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* SUPPORT_SERIAL */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifdef SUPPORT_HERCULES
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe "hercules",
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 24,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe hercules_putchar,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_checkkey,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_getkey,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe hercules_getxy,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe hercules_gotoxy,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe hercules_cls,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe hercules_setcolorstate,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe hercules_setcolor,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe hercules_setcursor,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 0
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe },
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* SUPPORT_HERCULES */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifdef SUPPORT_GRAPHICS
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe { "graphics",
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe TERM_NEED_INIT, /* flags */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe 30, /* number of lines */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_putchar, /* putchar */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_checkkey, /* checkkey */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe console_getkey, /* getkey */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_getxy, /* getxy */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_gotoxy, /* gotoxy */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_cls, /* cls */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_setcolorstate, /* setcolorstate */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_setcolor, /* setcolor */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_setcursor, /* nocursor */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_init, /* initialize */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe graphics_end /* shutdown */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe },
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* SUPPORT_GRAPHICS */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* This must be the last entry. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe };
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/* This must be console. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestruct term_entry *current_term = term_table;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint max_lines = 24;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint count_lines = -1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint use_pager = 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweprint_error (void)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (errnum > ERR_NONE && errnum < MAX_ERR_NUM)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* printf("\7\n %s\n", err_list[errnum]); */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe printf ("\nError %u: %s\n", errnum, err_list[errnum]);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#else /* STAGE1_5 */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe printf ("Error %u\n", errnum);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* STAGE1_5 */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowechar *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweconvert_to_ascii (char *buf, int c,...)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe unsigned long num = *((&c) + 1), mult = 10;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *ptr = buf;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c == 'x' || c == 'X')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mult = 16;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if ((num & 0x80000000uL) && c == 'd')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe num = (~num) + 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *(ptr++) = '-';
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe buf++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe do
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int dig = num % mult;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *(ptr++) = ((dig > 9) ? dig + 'a' - 10 : '0' + dig);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (num /= mult);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* reorder to correct direction!! */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *ptr1 = ptr - 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *ptr2 = buf;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (ptr1 > ptr2)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int tmp = *ptr1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *ptr1 = *ptr2;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *ptr2 = tmp;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ptr1--;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ptr2++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return ptr;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_putstr (const char *str)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (*str)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (*str++);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic void
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_vprintf (const char *format, int *dataptr)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char c, str[16];
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while ((c = *(format++)) != 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c != '%')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (c);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe switch (c = *(format++))
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 'd':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 'x':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 'X':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 'u':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putstr (str);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 'c':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ((*(dataptr++)) & 0xff);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 's':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putstr ((char *) *(dataptr++));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweinit_page (void)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cls ();
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_printf ("\n GNU GRUB version %s (%dK lower / %dK upper memory)\n\n",
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe version_string, mbi.mem_lower, mbi.mem_upper);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/* The number of the history entries. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic int num_history = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/* Get the NOth history. If NO is less than zero or greater than or
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe equal to NUM_HISTORY, return NULL. Otherwise return a valid string. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic char *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweget_history (int no)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (no < 0 || no >= num_history)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (char *) HISTORY_BUF + MAX_CMDLINE * no;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/* Add CMDLINE to the history buffer. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic void
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweadd_history (const char *cmdline, int no)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove ((char *) HISTORY_BUF + MAX_CMDLINE * (no + 1),
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe (char *) HISTORY_BUF + MAX_CMDLINE * no,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe MAX_CMDLINE * (num_history - no));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_strcpy ((char *) HISTORY_BUF + MAX_CMDLINE * no, cmdline);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (num_history < HISTORY_SIZE)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe num_history++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic int
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowereal_get_cmdline (char *prompt, char *cmdline, int maxlen,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int echo_char, int readline)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* This is a rather complicated function. So explain the concept.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe A command-line consists of ``section''s. A section is a part of the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe line which may be displayed on the screen, but a section is never
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe displayed with another section simultaneously.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe Each section is basically 77 or less characters, but the exception
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe is the first section, which is 78 or less characters, because the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe starting point is special. See below.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe The first section contains a prompt and a command-line (or the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe first part of a command-line when it is too long to be fit in the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe screen). So, in the first section, the number of command-line
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe characters displayed is 78 minus the length of the prompt (or
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe less). If the command-line has more characters, `>' is put at the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe position 78 (zero-origin), to inform the user of the hidden
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe characters.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe Other sections always have `<' at the first position, since there
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe is absolutely a section before each section. If there is a section
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe after another section, this section consists of 77 characters and
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe `>' at the last position. The last section has 77 or less
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe characters and doesn't have `>'.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe Each section other than the last shares some characters with the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe previous section. This region is called ``margin''. If the cursor
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe is put at the magin which is shared by the first section and the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe second, the first section is displayed. Otherwise, a displayed
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe section is switched to another section, only if the cursor is put
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe outside that section. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* XXX: These should be defined in shared.h, but I leave these here,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe until this code is freezed. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define CMDLINE_WIDTH 78
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define CMDLINE_MARGIN 10
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int xpos, lpos, c, section;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* The length of PROMPT. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int plen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* The length of the command-line. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int llen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* The index for the history. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int history = -1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* The working buffer for the command-line. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *buf = (char *) CMDLINE_BUF;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* The kill buffer. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *kill_buf = (char *) KILL_BUF;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Nested function definitions for code simplicity. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* The forward declarations of nested functions are prefixed
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe with `auto'. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe auto void cl_refresh (int full, int len);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe auto void cl_backward (int count);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe auto void cl_forward (int count);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe auto void cl_insert (const char *str);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe auto void cl_delete (int count);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe auto void cl_init (void);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Move the cursor backward. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe void cl_backward (int count)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe lpos -= count;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If the cursor is in the first section, display the first section
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe instead of the second. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (section == 1 && plen + lpos < CMDLINE_WIDTH)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (1, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else if (xpos - count < 1)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (1, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe xpos -= count;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (current_term->flags & TERM_DUMB)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int i;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe for (i = 0; i < count; i++)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('\b');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe gotoxy (xpos, getxy () & 0xFF);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Move the cursor forward. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe void cl_forward (int count)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe lpos += count;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If the cursor goes outside, scroll the screen to the right. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (xpos + count >= CMDLINE_WIDTH)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (1, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe xpos += count;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (current_term->flags & TERM_DUMB)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int i;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe for (i = lpos - count; i < lpos; i++)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! echo_char)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (buf[i]);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (echo_char);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe gotoxy (xpos, getxy () & 0xFF);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Refresh the screen. If FULL is true, redraw the full line, otherwise,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe only LEN characters from LPOS. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe void cl_refresh (int full, int len)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int i;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int start;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int pos = xpos;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (full)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Recompute the section number. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (lpos + plen < CMDLINE_WIDTH)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe section = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe section = ((lpos + plen - CMDLINE_WIDTH)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* From the start to the end. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe len = CMDLINE_WIDTH;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe pos = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('\r');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If SECTION is the first section, print the prompt, otherwise,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe print `<'. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (section == 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_printf ("%s", prompt);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe len -= plen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe pos += plen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('<');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe len--;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe pos++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Compute the index to start writing BUF and the resulting position
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe on the screen. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (section == 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int offset = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! full)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe offset = xpos - plen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe start = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe xpos = lpos + plen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe start += offset;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int offset = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! full)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe offset = xpos - 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe xpos = lpos + 1 - start;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe start += offset;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Print BUF. If ECHO_CHAR is not zero, put it instead. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe for (i = start; i < start + len && i < llen; i++)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! echo_char)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (buf[i]);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (echo_char);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe pos++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Fill up the rest of the line with spaces. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe for (; i < start + len; i++)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (' ');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe pos++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If the cursor is at the last position, put `>' or a space,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe depending on if there are more characters in BUF. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (pos == CMDLINE_WIDTH)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (start + len < llen)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('>');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (' ');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe pos++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Back to XPOS. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (current_term->flags & TERM_DUMB)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe for (i = 0; i < pos - xpos; i++)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('\b');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe gotoxy (xpos, getxy () & 0xFF);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Initialize the command-line. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe void cl_init (void)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Distinguish us from other lines and error messages! */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('\n');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Print full line and set position here. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (1, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Insert STR to BUF. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe void cl_insert (const char *str)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int l = grub_strlen (str);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (llen + l < maxlen)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (lpos == llen)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove (buf + lpos, str, l + 1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove (buf + lpos, str, l);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe llen += l;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe lpos += l;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (xpos + l >= CMDLINE_WIDTH)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (1, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else if (xpos + l + llen - lpos > CMDLINE_WIDTH)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (0, CMDLINE_WIDTH - xpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (0, l + llen - lpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Delete COUNT characters in BUF. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe void cl_delete (int count)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe llen -= count;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (xpos + llen + count - lpos > CMDLINE_WIDTH)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (0, CMDLINE_WIDTH - xpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (0, llen + count - lpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe plen = grub_strlen (prompt);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe llen = grub_strlen (cmdline);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (maxlen > MAX_CMDLINE)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe maxlen = MAX_CMDLINE;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (llen >= MAX_CMDLINE)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe llen = MAX_CMDLINE - 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cmdline[MAX_CMDLINE] = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe lpos = llen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_strcpy (buf, cmdline);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_init ();
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If READLINE is non-zero, handle readline-like key bindings. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (readline)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe switch (c)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 9: /* TAB lists completions */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int i;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* POS points to the first space after a command. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int pos = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int ret;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *completion_buffer = (char *) COMPLETION_BUF;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int equal_pos = -1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int is_filename;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Find the first word. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (buf[pos] == ' ')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe pos++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe pos++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe is_filename = (lpos > pos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Find the position of the equal character after a
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe command, and replace it with a space. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe for (i = pos; buf[i] && buf[i] != ' '; i++)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (buf[i] == '=')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe equal_pos = i;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe buf[i] = ' ';
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Find the position of the first character in this
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe word. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe for (i = lpos; i > 0 && buf[i - 1] != ' '; i--)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Invalidate the cache, because the user may exchange
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe removable disks. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe buf_drive = -1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Copy this word to COMPLETION_BUFFER and do the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe completion. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove (completion_buffer, buf + i, lpos - i);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe completion_buffer[lpos - i] = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ret = print_completions (is_filename, 1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe errnum = ERR_NONE;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (ret >= 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Found, so insert COMPLETION_BUFFER. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_insert (completion_buffer + lpos - i);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (ret > 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* There are more than one candidates, so print
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe the list. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('\n');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe print_completions (is_filename, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe errnum = ERR_NONE;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Restore the command-line. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (equal_pos >= 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe buf[equal_pos] = '=';
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (ret)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_init ();
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 1: /* C-a go to beginning of line */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_backward (lpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 5: /* C-e go to end of line */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_forward (llen - lpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 6: /* C-f forward one character */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (lpos < llen)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_forward (1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 2: /* C-b backward one character */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (lpos > 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_backward (1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 21: /* C-u kill to beginning of line */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (lpos == 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Copy the string being deleted to KILL_BUF. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove (kill_buf, buf, lpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe kill_buf[lpos] = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* XXX: Not very clever. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int count = lpos;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_backward (lpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_delete (count);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 11: /* C-k kill to end of line */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (lpos == llen)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Copy the string being deleted to KILL_BUF. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove (kill_buf, buf + lpos, llen - lpos + 1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_delete (llen - lpos);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 25: /* C-y yank the kill buffer */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_insert (kill_buf);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 16: /* C-p fetch the previous command */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *p;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (history < 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Save the working buffer. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_strcpy (cmdline, buf);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else if (grub_strcmp (get_history (history), buf) != 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If BUF is modified, add it into the history list. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe add_history (buf, history);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe history++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe p = get_history (history);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! p)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe history--;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_strcpy (buf, p);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe llen = grub_strlen (buf);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe lpos = llen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (1, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 14: /* C-n fetch the next command */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *p;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (history < 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else if (grub_strcmp (get_history (history), buf) != 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If BUF is modified, add it into the history list. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe add_history (buf, history);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe history--;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe p = get_history (history);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! p)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe p = cmdline;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_strcpy (buf, p);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe llen = grub_strlen (buf);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe lpos = llen;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_refresh (1, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* ESC, C-d and C-h are always handled. Actually C-d is not
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe functional if READLINE is zero, as the cursor cannot go
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe backward, but that's ok. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe switch (c)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 27: /* ESC immediately return 1 */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 4: /* C-d delete character under cursor */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (lpos == llen)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_delete (1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 8: /* C-h backspace */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe# ifdef GRUB_UTIL
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 127: /* also backspace */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe# endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (lpos > 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_backward (1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_delete (1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe default: /* insert printable character into line */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c >= ' ' && c <= '~')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char str[2];
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe str[0] = c;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe str[1] = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cl_insert (str);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('\n');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If ECHO_CHAR is NUL, remove the leading spaces. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe lpos = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! echo_char)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (buf[lpos] == ' ')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe lpos++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Copy the working buffer to CMDLINE. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_memmove (cmdline, buf + lpos, llen - lpos + 1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* If the readline-like feature is turned on and CMDLINE is not
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe empty, add it into the history list. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (readline && lpos < llen)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe add_history (cmdline, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/* Don't use this with a MAXLEN greater than 1600 or so! The problem
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe is that GET_CMDLINE depends on the everything fitting on the screen
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe at once. So, the whole screen is about 2000 characters, minus the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe PROMPT, and space for error and status lines, etc. MAXLEN must be
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe at least 1, and PROMPT and CMDLINE must be valid strings (not NULL
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe or zero-length).
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe If ECHO_CHAR is nonzero, echo it instead of the typed character. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweget_cmdline (char *prompt, char *cmdline, int maxlen,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int echo_char, int readline)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int old_cursor;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int ret;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe old_cursor = setcursor (1);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Because it is hard to deal with different conditions simultaneously,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe less functional cases are handled here. Assume that TERM_NO_ECHO
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe implies TERM_NO_EDIT. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (current_term->flags & (TERM_NO_ECHO | TERM_NO_EDIT))
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *p = cmdline;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int c;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Make sure that MAXLEN is not too large. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (maxlen > MAX_CMDLINE)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe maxlen = MAX_CMDLINE;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Print only the prompt. The contents of CMDLINE is simply discarded,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe even if it is not empty. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_printf ("%s", prompt);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Gather characters until a newline is gotten. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Return immediately if ESC is pressed. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c == 27)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe setcursor (old_cursor);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Printable characters are added into CMDLINE. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c >= ' ' && c <= '~')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! (current_term->flags & TERM_NO_ECHO))
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar (c);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Preceding space characters must be ignored. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c != ' ' || p != cmdline)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *p++ = c;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *p = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (! (current_term->flags & TERM_NO_ECHO))
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_putchar ('\n');
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe setcursor (old_cursor);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* Complicated features are left to real_get_cmdline. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ret = real_get_cmdline (prompt, cmdline, maxlen, echo_char, readline);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe setcursor (old_cursor);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return ret;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesafe_parse_maxint (char **str_ptr, int *myint_ptr)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *ptr = *str_ptr;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int myint = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int mult = 10, found = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Is this a hex number?
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (*ptr == '0' && tolower (*(ptr + 1)) == 'x')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ptr += 2;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mult = 16;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (1)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* A bit tricky. This below makes use of the equivalence:
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe (A >= B && A <= C) <=> ((A - B) <= (C - B))
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe when C > B and A is unsigned. */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe unsigned int digit;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe digit = tolower (*ptr) - '0';
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (digit > 9)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe digit -= 'a' - '0';
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (mult == 10 || digit > 5)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe digit += 10;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe found = 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (myint > ((MAXINT - digit) / mult))
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe errnum = ERR_NUMBER_OVERFLOW;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe myint = (myint * mult) + digit;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ptr++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (!found)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe errnum = ERR_NUMBER_PARSING;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *str_ptr = ptr;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *myint_ptr = myint;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* STAGE1_5 */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#if !defined(STAGE1_5) || defined(FSYS_ZFS)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic int
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_vsprintf (char *buffer, const char *format, int *dataptr)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* XXX hohmuth
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ugly hack -- should unify with printf() */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char c, *ptr, str[16];
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe char *bp = buffer;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int len = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while ((c = *format++) != 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c != '%') {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (buffer)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *bp++ = c; /* putchar(c); */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe len++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe } else {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe switch (c = *(format++))
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 'd': case 'u': case 'x':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ptr = str;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (*ptr) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (buffer)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *bp++ = *(ptr++); /* putchar(*(ptr++)); */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ptr++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe len++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 'c':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (buffer)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *bp++ = (*(dataptr++))&0xff;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe dataptr++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe len++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* putchar((*(dataptr++))&0xff); */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case 's':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ptr = (char *) (*(dataptr++));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while ((c = *ptr++) != 0) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (buffer)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *bp++ = c; /* putchar(c); */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe len++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *bp = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (len);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_sprintf (char *buffer, const char *format, ...)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int *dataptr = (int *) &format;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe dataptr++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (grub_vsprintf (buffer, format, dataptr));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* !defined(STAGE1_5) || defined(FSYS_ZFS) */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowenoisy_printf (const char *format,...)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int *dataptr = (int *) &format;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe dataptr++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_vprintf(format, dataptr);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * print to a buffer, unless verbose mode is on
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * if verbos mode is switched on, the buffer is dumped in verbose_func()
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_printf (const char *format,...)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int len;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int *dataptr = (int *) &format;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe dataptr++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (silent.status != SILENT)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_vprintf(format, dataptr);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe len = grub_vsprintf(NULL, format, dataptr);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (silent.buffer_start - silent.buffer + len + 1 >=
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe SCREENBUF) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe silent.buffer_start = silent.buffer;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe silent.looped = 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (len < SCREENBUF) /* all other cases loop safely */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe silent.buffer_start +=
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe grub_vsprintf(silent.buffer_start, format, dataptr);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#if !defined(STAGE1_5) || defined(FSYS_FAT)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_tolower (int c)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c >= 'A' && c <= 'Z')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (c + ('a' - 'A'));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return c;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* ! STAGE1_5 || FSYS_FAT */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_isspace (int c)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe switch (c)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case ' ':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case '\t':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case '\r':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case '\n':
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe default:
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#if !defined(STAGE1_5) || defined(FSYS_ISO9660)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_memcmp (const char *s1, const char *s2, int n)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (n)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (*s1 < *s2)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return -1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else if (*s1 > *s2)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe s1++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe s2++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe n--;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* ! STAGE1_5 || FSYS_ISO9660 */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#ifndef STAGE1_5
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_strncat (char *s1, const char *s2, int n)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int i = -1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (++i < n && s1[i] != 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (i < n && (s1[i++] = *(s2++)) != 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe s1[n - 1] = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (i >= n)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe s1[i] = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#endif /* ! STAGE1_5 */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/* XXX: This below is an evil hack. Certainly, we should change the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe strategy to determine what should be defined and what shouldn't be
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe defined for each image. For example, it would be better to create
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe a static library supporting minimal standard C functions and link
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe each image with the library. Complicated things should be left to
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe computer, definitely. -okuji */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/* Make some grub_str* routines available to ZFS plug-in as well */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#if !defined(STAGE1_5) || defined(FSYS_VSTAFS) || defined(FSYS_ZFS)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_strcmp (const char *s1, const char *s2)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (*s1 || *s2)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (*s1 < *s2)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return -1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe else if (*s1 > *s2)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe s1 ++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe s2 ++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowegrub_strncmp(const char *s1, const char *s2, int n)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (s1 == s2)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe n++;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while (--n != 0 && *s1 == *s2++)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (*s1++ == '\0')
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return ((n == 0) ? 0 : *(unsigned char *)s1 - *(unsigned char *)--s2);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
#endif /* ! STAGE1_5 || FSYS_VSTAFS || defined(FSYS_ZFS) */
#ifndef STAGE1_5
/* Wait for a keypress and return its code. */
int
getkey (void)
{
return current_term->getkey ();
}
/* Check if a key code is available. */
int
checkkey (void)
{
return current_term->checkkey ();
}
#endif /* ! STAGE1_5 */
/* Display an ASCII character. */
void
grub_putchar (int c)
{
if (c == '\n')
grub_putchar ('\r');
#ifndef STAGE1_5
else if (c == '\t' && current_term->getxy)
{
int n;
n = 8 - ((current_term->getxy () >> 8) & 3);
while (n--)
grub_putchar (' ');
return;
}
#endif /* ! STAGE1_5 */
#ifdef STAGE1_5
/* In Stage 1.5, only the normal console is supported. */
console_putchar (c);
#else /* ! STAGE1_5 */
if (c == '\n')
{
/* Internal `more'-like feature. */
if (count_lines >= 0)
{
count_lines++;
if (count_lines >= max_lines - 2)
{
int tmp;
/* It's important to disable the feature temporarily, because
the following grub_printf call will print newlines. */
count_lines = -1;
grub_printf("\n");
if (current_term->setcolorstate)
current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
grub_printf ("[Hit return to continue]");
if (current_term->setcolorstate)
current_term->setcolorstate (COLOR_STATE_NORMAL);
do
{
tmp = ASCII_CHAR (getkey ());
}
while (tmp != '\n' && tmp != '\r');
grub_printf ("\r \r");
/* Restart to count lines. */
count_lines = 0;
return;
}
}
}
current_term->putchar (c);
#endif /* ! STAGE1_5 */
}
#ifndef STAGE1_5
void
gotoxy (int x, int y)
{
current_term->gotoxy (x, y);
}
int
getxy (void)
{
return current_term->getxy ();
}
void
cls (void)
{
/* If the terminal is dumb, there is no way to clean the terminal. */
if (current_term->flags & TERM_DUMB)
grub_putchar ('\n');
else
current_term->cls ();
}
int
setcursor (int on)
{
if (current_term->setcursor)
return current_term->setcursor (on);
return 1;
}
#endif /* ! STAGE1_5 */
int
substring (const char *s1, const char *s2)
{
while (*s1 == *s2)
{
/* The strings match exactly. */
if (! *(s1++))
return 0;
s2 ++;
}
/* S1 is a substring of S2. */
if (*s1 == 0)
return -1;
/* S1 isn't a substring. */
return 1;
}
#if !defined(STAGE1_5) || defined(FSYS_ZFS)
char *
grub_strstr (const char *s1, const char *s2)
{
while (*s1)
{
const char *ptr, *tmp;
ptr = s1;
tmp = s2;
while (*tmp && *ptr == *tmp)
ptr++, tmp++;
if (tmp > s2 && ! *tmp)
return (char *) s1;
s1++;
}
return 0;
}
int
grub_strlen (const char *str)
{
int len = 0;
while (*str++)
len++;
return len;
}
#endif /* !defined(STAGE1_5) || defined(FSYS_ZFS) */
#ifndef STAGE1_5
/* Terminate the string STR with NUL. */
int
nul_terminate (char *str)
{
int ch;
while (*str && ! grub_isspace (*str))
str++;
ch = *str;
*str = 0;
return ch;
}
char *
grub_strchr (char *str, char c)
{
for (; *str && (*str != c); str++);
return (*str ? str : NULL);
}
#endif /* ! STAGE1_5 */
int
memcheck (unsigned long addr, unsigned long len)
{
int local_errnum = 0;
#ifdef GRUB_UTIL
auto unsigned long start_addr (void);
auto unsigned long end_addr (void);
auto unsigned long start_addr (void)
{
int ret;
# if defined(HAVE_START_SYMBOL)
asm volatile ("movl $start, %0" : "=a" (ret));
# elif defined(HAVE_USCORE_START_SYMBOL)
asm volatile ("movl $_start, %0" : "=a" (ret));
# endif
return ret;
}
auto unsigned long end_addr (void)
{
int ret;
# if defined(HAVE_END_SYMBOL)
asm volatile ("movl $end, %0" : "=a" (ret));
# elif defined(HAVE_USCORE_END_SYMBOL)
asm volatile ("movl $_end, %0" : "=a" (ret));
# endif
return ret;
}
if (start_addr () <= addr && end_addr () > addr + len)
return ! local_errnum;
#endif /* GRUB_UTIL */
if ((addr < RAW_ADDR (0x1000))
|| (addr < RAW_ADDR (0x100000)
&& RAW_ADDR (mbi.mem_lower * 1024) < (addr + len))
|| (addr >= RAW_ADDR (0x100000)
&& RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
local_errnum = ERR_WONT_FIT;
if (errnum == 0) /* preserve original errnum */
errnum = local_errnum;
return ! local_errnum;
}
void
grub_memcpy(void *dest, const void *src, int len)
{
int i;
register char *d = (char*)dest, *s = (char*)src;
for (i = 0; i < len; i++)
d[i] = s[i];
}
void *
grub_memmove (void *to, const void *from, int len)
{
if (memcheck ((int) to, len))
{
/* This assembly code is stolen from
linux-2.2.2/include/asm-i386/string.h. This is not very fast
but compact. */
int d0, d1, d2;
if (to < from)
{
asm volatile ("cld\n\t"
"rep\n\t"
"movsb"
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
: "0" (len),"1" (from),"2" (to)
: "memory");
}
else
{
asm volatile ("std\n\t"
"rep\n\t"
"movsb\n\t"
"cld"
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
: "0" (len),
"1" (len - 1 + (const char *) from),
"2" (len - 1 + (char *) to)
: "memory");
}
return to;
}
return NULL;
}
void *
grub_memset (void *start, int c, int len)
{
char *p = start;
if (memcheck ((int) start, len))
{
while (len -- > 0)
*p ++ = c;
}
return errnum ? NULL : start;
}
#ifndef STAGE1_5
char *
grub_strcpy (char *dest, const char *src)
{
grub_memmove (dest, src, grub_strlen (src) + 1);
return dest;
}
#endif /* ! STAGE1_5 */
#ifndef GRUB_UTIL
# undef memcpy
/* GCC emits references to memcpy() for struct copies etc. */
void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));
#endif