/*****
 NAME
 	flang.m - source code for functions for language
 VERSION
 	$Id$
 CHANGELOG
 	$Log$
 NOTE
 	ths functions defined in this file are tested in 
	"clangsystem-test.m"
 */

#include <coconut/flang.h>
#include <coconut/clangsystem.h>
#include <coconut/cstring.h>
#include <coconut/dconststr.h>
#include <stdlib.h>
#include <errno.h>

static utf8_char * lex_input_name = NULL ;

#define	LANGSYSTEM	[CLangSystem langSystem]

void syntaxError(int lineno, const char * form, ...)
{
	va_list		args ;
	utf8_char *	name ;

	name = lex_input_name ?  lex_input_name : (utf8_char *) STDIN_STR ;
	fprintf(stderr, "%s:%d: ", name, lineno) ;
	va_start(args, form) ;
	  vfprintf(stderr, form, args) ;
	va_end(args) ;
	fputc('\n', stderr) ;
}

void setLexInputName(const utf8_char * text)
{
	[CString free: lex_input_name] ;
	lex_input_name = [CString duplicate: text] ;
}

token_ptr doubleTextToToken(int lineno, const char * text)
{
	double		dvalue ;
	char *		endptr ;

	dvalue = strtod(text, &endptr) ;
	if(*endptr != '\0' || errno == ERANGE){
		syntaxError(lineno, "\"%s\" is illegal for double value",
		  text) ;
		return (token_ptr) [LANGSYSTEM errorToken] ;
	} else {
		return (token_ptr) [LANGSYSTEM doubleToken: dvalue] ;
	}
}

token_ptr intTextToToken(int lineno, const char * text, int base)
{
	long int	lvalue ;
	char *		endptr ;

	lvalue = strtol(text, &endptr, base) ;
	if(*endptr != '\0'){
		syntaxError(lineno, "\"%s\" is illegal for integer value",
		  text) ;
		return (token_ptr) [LANGSYSTEM errorToken] ;
	} else if(errno == ERANGE || lvalue < INT_MIN || INT_MAX < lvalue){
		if(base == 10)
			return doubleTextToToken(lineno, text) ;
		else {
			syntaxError(lineno, "\"%s\" is illegal for integer"
			  " value", text) ;
			return (token_ptr) [LANGSYSTEM errorToken] ;
		}
	} else {
		return (token_ptr) [LANGSYSTEM intToken: lvalue] ;
	}
}

token_ptr constStrToToken(const utf8_char * text)
{
	return (token_ptr) [LANGSYSTEM strToken: text] ;
}

token_ptr identStrToToken(const utf8_char * text)
{
	return (token_ptr) [LANGSYSTEM identToken: text] ;
}

int rwordToToken(token_ptr * ptr, const char * text)
{
	id <PToken>	token ;
	token = [LANGSYSTEM searchReservedWord: text] ;
	if(token){
		*ptr = token ;
		return [token rwordId] ;
	} else {
		*ptr = nil ;
		return -1 ;
	}
}

static id <PString>	s_lex_string = nil ;

void startLexString(void)
{
	[s_lex_string release] ;
	s_lex_string = [[CString alloc] initStringWithPage: 128] ;
	g_assert(s_lex_string != nil) ;
}

const utf8_char * finishLexString(void)
{
	return [s_lex_string ptr] ;
}

void addLexString(utf8_char c)
{
	[s_lex_string appendChar: c] ;
}

