/* $Revision: 1.2 $ */

/*
 * Copyright (c) 1983 Regents of the University of California. All rights
 * reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer. 2.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution. 3. All advertising
 * materials mentioning features or use of this software must display the
 * following acknowledgement: This product includes software developed by the
 * University of California, Berkeley and its contributors. 4. Neither the
 * name of the University nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific
 * prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * UNIX stdio-like I/O package (polling version). These are useful kernel
 * debug I/O messages. Tasks that need to be preempted should use non-polling
 * versions -- notably, getchar() instead of kgetchar(), and gets() instead
 * of kgets().
 */

#include <locore.h>
#include <bsp.h>
#include <common.h>
#include <kern.h>
#include <sem.h>
#include <string.h>


#define I_AM_UGLY

#ifdef I_AM_UGLY
#include <varargs.h>
extern void   do_printf(void (*do_putc) (char), va_list );
#else
#include <stdio.h>
#endif



/* void kstdio_init(void); */
/* int kgetchar(void); */
/* char *kgets(void); */
/* void kputchar(char ch); */
/* void do_printf(void (*do_putc) (char), va_list pvar); */
/* void dump(int addr, int len); */
/* void panic(char *msg); */


extern volatile char *tty;

int paniced = 0;
char panic_msg[BUFSIZ];
char *panic_str = panic_msg;

void
kstdio_init(void)
{
}

extern char cinput[];
extern int cinput_i;
extern int coutput_i;

int kgetchar(void){
  int ch;
  
  if (cinput_i == coutput_i){
    return -1;
  }
  ch = cinput[coutput_i];
  coutput_i = (coutput_i + 1) % BUFSIZ;
  return (ch);
}

char * kgets(void){
  static char buf[BUFSIZ];
  static char *str = buf;
  char ch;
  char *org = str;

  do {
    if ((ch = kgetchar()) < 0)
      continue;
    *str = ch;
    str++;
  }
  while (!isnewline(ch));
  *str = '\0';
  return org;
}

void kputchar(char ch){
  if (ch == '\n')
    tty_poll_write(tty, '\r');
  if (ch == '\r')
    tty_poll_write(tty, '\n');
  tty_poll_write(tty, ch);
  if (paniced)		/* put a copy in panic memory location */
    *panic_str++ = ch;
}

void kputs(char * str){
  char * cnt = str;
  while( *cnt != 0 ){
    kputchar( *cnt );
    cnt ++ ;
  }
}

char hexdigits[] = "0123456789abcdef";

/* bis do_printf nicht sauber läuft muss das ding exportiert werden */
/* static */ char * ksprintn(long unsigned int ul, int base, int *lenp)
{
  static char buf[20];
  register char *p;
  
  p = buf;
  *p = '\0';
  do {
    *++p = hexdigits[ul % base];
  }
  while (ul /= base);
  if (lenp)
    *lenp = p - buf;
  return p;
}

#ifdef I_AM_UGLY

void kprintf( va_alist )
     va_dcl 
{
  va_list pvar;
  
  va_start(pvar);
  do_printf(kputchar,pvar);
  va_end(pvar);
}

#else

void kprintf(char * fmt, ...)
{
  va_list pvar;
  
  va_start(pvar,fmt);
  do_printf(kputchar, fmt ,pvar);
  va_end(pvar);
}
#endif /* I_AM_UGLY */

/* table of printable ASCII characters */
u_char *ascii_table = (u_char *) " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.";

void dump(int addr, int len){
  int i, j;
  u_char buf[33];/* 32 chars plus NUL */
  u_char *bp = buf;
  u_char *ap;
  u_long val;

  /* assume 4 bytes alignment */
  for (i = 0; i < len; i += 4, addr += 4) {
    if ((i % 0x10) == 0) {
      if (i != 0) {
	kprintf(" %s\n", buf);
	bp = buf;
      }
      kprintf(" %8.0h: ", addr);
    }
    ap = (u_char *) addr;
    val = (u_long) (((int) *ap) << 24 |
		    ((int) *(ap + 1)) << 16 |
		    ((int) *(ap + 2)) << 8 |
		    ((int) *(ap + 3)));
    kprintf("%8.0x ", val);
    for (ap = (u_char *) addr, j = 0; j < 4; j++, ap++, bp++) {
      if ((int) (*ap) < 128 && (int) (*ap) > 31)
	*bp = ascii_table[(int) (*ap) - 32];
      else
	*bp = '.';
    }
    *bp = '\0';
  }
  kprintf("  %s\n", buf);
}

void panic(char *msg) {
  paniced = 1;		/* signal panic msg to be copied to memory */
  kprintf("\nPANIC: ");
  kprintf(msg);
  kputchar('\n');
  halt();
}

/* #ifdef DEBUG */
/* void debug(va_alist) */
/*      va_dcl */
/* { */
/*   va_list pvar; */
  
/*   va_start(pvar); */
/*   do_printf(kputchar, pvar); */
/*   va_end(pvar); */
/* } */

/* #else */
/* void debug(char *fmt,...){ */
/* } */
/* #endif */
