#include "types.h"
#include "stat.h"
#include "user.h"

static void
putc (int fd, char c)
{
  write (fd, &c, 1);
}

static void
printint (int fd, int xx, int base, int sgn)
{
  static char digits[] = "0123456789ABCDEF";
  char buf[16];
  int i, neg;
  uint x;

  neg = 0;
  if (sgn && xx < 0)
    {
      neg = 1;
      x = -xx;
    }
  else
    {
      x = xx;
    }

  i = 0;
  do
    {
      buf[i++] = digits[x % base];
    }
  while ((x /= base) != 0);
  if (neg)
    buf[i++] = '-';

  while (--i >= 0)
    putc (fd, buf[i]);
}

// Print to the given fd. Only understands %d, %x, %p, %s.
void
printf (int fd, char *fmt, ...)
{
  char *s;
  int c, i, state;
  uint *ap;

  state = 0;
  ap = (uint *) (void *) &fmt + 1;
  for (i = 0; fmt[i]; i++)
    {
      c = fmt[i] & 0xff;
      if (state == 0)
	{
	  if (c == '%')
	    {
	      state = '%';
	    }
	  else
	    {
	      putc (fd, c);
	    }
	}
      else if (state == '%')
	{
	  if (c == 'd')
	    {
	      printint (fd, *ap, 10, 1);
	      ap++;
	    }
	  else if (c == 'x' || c == 'p')
	    {
	      printint (fd, *ap, 16, 0);
	      ap++;
	    }
	  else if (c == 's')
	    {
	      s = (char *) *ap;
	      ap++;
	      if (s == 0)
		s = "(null)";
	      while (*s != 0)
		{
		  putc (fd, *s);
		  s++;
		}
	    }
	  else if (c == 'c')
	    {
	      putc (fd, *ap);
	      ap++;
	    }
	  else if (c == '%')
	    {
	      putc (fd, c);
	    }
	  else
	    {
	      // Unknown % sequence.  Print it to draw attention.
	      putc (fd, '%');
	      putc (fd, c);
	    }
	  state = 0;
	}
    }
}
