#include <limits.h>
#include "parse.h"
#include "util.h"

Ttype parse_blank(uchar ** s)
{
	uchar *p;

	p = *s;
	if (*p == '\0')
		return TNUL;
	while (*p == ' ' || *p == '\t')
		p++;
	if (p == *s)
		return TERROR;
	*s = p;
	return TBLANK;
}

Ttype parse_number(uchar ** s, void *t)
{
	uchar *p;
	ulong l;

	p = *s;
	if (parse_blank(&p) == TNUL)
		return TNUL;
	l = 0;
	while (*p == '0')
		p++;
	while (*p >= '0' && *p <= '9') {
		if (l > ULONG_MAX - (10 * l + *p - '0'))
			return TERROR;
		l = 10 * l + *p - '0';
		p++;
	}
	if (p == *s)
		return TERROR;
	*s = p;
	((Tnumber *) t)->value = l;
	return TNUMBER;
}

Ttype parse_date(uchar ** s, void *t)
{
	Tnumber n;
	uchar *p;
	uint y;
	ushort m;
	ushort d;

	p = *s;
	y = 0;
	if (parse_number(&p, &n) != TNUMBER)
		return TERROR;
	y = (uint) n.value;
	if (y < 1900 || y > 2900)
		return TERROR;
	*s = p;
	if (*p != '/')
		return TERROR;
	p++;
	m = 0;
	if (parse_number(&p, &n) != TNUMBER)
		return TERROR;
	m = (ushort) n.value;
	if (m < 1 && m > 12)
		return TERROR;
	*s = p;
	if (*p != '/')
		return TERROR;
	p++;
	d = 0;
	*s = p;
	if (parse_number(&p, &n) != TNUMBER)
		return TERROR;
	d = (ushort) n.value;
	if (d < 1 || d > month_days(y, m))
		return TERROR;
	*s = p;
	((Tdate *) t)->year = y;
	((Tdate *) t)->month = m;
	((Tdate *) t)->day = d;
	return TDATE;
}
