text: #include <stdarg.h>
  #include <sys/types.h>
  
  #define NULL (void*)0
  
  
  /**
   * simple_strtoul - convert a string to an unsigned long
   * @cp: The start of the string
   * @endp: A pointer to the end of the parsed string will be placed here
   * @base: The number base to use
   */
  unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
  {
  	unsigned long result = 0,value;
  
  	if (!base) {
  		base = 10;
  		if (*cp == '0') {
  			base = 8;
  			cp++;
  			if ((*cp == 'x') && isxdigit(cp[1])) {
  				cp++;
  				base = 16;
  			}
  		}
  	}
  	while (isxdigit(*cp) &&
  	       (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
  		result = result*base + value;
  		cp++;
  	}
  	if (endp)
  		*endp = (char *)cp;
  	return result;
  }
  
  /**
   * simple_strtol - convert a string to a signed long
   * @cp: The start of the string
   * @endp: A pointer to the end of the parsed string will be placed here
   * @base: The number base to use
   */
  long simple_strtol(const char *cp,char **endp,unsigned int base)
  {
  	if(*cp=='-')
  		return -simple_strtoul(cp+1,endp,base);
  	return simple_strtoul(cp,endp,base);
  }
  
  /**
   * simple_strtoull - convert a string to an unsigned long long
   * @cp: The start of the string
   * @endp: A pointer to the end of the parsed string will be placed here
   * @base: The number base to use
   */
  unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
  {
  	unsigned long long result = 0,value;
  
  	if (!base) {
  		base = 10;
  		if (*cp == '0') {
  			base = 8;
  			cp++;
  			if ((*cp == 'x') && isxdigit(cp[1])) {
  				cp++;
  				base = 16;
  			}
  		}
  	}
  	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
  	    ? toupper(*cp) : *cp)-'A'+10) < base) {
  		result = result*base + value;
  		cp++;
  	}
  	if (endp)
  		*endp = (char *)cp;
  	return result;
  }
  
  /**
   * simple_strtoll - convert a string to a signed long long
   * @cp: The start of the string
   * @endp: A pointer to the end of the parsed string will be placed here
   * @base: The number base to use
   */
  long long simple_strtoll(const char *cp,char **endp,unsigned int base)
  {
  	if(*cp=='-')
  		return -simple_strtoull(cp+1,endp,base);
  	return simple_strtoull(cp,endp,base);
  }
  
  static int skip_atoi(const char **s)
  {
  	int i=0;
  
  	while (isdigit(**s))
  		i = i*10 + *((*s)++) - '0';
  	return i;
  }
  
  /**
   * vsscanf - Unformat a buffer into a list of arguments
   * @buf:	input buffer
   * @fmt:	format of buffer
   * @args:	arguments
   */
  int vsscanf(const char * buf, const char * fmt, va_list args)
  {
  	const char *str = buf;
  	char *next;
  	char digit;
  	int num = 0;
  	int qualifier;
  	int base;
  	int field_width;
  	int is_sign = 0;
  
  	while(*fmt && *str) {
  		/* skip any white space in format */
  		/* white space in format matchs any amount of
  		 * white space, including none, in the input.
  		 */
  		if (isspace(*fmt)) {
  			while (isspace(*fmt))
  				++fmt;
  			while (isspace(*str))
  				++str;
  		}
  
  		/* anything that is not a conversion must match exactly */
  		if (*fmt != '%' && *fmt) {
  			if (*fmt++ != *str++)
  				break;
  			continue;
  		}
  
  		if (!*fmt)
  			break;
  		++fmt;
  
  		/* skip this conversion.
  		 * advance both strings to next white space
  		 */
  		if (*fmt == '*') {
  			while (!isspace(*fmt) && *fmt)
  				fmt++;
  			while (!isspace(*str) && *str)
  				str++;
  			continue;
  		}
  
  		/* get field width */
  		field_width = -1;
  		if (isdigit(*fmt))
  			field_width = skip_atoi(&fmt);
  
  		/* get conversion qualifier */
  		qualifier = -1;
  		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
  		    *fmt == 'Z' || *fmt == 'z') {
  			qualifier = *fmt;
  			fmt++;
  		}
  		base = 10;
  		is_sign = 0;
  
  		if (!*fmt || !*str)
  			break;
  
  		switch(*fmt++) {
  		case 'c':
  		{
  			char *s = (char *) va_arg(args,char*);
  			if (field_width == -1)
  				field_width = 1;
  			do {
  				*s++ = *str++;
  			} while (--field_width > 0 && *str);
  			num++;
  		}
  		continue;
  		case 's':
  		{
  			char *s = (char *) va_arg(args, char *);
  			if(field_width == -1)
  				field_width = sizeof(int);
  			/* first, skip leading white space in buffer */
  			while (isspace(*str))
  				str++;
  
  			/* now copy until next white space */
  			while (*str && !isspace(*str) && field_width--) {
  				*s++ = *str++;
  			}
  			*s = '\0';
  			num++;
  		}
  		continue;
  		case 'n':
  			/* return number of characters read so far */
  		{
  			int *i = (int *)va_arg(args,int*);
  			*i = str - buf;
  		}
  		continue;
  		case 'o':
  			base = 8;
  			break;
  		case 'x':
  		case 'X':
  			base = 16;
  			break;
  		case 'i':
                          base = 0;
  		case 'd':
  			is_sign = 1;
  		case 'u':
  			break;
  		case '%':
  			/* looking for '%' in str */
  			if (*str++ != '%')
  				return num;
  			continue;
  		default:
  			/* invalid format; stop here */
  			return num;
  		}
  
  		/* have some sort of integer conversion.
  		 * first, skip white space in buffer.
  		 */
  		while (isspace(*str))
  			str++;
  
  		digit = *str;
  		if (is_sign && digit == '-')
  			digit = *(str + 1);
  
  		if (!digit
                      || (base == 16 && !isxdigit(digit))
                      || (base == 10 && !isdigit(digit))
                      || (base == 8 && (!isdigit(digit) || digit > '7'))
                      || (base == 0 && !isdigit(digit)))
  				break;
  
  		switch(qualifier) {
  		case 'h':
  			if (is_sign) {
  				short *s = (short *) va_arg(args,short *);
  				*s = (short) simple_strtol(str,&next,base);
  			} else {
  				unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
  				*s = (unsigned short) simple_strtoul(str, &next, base);
  			}
  			break;
  		case 'l':
  			if (is_sign) {
  				long *l = (long *) va_arg(args,long *);
  				*l = simple_strtol(str,&next,base);
  			} else {
  				unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
  				*l = simple_strtoul(str,&next,base);
  			}
  			break;
  		case 'L':
  			if (is_sign) {
  				long long *l = (long long*) va_arg(args,long long *);
  				*l = simple_strtoll(str,&next,base);
  			} else {
  				unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
  				*l = simple_strtoull(str,&next,base);
  			}
  			break;
  		case 'Z':
  		case 'z':
  		{
  			size_t *s = (size_t*) va_arg(args,size_t*);
  			*s = (size_t) simple_strtoul(str,&next,base);
  		}
  		break;
  		default:
  			if (is_sign) {
  				int *i = (int *) va_arg(args, int*);
  				*i = (int) simple_strtol(str,&next,base);
  			} else {
  				unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
  				*i = (unsigned int) simple_strtoul(str,&next,base);
  			}
  			break;
  		}
  		num++;
  
  		if (!next)
  			break;
  		str = next;
  	}
  	return num;
  }
  
  /**
   * sscanf - Unformat a buffer into a list of arguments
   * @buf:	input buffer
   * @fmt:	formatting of buffer
   * @...:	resulting arguments
   */
  int sscanf(const char * buf, const char * fmt, ...)
  {
  	va_list args;
  	int i;
  
  	va_start(args,fmt);
  	i = vsscanf(buf,fmt,args);
  	va_end(args);
  	return i;
  }