#import "atod3.h"
#import "atoi3b.h"
#include "support.h"	// fsjisInRun,型宣言
#include "code2code.h"	// getSjisOrUtf8()

// 2/8/10/16進整数または浮動小数点文字列を浮動小数点数値に直す
// 符号の+/-はあらかじめ処理されており、ここには数値のみでくることを前提としている
//  1234.e56:10進数 , &hABCD/0xEF:16進数 , &b0101:2進数 , &o137:8進数
//  '?':?1文字のASCコード
// end0 : 変換できなかった最初の文字、または変換できた最終文字+1の位置を返す ; NULLなら返さない
// ferr : 数字として正しいかどうか ; YES=エラー ; NULLなら返さない
double atod3(UByte *str,UByte *(*end0),BOOL *ferr)
{
	printFunc();
	errno=0; // これはstrtod用

	UByte *end;
	double d=strtod((const char *)str,(char **)&end);	// +/-/10進/16進数(0x～)/浮動小数点はこれで処理できる
														// 文字列先頭のスペースも削除される
	nslog(@"d=%f,errno=%d,end=$%02x(%c)",d,errno,*end,*end);
	if (errno==ERANGE) { //
		nslog(@"オーバーフロー／アンダーフロー(strtod):error=%d",errno);
//		if (ferr!=NULL) *ferr=YES;
		// でもそれはそれで0としてそのまま返してしまう
		if (ferr!=NULL) *ferr=NO;
		return (d);
	}
	// 他のエラーが発生しても全て無視する（なぜか発生しているので）
	// 文字列に異常があった場合もerrno=0のままである（オーバーフロー／アンダーフロー以外チェックされない）
	
	// 後ろの文字がおかしい場合は、後ろの処理に任せれば良い
	// ここで判定すべきは&h/&o/&b/'?'のみ
		
	if (end==str) { // 先頭のときのみ
		int base;
		UByte c=*str++;
		nslog(@"atod3:先頭で変換できなかった:%c",c);
		switch (c) {
			default:
				// 数字として無効
				errno=ERANGE; // エラーにしてしまう
				if (ferr!=NULL) *ferr=YES;
				nslog(@"浮動小数点文字列異常(1)");
				return (0);
			
			case '&': // &H/O/Bかもしれない
				nslog(@"&...:%c",*str);
				switch (*str++) {
					default:
						// 数字として無効
						errno=ERANGE; // エラーにしてしまう
						if (ferr!=NULL) *ferr=YES;
						nslog(@"浮動小数点文字列異常(2)");
						return (0);
					//
					case 'h':
					case 'H':
						base=16;
						nslog(@"&h");
						break;
					
					case 'o':
					case 'O':
						base=8;
						nslog(@"&o");
						break;
					
					case 'b':
					case 'B':
						base=2;
						nslog(@"&b");
						break;
				}
				d=(double)(atoi3b(str,base,&end));
				break;
			
			case '\'': // \'1文字
				nslog(@"1文字:%c/chr$(%d)",*str,*str);
				d=(double)getSjisOrUtf8(&str,fsjisInRun);
				if (*str=='\'') str++; // 閉じ\'があるときはそれも飛ばす
				end=str;
				break;
		}
	} else {
		nslog(@"通常文字列だった");
	}
	if (ferr!=NULL) *ferr=NO;
	errno=0;
	if (*end=='#') {
		// floatの印がある場合は飛ばす
		nslog(@"#を飛ばす");
		end++;
	}
	// errno!=0の時はアンダーフロー/オーバーフロー（外部で判定すること）
	if (end0!=NULL) *end0=end;
	nslog(@"d=%f:次=%c/errno=%d",d,*end,errno);
	return (d);
}
