/*
 * string code program copyright (C) 2009 - 2013 H.Niwa
 */

/*
 * This program 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 2, or (at your option)
 * any later version.

 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include <string>
#include <complex>

#include "syserr.h"

#include "pllex.h"
#include "bin_node.h"
#include "code.h"


std::string code = "UTF8";
//std::string code = "EUC";
//std::string code = "SJIS";

extern int GetChar();
extern void UnGetChar(int c);

extern int CharUTF8Len(unsigned char c);
extern int CharEUCLen(unsigned char c);
extern int CharSJISLen(unsigned char c);

extern Node* UTF8Char(char* str);
extern Node* EUCChar(char* str);
extern Node* SJISChar(char* str);

extern int UTF8Len(char* str);
extern int EUCLen(char* str);
extern int SJISLen(char* str);

extern int UTF8toupper(char* input, char* output);
extern int UTF8tolower(char* input, char* output);
extern int EUCtoupper(char* input, char* output);
extern int EUCtolower(char* input, char* output);
extern int SJIStoupper(char* input, char* output);
extern int SJIStolower(char* input, char* output);

char EUCspace[]  = {0xa1, 0xa1, 0};
char SJISspace[] = {0x81, 0x40, 0};
char UTF8space[] = {0xe3, 0x80, 0x80, 0};


char* CharSpace()
{
	if (code == "EUC") {
		return EUCspace;
	} else if (code == "SJIS") {
		return SJISspace;
	} else {
		return UTF8space;
	}
}

int CharLen(unsigned char c)
{
	if (code == "EUC") {
		return CharEUCLen(c);
	} else if (code == "SJIS") {
		return CharSJISLen(c);
	} else {
		return CharUTF8Len(c);
	}

}

Node* CodeChar(char* str)
{
	if (code == "EUC") {
		return EUCChar(str);
	} else if (code == "SJIS") {
		return SJISChar(str);
	} else {
		return UTF8Char(str);
	}
}

int CodeLen(char* str)
{
	if (code == "EUC") {
		return EUCLen(str);
	} else if (code == "SJIS") {
		return SJISLen(str);
	} else {
		return UTF8Len(str);
	}

}

int pllexSpace(int c)
{
	int c1, c2;
	int savec = c;
	extern std::string code;
	
	if (isspace(c)) {
		Char = savec;
		return 1;
	}

	if (code == "EUC") {
		if (c == 0xa1){	// EUC space
			c1 = GetChar();
			if (c1 == 0xa1) {
				return 1;	
			} else {
				UnGetChar(c1);
				Char = savec;
				return 0;
			}
		}			
	} else if (code == "SJIS") {
		if (c == 0x81){	// EUC space
			c1 = GetChar();
			if (c1 == 0x40) {
				return 1;	
			} else {
				UnGetChar(c1);
				Char = savec;
				return 0;
			}
		}			
	} else {	// UTF8
		if (c == 0xe3){	// UTF8 space
			c1 = GetChar();
			if (c1 == 0x80) {
				c2 = GetChar();
				if (c2 == 0x80) {
					return 1;
				} else {
					UnGetChar(c2);
					UnGetChar(c1);
					Char = savec;
					return 0;
				}
			} else {
				UnGetChar(c1);
				Char = savec;
				return 0;
			}
		}			
	}
	Char = savec;
	return 0;
}

int pllexCkSpace(int c)
{
	int c1, c2;
	int savec = c;
	extern std::string code;
	
	if (isspace(c)) {
		Char = savec;
		return 1;
	}

	if (code == "EUC") {
		if (c == 0xa1){	// EUC space
			c1 = GetChar();
			UnGetChar(c1);
			if (c1 == 0xa1) {
				Char = savec;
				return 1;	
			} else {
				Char = savec;
				return 0;
			}
		}			
	} else if (code == "SJIS") {
		if (c == 0x81){	// EUC space
			c1 = GetChar();
			UnGetChar(c1);
			if (c1 == 0x40) {
				Char = savec;
				return 1;	
			} else {
				Char = savec;
				return 0;
			}
		}			
	} else {	// UTF8
		if (c == 0xe3){	// UTF8 space
			c1 = GetChar();
			if (c1 == 0x80) {
				c2 = GetChar();
				UnGetChar(c2);
				UnGetChar(c1);
				if (c2 == 0x80) {
					Char = savec;
					return 1;
				} else {
					Char = savec;
					return 0;
				}
			} else {
				UnGetChar(c1);
				Char = savec;
				return 0;
			}
		}			
	}
	Char = savec;
	return 0;
}

void CodeToupper(char* input, char* output)
{
	if (code == "EUC") {
		EUCtoupper(input, output);
	} else if (code == "SJIS") {
		SJIStoupper(input, output);
	} else {	// UTF8
		UTF8toupper(input, output);
	}
}

void CodeTolower(char* input, char* output)
{
	if (code == "EUC") {
		EUCtolower(input, output);
	} else if (code == "SJIS") {
		SJIStolower(input, output);
	} else {	// UTF8
		UTF8tolower(input, output);
	}
}


