Merge branch 'master' into rosh_for_hpa
[profile/ivi/syslinux.git] / memdisk / conio.c
index 34a75b3..d1f0862 100644 (file)
@@ -1,12 +1,11 @@
-#ident "$Id$"
 /* ----------------------------------------------------------------------- *
- *   
- *   Copyright 2001 H. Peter Anvin - All Rights Reserved
+ *
+ *   Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
- *   Bostom MA 02111-1307, USA; either version 2 of the License, or
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
  *   (at your option) any later version; incorporated herein by reference.
  *
  * ----------------------------------------------------------------------- */
 
 int putchar(int ch)
 {
-  com32sys_t regs;
+    com32sys_t regs;
+
+    if (ch == '\n') {
+       /* \n -> \r\n */
+       putchar('\r');
+    }
 
-  if ( ch == '\n' ) {
-    /* \n -> \r\n */
-    putchar('\r');
-  }
-  
-  regs.eax.w[0] = 0x0e00|(ch&0xff);
-  syscall(0x10, &regs, NULL);
+    regs.eax.w[0] = 0x0e00 | (ch & 0xff);
+    intcall(0x10, &regs, NULL);
 
-  return ch;
+    return ch;
 }
 
 int puts(const char *s)
 {
-  int count = 0;
+    int count = 0;
 
-  while ( *s ) {
-    putchar(*s);
-    count++;
-    s++;
-  }
+    while (*s) {
+       putchar(*s);
+       count++;
+       s++;
+    }
 
-  return count;
+    return count;
 }
 
 /*
@@ -59,37 +58,37 @@ int puts(const char *s)
  * modified.
  */
 
-static inline int
-isdigit(int ch)
+static inline int isdigit(int ch)
 {
-  return (ch >= '0') && (ch <= '9');
+    return (ch >= '0') && (ch <= '9');
 }
 
 static int skip_atoi(const char **s)
 {
-  int i=0;
-  
-  while (isdigit(**s))
-    i = i*10 + *((*s)++) - '0';
-  return i;
+    int i = 0;
+
+    while (isdigit(**s))
+       i = i * 10 + *((*s)++) - '0';
+    return i;
 }
 
 unsigned int atou(const char *s)
 {
-  unsigned int i = 0;
-  while (isdigit(*s))
-    i = i*10 + (*s++ - '0');
-  return i;
+    unsigned int i = 0;
+    while (isdigit(*s))
+       i = i * 10 + (*s++ - '0');
+    return i;
 }
 
 static int strnlen(const char *s, int maxlen)
 {
-  const char *es = s;
-  while ( *es && maxlen ) {
-    es++; maxlen--;
-  }
+    const char *es = s;
+    while (*es && maxlen) {
+       es++;
+       maxlen--;
+    }
 
-  return (es-s);
+    return (es - s);
 }
 
 #define ZEROPAD        1               /* pad with zero */
@@ -106,260 +105,290 @@ __res = ((unsigned long) n) % (unsigned) base; \
 n = ((unsigned long) n) / (unsigned) base; \
 __res; })
 
-static char * number(char * str, long num, int base, int size, int precision
-       ,int type)
+static char *number(char *str, long num, int base, int size, int precision,
+                   int type)
 {
-  char c,sign,tmp[66];
-  const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
-  int i;
-  
-  if (type & LARGE)
-    digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  if (type & LEFT)
-    type &= ~ZEROPAD;
-  if (base < 2 || base > 36)
-    return 0;
-  c = (type & ZEROPAD) ? '0' : ' ';
-  sign = 0;
-  if (type & SIGN) {
-    if (num < 0) {
-      sign = '-';
-      num = -num;
-      size--;
-    } else if (type & PLUS) {
-      sign = '+';
-      size--;
-    } else if (type & SPACE) {
-      sign = ' ';
-      size--;
+    char c, sign, tmp[66];
+    const char *digits = "0123456789abcdef";
+    int i;
+
+    if (type & LARGE)
+       digits = "0123456789ABCDEF";
+    if (type & LEFT)
+       type &= ~ZEROPAD;
+    if (base < 2 || base > 36)
+       return 0;
+    c = (type & ZEROPAD) ? '0' : ' ';
+    sign = 0;
+    if (type & SIGN) {
+       if (num < 0) {
+           sign = '-';
+           num = -num;
+           size--;
+       } else if (type & PLUS) {
+           sign = '+';
+           size--;
+       } else if (type & SPACE) {
+           sign = ' ';
+           size--;
+       }
+    }
+    if (type & SPECIAL) {
+       if (base == 16)
+           size -= 2;
+       else if (base == 8)
+           size--;
     }
-  }
-  if (type & SPECIAL) {
-    if (base == 16)
-      size -= 2;
-    else if (base == 8)
-      size--;
-  }
-  i = 0;
-  if (num == 0)
-    tmp[i++]='0';
-  else while (num != 0)
-    tmp[i++] = digits[do_div(num,base)];
-  if (i > precision)
-    precision = i;
-  size -= precision;
-  if (!(type&(ZEROPAD+LEFT)))
-    while(size-->0)
-      *str++ = ' ';
-  if (sign)
-    *str++ = sign;
-  if (type & SPECIAL) {
-    if (base==8)
-      *str++ = '0';
-    else if (base==16) {
-      *str++ = '0';
-      *str++ = digits[33];
+    i = 0;
+    if (num == 0)
+       tmp[i++] = '0';
+    else
+       while (num != 0)
+           tmp[i++] = digits[do_div(num, base)];
+    if (i > precision)
+       precision = i;
+    size -= precision;
+    if (!(type & (ZEROPAD + LEFT)))
+       while (size-- > 0)
+           *str++ = ' ';
+    if (sign)
+       *str++ = sign;
+    if (type & SPECIAL) {
+       if (base == 8)
+           *str++ = '0';
+       else if (base == 16) {
+           *str++ = '0';
+           *str++ = digits[33];
+       }
     }
-  }
-  if (!(type & LEFT))
+    if (!(type & LEFT))
+       while (size-- > 0)
+           *str++ = c;
+    while (i < precision--)
+       *str++ = '0';
+    while (i-- > 0)
+       *str++ = tmp[i];
     while (size-- > 0)
-      *str++ = c;
-  while (i < precision--)
-    *str++ = '0';
-  while (i-- > 0)
-    *str++ = tmp[i];
-  while (size-- > 0)
-    *str++ = ' ';
-  return str;
+       *str++ = ' ';
+    return str;
 }
 
-/* Forward decl. needed for IP address printing stuff... */
-int sprintf(char * buf, const char *fmt, ...);
-
 int vsprintf(char *buf, const char *fmt, va_list args)
 {
-  int len;
-  unsigned long num;
-  int i, base;
-  char * str;
-  const char *s;
-  
-  int flags;           /* flags to number() */
-  
-  int field_width;     /* width of output field */
-  int precision;               /* min. # of digits for integers; max
+    int len;
+    unsigned long num;
+    int i, base;
+    char *str;
+    const char *s;
+
+    int flags;                 /* flags to number() */
+
+    int field_width;           /* width of output field */
+    int precision;             /* min. # of digits for integers; max
                                   number of chars for from string */
-  int qualifier;               /* 'h', 'l', or 'L' for integer fields */
-  
-  for (str=buf ; *fmt ; ++fmt) {
-    if (*fmt != '%') {
-      *str++ = *fmt;
-      continue;
-    }
-    
-    /* process flags */
-    flags = 0;
-  repeat:
-    ++fmt;             /* this also skips first '%' */
-    switch (*fmt) {
-    case '-': flags |= LEFT; goto repeat;
-    case '+': flags |= PLUS; goto repeat;
-    case ' ': flags |= SPACE; goto repeat;
-    case '#': flags |= SPECIAL; goto repeat;
-    case '0': flags |= ZEROPAD; goto repeat;
-    }
-    
-    /* get field width */
-    field_width = -1;
-    if (isdigit(*fmt))
-      field_width = skip_atoi(&fmt);
-    else if (*fmt == '*') {
-      ++fmt;
-      /* it's the next argument */
-      field_width = va_arg(args, int);
-      if (field_width < 0) {
-       field_width = -field_width;
-       flags |= LEFT;
-      }
-    }
-    
-    /* get the precision */
-    precision = -1;
-    if (*fmt == '.') {
-      ++fmt;   
-      if (isdigit(*fmt))
-       precision = skip_atoi(&fmt);
-      else if (*fmt == '*') {
-       ++fmt;
-       /* it's the next argument */
-       precision = va_arg(args, int);
-      }
-      if (precision < 0)
-       precision = 0;
-    }
-    
-    /* get the conversion qualifier */
-    qualifier = -1;
-    if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
-      qualifier = *fmt;
-      ++fmt;
-    }
-    
-    /* default base */
-    base = 10;
-    
-    switch (*fmt) {
-    case 'c':
-      if (!(flags & LEFT))
-       while (--field_width > 0)
-         *str++ = ' ';
-      *str++ = (unsigned char) va_arg(args, int);
-      while (--field_width > 0)
-       *str++ = ' ';
-      continue;
-      
-    case 's':
-      s = va_arg(args, char *);
-      len = strnlen(s, precision);
-      
-      if (!(flags & LEFT))
-       while (len < field_width--)
-         *str++ = ' ';
-      for (i = 0; i < len; ++i)
-       *str++ = *s++;
-      while (len < field_width--)
-       *str++ = ' ';
-      continue;
-      
-    case 'p':
-      if (field_width == -1) {
-       field_width = 2*sizeof(void *);
-       flags |= ZEROPAD;
-      }
-      str = number(str,
-                  (unsigned long) va_arg(args, void *), 16,
-                  field_width, precision, flags);
-      continue;
-      
-      
-    case 'n':
-      if (qualifier == 'l') {
-       long * ip = va_arg(args, long *);
-       *ip = (str - buf);
-      } else {
-       int * ip = va_arg(args, int *);
-       *ip = (str - buf);
-      }
-      continue;
-      
-    case '%':
-      *str++ = '%';
-      continue;
-      
-      /* integer number formats - set up the flags and "break" */
-    case 'o':
-      base = 8;
-      break;
-      
-    case 'X':
-      flags |= LARGE;
-    case 'x':
-      base = 16;
-      break;
-      
-    case 'd':
-    case 'i':
-      flags |= SIGN;
-    case 'u':
-      break;
-      
-    default:
-      *str++ = '%';
-      if (*fmt)
-       *str++ = *fmt;
-      else
-       --fmt;
-      continue;
+    int qualifier;             /* 'h', 'l', or 'L' for integer fields */
+
+    for (str = buf; *fmt; ++fmt) {
+       if (*fmt != '%') {
+           *str++ = *fmt;
+           continue;
+       }
+
+       /* process flags */
+       flags = 0;
+repeat:
+       ++fmt;                  /* this also skips first '%' */
+       switch (*fmt) {
+       case '-':
+           flags |= LEFT;
+           goto repeat;
+       case '+':
+           flags |= PLUS;
+           goto repeat;
+       case ' ':
+           flags |= SPACE;
+           goto repeat;
+       case '#':
+           flags |= SPECIAL;
+           goto repeat;
+       case '0':
+           flags |= ZEROPAD;
+           goto repeat;
+       }
+
+       /* get field width */
+       field_width = -1;
+       if (isdigit(*fmt))
+           field_width = skip_atoi(&fmt);
+       else if (*fmt == '*') {
+           ++fmt;
+           /* it's the next argument */
+           field_width = va_arg(args, int);
+           if (field_width < 0) {
+               field_width = -field_width;
+               flags |= LEFT;
+           }
+       }
+
+       /* get the precision */
+       precision = -1;
+       if (*fmt == '.') {
+           ++fmt;
+           if (isdigit(*fmt))
+               precision = skip_atoi(&fmt);
+           else if (*fmt == '*') {
+               ++fmt;
+               /* it's the next argument */
+               precision = va_arg(args, int);
+           }
+           if (precision < 0)
+               precision = 0;
+       }
+
+       /* get the conversion qualifier */
+       qualifier = -1;
+       if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+           qualifier = *fmt;
+           ++fmt;
+       }
+
+       /* default base */
+       base = 10;
+
+       switch (*fmt) {
+       case 'c':
+           if (!(flags & LEFT))
+               while (--field_width > 0)
+                   *str++ = ' ';
+           *str++ = (unsigned char)va_arg(args, int);
+           while (--field_width > 0)
+               *str++ = ' ';
+           continue;
+
+       case 's':
+           s = va_arg(args, char *);
+           len = strnlen(s, precision);
+
+           if (!(flags & LEFT))
+               while (len < field_width--)
+                   *str++ = ' ';
+           for (i = 0; i < len; ++i)
+               *str++ = *s++;
+           while (len < field_width--)
+               *str++ = ' ';
+           continue;
+
+       case 'p':
+           if (field_width == -1) {
+               field_width = 2 * sizeof(void *);
+               flags |= ZEROPAD;
+           }
+           str = number(str,
+                        (unsigned long)va_arg(args, void *), 16,
+                        field_width, precision, flags);
+           continue;
+
+       case 'n':
+           if (qualifier == 'l') {
+               long *ip = va_arg(args, long *);
+               *ip = (str - buf);
+           } else {
+               int *ip = va_arg(args, int *);
+               *ip = (str - buf);
+           }
+           continue;
+
+       case '%':
+           *str++ = '%';
+           continue;
+
+           /* integer number formats - set up the flags and "break" */
+       case 'o':
+           base = 8;
+           break;
+
+       case 'X':
+           flags |= LARGE;
+       case 'x':
+           base = 16;
+           break;
+
+       case 'd':
+       case 'i':
+           flags |= SIGN;
+       case 'u':
+           break;
+
+       default:
+           *str++ = '%';
+           if (*fmt)
+               *str++ = *fmt;
+           else
+               --fmt;
+           continue;
+       }
+       if (qualifier == 'l')
+           num = va_arg(args, unsigned long);
+       else if (qualifier == 'h') {
+           num = (unsigned short)va_arg(args, int);
+           if (flags & SIGN)
+               num = (short)num;
+       } else if (flags & SIGN)
+           num = va_arg(args, int);
+       else
+           num = va_arg(args, unsigned int);
+       str = number(str, num, base, field_width, precision, flags);
     }
-    if (qualifier == 'l')
-      num = va_arg(args, unsigned long);
-    else if (qualifier == 'h') {
-      num = (unsigned short) va_arg(args, int);
-      if (flags & SIGN)
-       num = (short) num;
-    } else if (flags & SIGN)
-      num = va_arg(args, int);
-    else
-      num = va_arg(args, unsigned int);
-    str = number(str, num, base, field_width, precision, flags);
-  }
-  *str = '\0';
-  return str-buf;
+    *str = '\0';
+    return str - buf;
 }
 
-int sprintf(char * buf, const char *fmt, ...)
+#if 0
+int sprintf(char *buf, const char *fmt, ...)
 {
-  va_list args;
-  int i;
-  
-  va_start(args, fmt);
-  i=vsprintf(buf,fmt,args);
-  va_end(args);
-  return i;
+    va_list args;
+    int i;
+
+    va_start(args, fmt);
+    i = vsprintf(buf, fmt, args);
+    va_end(args);
+    return i;
 }
+#endif
 
-int printf(const char *fmt, ...)
+int vprintf(const char *fmt, va_list args)
 {
-  char printf_buf[1024];
-  va_list args;
-  int printed;
+    char printf_buf[2048];
+    int printed;
 
-  va_start(args, fmt);
-  printed = vsprintf(printf_buf, fmt, args);
-  va_end(args);
+    printed = vsprintf(printf_buf, fmt, args);
+    puts(printf_buf);
+    return printed;
+}
 
-  puts(printf_buf);
+int printf(const char *fmt, ...)
+{
+    va_list args;
+    int printed;
 
-  return printed;
+    va_start(args, fmt);
+    printed = vprintf(fmt, args);
+    va_end(args);
+    return printed;
 }
 
+/*
+ * Jump here if all hope is gone...
+ */
+void __attribute__ ((noreturn)) die(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    va_end(ap);
+
+    sti();
+    for (;;)
+       asm volatile("hlt");
+}