#include <stdio.h>
#include <stdarg.h>

/* ************************************************************ */

int atoi(char *s)
{
  int i, n, sign;

  for(i = 0; (s[i] == ' ') || (s[i] == EOL) || (s[i] == '\t'); ++i)
    ;
  sign = 1;
  switch(s[i])
    {
    case '-':
      sign = -1;
      /* and fall through */
    case '+':
      ++i;
      break;
    }
  for(n = 0; isdigit(s[i]); ++i)
    n = 10 * n + s[i] - '0';
  return(sign * n);
}

/* ************************************************************ */

int abs(int num)
{
  if(num < 0)
    return(-num);
  else
    return(num);
}

/* ************************************************************ */

int isalpha(char c)
{
  if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
    return(1);
  else
    return(0);
}

int isupper(char c)
{
  if(c >= 'A' && c <= 'Z')
    return(1);
  else
    return(0);
}

int islower(char c)
{
  if(c >= 'a' && c <= 'z')
    return(1);
  else
    return(0);
}

int isdigit(char c)
{
  if(c >= '0' && c <= '9')
    return(1);
  else
    return(0);
}

int isspace(char c)
{
  if(c == ' ' || c == '\t' || c == '\n')
    return(1);
  else
    return(0);
}

int toupper(char c)
{
  return((c >= 'a' && c <= 'z') ? c - 32: c);
}

int tolower(char c)
{
  return((c >= 'A' && c <= 'Z') ? c + 32: c);
}


/* ************************************************************ */

/* Find index of string t in s */

int index(char *s, char *t)
{
  int i, j, k;

  for(i = 0; s[i] != EOS; i++) {
    k = 0;
    for(j = i; t[k] != EOS && s[j] == t[k]; i++)
      j++;
    if (t[k] == EOS)
      return(i);
  }
  return(-1);
}

/* ************************************************************ */

char *itoa(int n, char *s)
{
  int i, sign;

  if((sign = n) < 0)
    n = -n;
  i = 0;
  do {
    s[i++] = n % 10 + '0';
  } while((n = n/10) > 0);
  if(sign < 0) s[i++] = '-';
  s[i] = EOS;
  reverse(s);
  return(s);
}

/* ************************************************************ */

/* Print a number in any radix */

#define DIGARR "0123456789ABCDEF"

void printn(int number, int radix)
{
  int i;
  char *digitreps;

  if(number < 0 && radix == 10) {
    putchar('-');
    number = -number;
  }
  if((i = (unsigned)number / (unsigned)radix) != 0)
    printn(i, radix);
  digitreps = DIGARR;
  putchar(digitreps[(unsigned)number % (unsigned)radix]);
}

/* ************************************************************ */

/* Reverse a character string */

char *reverse(char *s)
{
  int i, j;
  char c;

  i = 0;
  j = strlen(s) - 1;
  while(i < j) {
    c = s[i];
    s[i] = s[j];
    s[j] = c;
    i++;
    j--;
  }
  return(s);
}

/* ************************************************************ */

/*
 * Concatenate s2 on the end of s1. s1 must be large enough.
 * Return s1.
 */

char *strcat(char *s1, char *s2)
{
  char *os1;

  os1 = s1;
  while(*s1++)
    ;
  *--s1;
  while(*s1++ = *s2++)
    ;
  return(os1);
}

/* ************************************************************ */

/*
 * Compare strings:
 *  s1>s2: >0
 *  s1==s2: 0
 *  s1<s2: <0
 */

int strcmp(char *s1, char *s2)
{
  while(*s1 == *s2++)
    if(*s1++=='\0')
      return(0);
  return(*s1 - *--s2);
}

/* ************************************************************ */

/*
 * Copy string s2 to s1. s1 must be large enough.
 * Return s1.
 */

char *strcpy(char *s1, char *s2)
{
  char *os1;

  os1 = s1;
  while(*s1++ = *s2++)
    ;
  return(os1);
}

/* ************************************************************ */

/* Return length of string */

int strlen(char *s)
{
  int i;

  i = 0;
  while(*s++)
    i++;
  return(i);
}

/* ************************************************************ */

/*
 * Concatenate s2 on the end of s1. s1 must be large enough.
 * At most n characters are moved.
 * Return s1.
 */

char *strncat(char *s1, char *s2, int n)
{
  char *os1;

  os1 = s1;
  while(*s1++)
    ;
  --s1;
  while(*s1++ = *s2++)
    if(--n < 0) {
      *--s1 = '\0';
      break;
    }
  return(os1);
}

/* ************************************************************ */

/*
 * Compare strings (at most n bytes):
 *  s1>s2: >0
 *  s1==s2: 0
 *  s1<s2: <0
 */

int strncmp(char *s1, char *s2, int n)
{
  while(--n >= 0 && *s1 == *s2++)
    if (*s1++ == '\0')
      return(0);
  return(n < 0 ? 0 : *s1 - *--s2);
}

/* ************************************************************ */

/*
 * Copy s2 to s1, truncating or null-padding to always copy n bytes.
 * Return s1.
 */

char *strncpy(char *s1, char *s2, int n)
{
  int i;
  char *os1;

  os1 = s1;
  for(i = 0; i < n; i++)
    if((*s1++ = *s2++) == '\0') {
      while(++i < n)
	*s1++ = '\0';
      return(os1);
    }
  return(os1);
}

/* ************************************************************ */

void puts(char *str)
{
  while (*str)
    putchar(*str++);
  putchar(EOL);
}

void print(char *str)
{
  while (*str)
    putchar(*str++);
}

/* ************************************************************ */

void printf(char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  for (; *fmt; fmt++)
    if (*fmt == '%')
      switch (*++fmt) {
      case 'c':
	/* char */
	putchar(va_arg(ap, int));
	break;
      case 'd':
	/* decimal number */
	printn(va_arg(ap, int), 10);
	break;
      case 'o':
	/* octal number */
	printn(va_arg(ap, int), 8);
	break;
      case 'p':
	/* pointer */
	printn((int)va_arg(ap, void *), 16);
	break;
      case 's':
	/* string */
	print(va_arg(ap, char *));
	break;
      case 'x':
	/* hexadecimal number */
	printn(va_arg(ap, int), 16);
	break;
      default:
	putchar(*fmt);
	break;
      }
    else
      putchar(*fmt);
  va_end(ap);
}

/* ************************************************************ */

int scan_skip(char *s, int i)
{
oncemore:
  while(isspace(s[i]))
    i++;
  if(s[i] == EOS) {
    gets(s);
    i = 0;
    goto oncemore;
  }
  return i;
}

int scan_int(char *s, int i, int base, int *nb)
{
  int n = 0, sign = 1, j;

  switch(s[i])
    {
    case '-':
      sign = -1;
      /* and fall through */
    case '+':
      ++i;
      break;
    }
  while(1) {
    if(isdigit(s[i]))
      j = s[i] - '0';
    else if(isalpha(s[i]))
      j = toupper(s[i]) - 'A' + 10;
    else
      break;
    if(j >= base)
      break;
    n = base * n + j;
    i++;
  }
  *nb = sign * n;
  return(i);
}

int scanf(char *fmt, ...)
{
  va_list ap;
  char s[64];
  int i = 0, nb = 0;

  gets(s);
  va_start(ap, fmt);
  for (; *fmt; fmt++) {
    if(isspace(*fmt))
      continue;
    i = scan_skip(s, i);
    if (*fmt == '%') {
      switch (*++fmt) {
      case 'c':
	/* char */
	*va_arg(ap, char *) = s[i++];
	break;
      case 'd':
	/* decimal number */
	i = scan_int(s, i, 10, va_arg(ap, int *));
	break;
      case 'o':
	/* octal number */
	i = scan_int(s, i, 8, va_arg(ap, int *));
	break;
      case 'p':
	/* pointer */
	i = scan_int(s, i, 16, (int *)va_arg(ap, void **));
	break;
      case 's':
	/* string */
	{
	  int j = 0;
	  char *d = va_arg(ap, char *);
	  while((d[j++] = s[i++]) != EOS)
	    ;
	}
	break;
      case 'x':
	/* hexadecimal number */
	i = scan_int(s, i, 16, va_arg(ap, int *));
	break;
      default:
	if(s[i] != *fmt)
	  return EOF;
	break;
      }
      nb++;
    } else
      if(s[i] != *fmt)
	return EOF;
  }
  va_end(ap);

  return nb;
}
