/* Very simple and primitive printf
   Copyright (C) 1991, 1992 Free Software Foundation

This file is part of the GNU Hurd.

The GNU Hurd 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; either version 2, or (at your option)
any later version.

The GNU Hurd is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with the GNU Hurd; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by Michael I. Bushnell.  */

#include <libhurd.h>
#include <stdarg.h>
#include <device/device.h>

static void putchar (char c);
static void printn (u_long, int, int);
static device_t console_port;
static struct mutex printflock;

void
printf (char *control, ...)
{
  int c, i, base, u;
  va_list ap;
  char *s;

  mutex_lock (&printflock);
  /* Print filesystem identification XXX */
  s = "UFS: ";
  while (c = *s++)
    putchar (c);
  
  va_start (ap, control);
loop:
  while ((c = *control++) != '%')
    if (c == '\0')
      goto out;
    else
      putchar(c);
  
  switch (*control++)
    {
    case 'u':
      base = 10;
      u = 1;
      goto number;
    case 'd':
      base = 10;
      u = 0;
      goto number;
    case 'o':
      base = 8;
      u = 1;
      goto number;
    case 'x':
      u = 1;
      base = 16;
    number:
      printn(va_arg (ap, u_long), base, u);
      break;
    case 'c':
      for (i = 24; i >= 0; i -= 8)
	if (c = (va_arg (ap, char) >> i) & 0x7f)
	  putchar(c);
    case 's':
      s = va_arg (ap, char *);
      while (c = *s++)
	putchar(c);
      break;
    case '%':
      putchar('%');
      break;
    }
  goto loop;

 out:
  mutex_unlock (&printflock);
}


/* Print a number */
static void
printn(n, b, u)
     u_long n;
     int b, u;
{
  char prbuf[11];
  register char *cp;
  
  if (u && (int)n < 0)
    {
      putchar('-');
      n = (unsigned)(-(int)n);
    }
  cp = prbuf;
  do
    {
      *cp++ = "0123456789abcdef"[n%b];
      n /= b;
    }
  while (n);
  do
    putchar (*--cp);
  while (cp > prbuf);
}

/* Print a single character */
static void
putchar (char c)
{
  int foo;

  if (c == '\n')
    device_write_inband (console_port, 0, 0, "\r", 1, &foo);
  device_write_inband (console_port, 0, 0, &c, 1, &foo);
}

void
set_console_port (device_t con)
{
  console_port = con;
  mutex_init (&printflock);
}
