/* Simple tokeniser V1.13 3/06/07
   See stok.h for docs
   Copyright 2008 Jeffrey Lee
   This file is part of WOUM.
   WOUM 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 3 of the License, or
   (at your option) any later version.
   WOUM 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 WOUM.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _STOK_C
#define _STOK_C

#include "stok.h"

int stok_flags;
char stok_string[STOK_STRLEN_MAX];
int stok_strlen;
int stok_int;
float stok_float;
f1616 stok_f1616;
char stok_esc = 0;

char *stok_skipws(char *s)
{
	char c;
	c = *s;
	while ((c) && ((c < 33) || (c == 127)) && (c != 13) && (c != 10))
		c = *(++s);
	return s;
}

char *stok_tok(char *s)
{
	char c;
	float div;
	int hexmode;
	c = *s;
	/* Skip white space */
	stok_flags = 0; /* In case we quit straight away */
	while ((c) && ((c < 33) || (c == 127)) && (c != 13) && (c != 10))
		c = *(++s);
	if (c == 0)
		return s;
	if (c == 13)
	{
		stok_flags = STOK_NEWLINE;
		if (s[1] == 10)
			return s+2;
		return s+1;
	}
	if (c == 10)
	{
		stok_flags = STOK_NEWLINE;
		if (s[1] == 13)
			return s+2;
		return s+1;
	}
	stok_strlen = 0;
	if (c == '"')
	{
		stok_flags = STOK_STRING+STOK_QUOTED;
		s++;
		while (*s != '"')
		{
			if (stok_strlen == STOK_STRLEN_MAX)
				return 0; /* Too long! */
			if ((*s == stok_esc) && (s[1]) && (stok_esc))
				s++;
			stok_string[stok_strlen++] = *s;
			s++;
		}
		if (stok_strlen < STOK_STRLEN_MAX)
			stok_string[stok_strlen] = 0;
		return s+1;
	}
	/* Else parse normally */
	stok_flags = STOK_STRING + STOK_INT + STOK_FLOAT + STOK_F1616; /* remove as needed */
	stok_int = 0;
	stok_float = 0;
	stok_f1616 = 0;
	div = 1;
	c = 1; /* On the whole side */
	hexmode = 0; /* Not reading hex number */
	while ((*s > 32) && (*s != 127))
	{
		if (stok_strlen == STOK_STRLEN_MAX)
			return 0; /* Too long! */
		if ((*s == stok_esc) && (s[1]) && (stok_esc)) /* Skip esc */
			s++;
		stok_string[stok_strlen++] = *s;
		if (stok_flags & STOK_INT)
		{
			if ((*s >= '0') && (*s <= '9')) {
				if (hexmode)
					stok_int = stok_int*16 + *s-'0';
				else
					stok_int = stok_int*10 + *s-'0';
			} else if ((*s == 'x') && (hexmode == 0) && (stok_strlen == 2) && (stok_string[0] == '0'))
				hexmode = 1;
			else if ((hexmode) && (*s >= 'a') && (*s <= 'f'))
				stok_int = stok_int*16 + 10 + *s-'a';
			else if ((hexmode) && (*s >= 'A') && (*s <= 'F'))
				stok_int = stok_int*16 + 10 + *s-'A';
			else if ((*s != '-') || (stok_strlen != 1))
				stok_flags -= STOK_INT;
		}
		if (stok_flags & STOK_FLOAT)
		{
			if (c)
			{
				if ((*s >= '0') && (*s <= '9'))
					stok_float = stok_float*10 + *s-'0';
				else if (*s == '.')
					c = 0; /* Zero! */
				else if ((*s != '-') || (stok_strlen != 1))
					stok_flags -= STOK_FLOAT + STOK_F1616;
			}
			else
			{
				if ((*s >= '0') && (*s <= '9'))
				{
					div *= 10;
					stok_float = stok_float*10 + *s-'0';
				}
				else
					stok_float -= STOK_FLOAT + STOK_F1616;
			}
		}
		s++;
	}
	if (stok_flags & STOK_FLOAT)
	{
		if (c == 0)
			stok_float /= div;
		if (stok_string[0] == '-')
			stok_float = -stok_float;
		stok_f1616 = f1616_FromFloat(stok_float);
	}
	if ((stok_flags & STOK_INT) && (stok_string[0] == '-'))
		stok_int = -stok_int;
	if (stok_strlen < STOK_STRLEN_MAX)
		stok_string[stok_strlen] = 0; /* terminate it */
	return s;
}

#endif
