/*
	symbol.h
	整数型変数/文字列型変数の取り扱い
*/

#include "stdafx.h"
#include "symbol.h"
#include "token.h"
#include "addctrl.h"
#include "splash.h"
#include "function.h"

typedef struct {  // 整数型変数
	char *name;
	unsigned int integer;
} VARIABLE, *PVARIABLE;

typedef struct {  // 文字列型変数
	char *name;
	char *text;
} VARIABLE_D, *PVARIABLE_D;

unsigned int nsyms = 0;			// 整数型変数の数
unsigned int nsyms_d = 0;		// 文字列型変数の数
unsigned int nsyms_a = 0;		// 整数型配列の数
unsigned int nsyms_d_a = 0;		// 文字列型配列の数

static unsigned char flag_must_def_value;	// 配列でない変数は利用の前に代入が必要

PVARIABLE     variables = NULL;			// 整数型変数
PVARIABLE_D   variables_d = NULL;		// 文字列型変数
PVARIABLE_A   variables_a = NULL;		// 整数型配列
PVARIABLE_D_A variables_d_a = NULL;		// 文字列型配列

typedef struct {		// 初期代入変数(いわゆる定数)
	const char name[32];
	unsigned int cvalue;
} CVALUES, *PCVALUES;

CVALUES cvalues[] = { // 初期代入変数の一覧。アルファベット順にソートされている
	 { "cb_dword",							CB_DWORD },
	 { "check_dword",						CHECK_DWORD },
	 { "check_sz01",						CHECK_SZ01 },
	 { "check_sztf",						CHECK_SZTF },
	 { "check_szyn",						CHECK_SZYN },
	 { "ctrl_needadmin",					CTRL_NEEDADMIN },
	 { "ctrl_noeffect",						CTRL_NOEFFECT },
	 { "ctrl_normal",						CTRL_NORMAL },
	 { "ctrl_notify",						CTRL_NOTIFY },
	 { "ctrl_reboot",						CTRL_REBOOT },
	 { "ctrl_refresh",						CTRL_REFRESH },
	 { "delete_default",					DELETE_DEFAULT },
//	 { "dummy",								0 },	// 初期代入変数の挙動変更により外だし[2006/10/23]
	 { "edit_binary",						EDIT_BINARY },
	 { "edit_button",						EDIT_BUTTON },
	 { "edit_default",						EDIT_DEFAULT },
	 { "edit_filename",						EDIT_FILENAME },
	 { "edit_folder",						EDIT_FOLDER },
	 { "edit_password",						EDIT_PASSWORD },
	 { "edit_readonly",						EDIT_READONLY },
	 { "edit_sz",							EDIT_SZ },
	 { "error",								ERRORVALUE },
	 { "errorvalue",						ERRORVALUE },
	 { "false",								FALSE },
	 { "iever",								0 },	// IEVersion (後から代入)
	 { "isnt",								0 },	// isNT (後から代入)
	 { "lowvalue",							MININTEGER },
	 { "lv_delete_novalue",					LV_DELETE_NOVALUE },
	 { "lv_dword",							LV_DWORD },
	 { "lv_middle",							LV_MIDDLE },
	 { "lv_multiselect",					LV_MULTISELECT },
	 { "lv_small",							LV_SMALL },
	 { "lv_sortheader",						LV_SORTHEADER },
	 { "maxinteger",						MAXINTEGER },
	 { "maybe_expand",						MAYBE_EXPAND },
	 { "mininteger",						MININTEGER },
	 { "nil",								0 },
	 { "no",								0 },
	 { "nothing",							0 },
	 { "nul",								0 },
	 { "null",								0 },
	 { "reg_binary",						REG_BINARY },
	 { "reg_dword",							REG_DWORD },
	 { "reg_dword_big_endian",				REG_DWORD_BIG_ENDIAN },
	 { "reg_dword_little_endian",			REG_DWORD_LITTLE_ENDIAN },
	 { "reg_expand_sz",						REG_EXPAND_SZ },
	 { "reg_full_resource_descriptor",		REG_FULL_RESOURCE_DESCRIPTOR },
	 { "reg_link",							REG_LINK },
	 { "reg_multi_sz",						REG_MULTI_SZ },
	 { "reg_none",							0 },
	 { "reg_qword",							REG_QWORD },
	 { "reg_qword_little_endian",			REG_QWORD_LITTLE_ENDIAN },
	 { "reg_resource_list",					REG_RESOURCE_LIST },
	 { "reg_resource_requirements_list",	REG_RESOURCE_REQUIREMENTS_LIST },
	 { "reg_sz",							REG_SZ },
	 { "sz_expand",							SZ_EXPAND },
	 { "true",								TRUE },
	 { "winver",							0 },	// WinVer (後から代入)
	 { "yes",								1 },
	 { "zero",								0 }
};
/*
初期代入変数について
--------------------
初期代入変数は、定数整数を提供するための変数であり、プログラム開始時に準備されます。
変数の読み出しが行われるときは、「通常変数」→「初期代入変数」の順にサーチが行われます。
初期代入変数はアルファベット順にメモリ内に格納されており、バイナリサーチで検索されます。
変数の書き出しが行われるときは、通常変数のサーチのみが行われ、変数名が見つからなかった場合は
例えそれが初期代入変数と同じ名前であったとしても、通常変数として準備されます。
変数の読み出しは通常変数が優先されますので、この場合、初期代入変数の値は無視されるようになります。
（以前のバージョンでは、初期代入変数のエリアに書き込みが行われていたのですが、
　初期代入変数初期化にかかる時間や、設定時に初期代入変数をサーチするのにかかる時間を
　考慮し、取り外しました。結果としては動作は同じになるので）
*/


// 整数型：シンボル値の検索 (引数：小文字にした変数名、戻り値 NO_VALUE : みつからなかった)
static unsigned symlook( const char *s )
{
	unsigned int i;

	if ( s ) {
		for(i=0 ; i<nsyms ; ++i) {
			if( strcmp(variables[i].name, s) == 0 ) { // あった
				return i;	// 使用済みの変数の場合は、番号(0〜nsyms-1)を返す
			}
		}
	}

	return NO_VALUE;
}

// 文字列型：シンボル値の検索 (引数：小文字にした変数名、戻り値 NO_VALUE : みつからなかった)
static unsigned symlook_d( const char *s )
{
	unsigned int i;

	if ( s ) {
		for(i=0 ; i<nsyms_d ; ++i) {
			if( strcmp(variables_d[i].name, s) == 0 ) { // あった
				return i;	// 使用済みの変数の場合は、番号(0〜nsyms_d-1)を返す
			}
		}
	}

	return NO_VALUE;
}

// 整数型配列：シンボル値の検索 (引数：小文字にした変数名、戻り値 NO_VALUE : みつからなかった)
static unsigned symlook_a( const char *s )
{
	unsigned int i;

	if ( s ) {
		for(i=0 ; i<nsyms_a ; ++i) {
			if( strcmp(variables_a[i].name, s) == 0 ) { // あった
				return i;	// 使用済みの変数の場合は、番号(0〜nsyms_a-1)を返す
			}
		}
	}

	return NO_VALUE;
}

// 文字列型配列：シンボル値の検索 (引数：小文字にした変数名、戻り値 NO_VALUE : みつからなかった)
static unsigned symlook_d_a( const char *s )
{
	unsigned int i;

	if ( s ) {
		for(i=0 ; i<nsyms_d_a ; ++i) {
			if( strcmp(variables_d_a[i].name, s) == 0 ) { // あった
				return i;	// 使用済みの変数の場合は、番号(0〜nsyms_d_a-1)を返す
			}
		}
	}

	return NO_VALUE;
}

// 整数型：変数の内容を得る
unsigned int getVariable( const char *s )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
		int s_len = lstrlen(s);
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook( s_lc );	// すでに使用済みの変数かどうかを調べる

		if ( r == NO_VALUE ) {

			// 次に初期代入変数(いわゆる定数変数)を探る
			PCVALUES pcvalue = (PCVALUES)bsearch(s_lc, cvalues, _countof(cvalues), sizeof(CVALUES), strcmp);

			safefree(s_lc);

			if ( pcvalue ) {
				return pcvalue->cvalue;
			}

			// 変数が見つからなかった
			if ( flag_must_def_value ) { // 読み出しよりも先に設定を要求する場合
				char *mes = malloc( s_len + 200 );

				if ( mes ) {
					wsprintf( mes, "このスクリプトで利用されている変数%sは、代入されないまま読み出されています。\n(スクリプト定義部のMustDefVarが有効になっているため、この警告が出力されています)", s);
					destroy_splash_window();
					MessageBox(NULL, mes, "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
					safefree( mes );
				}
			}

			return 0;	// OK 未使用の変数の場合は空とみなし0を返す
		}
		else {
			safefree(s_lc);
			return variables[r].integer; // OK 使用済みの変数の場合はその中身を返す
		}
	}
	else {
		MessageBox( NULL, "getVariable: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return 0;
	}
}

// 整数型配列：変数の内容を得る(引数 s:変数名 i:添え字(0-) v:値が格納される, 戻り値 0:成功 1:失敗)
unsigned int getVariable_a( const char *s, unsigned int i, unsigned int *v )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook_a( s_lc );	// すでに使用済みの変数かどうかを調べる
		safefree(s_lc);

		if ( r == NO_VALUE || v == NULL) {
			return 1;		// NG 未宣言の配列 or 引数エラー
		}
		else {
			if ( i >= variables_a[r].num ) {
				return 1;	// NG 配列の要素番号の指定間違い
			}
			else {
				*v = variables_a[r].pinteger[i];
				return 0;	// OK 成功
			}
		}
	}
	else {
		MessageBox( NULL, "getVariable_a: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return 1;			// NG メモリ不足
	}
}

// 文字列型：変数の内容を得る
char *getVariable_d( const char *s )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
		int s_len = lstrlen(s);
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook_d( s_lc );	// すでに使用済みの変数かどうかを調べる
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			if ( flag_must_def_value ) {
				char *mes = malloc( s_len + 200 );

				if ( mes ) {
					wsprintf( mes, "このスクリプトで利用されている変数%sは、代入されないまま読み出されています。\n(スクリプト定義部のMustDefVarが有効になっているため、この警告が出力されています)", s);
					destroy_splash_window();
					MessageBox(NULL, mes, "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
					safefree( mes );
				}
			}
			return ""; // OK 変数が見つからなければ、空の変数であるとみなす
		}
		else {
			return variables_d[r].text; // OK 変数が見つかれば、その変数の中身を返す
		}
	}
	else {
		MessageBox( NULL, "getVariable_d: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return "";		// NG メモリ不足
	}
}

// 文字列型配列：変数の内容を得る(引数 s:変数名 i:添え字(0-) 戻り値 NULL:失敗 NULL以外:文字列)
char *getVariable_d_a( const char *s, unsigned int i )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook_d_a( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return NULL; // NG 宣言されていない配列
		}
		else {
			if ( i >= variables_d_a[r].num ) {
				return NULL; // NG 配列の要素番号の指定間違い
			}
			else {
				return variables_d_a[r].ptext[i]; // OK 成功
			}
		}
	}
	else {
		MessageBox( NULL, "getVariable_d_a: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NULL;			// NG メモリ不足
	}
}

// 整数型：変数に書き込む
unsigned int setVariable( const char *s, unsigned int new_i )
{
	unsigned r;			// 変数番号
	PVARIABLE tmp;		// 配列のメモリ拡張のためのテンポラリポインタ
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook( s_lc );

		if ( r == NO_VALUE ) {
			// 変数が存在していなければ作成
			if ( nsyms >= 0xffffffff/sizeof(VARIABLE) ) {
				safefree(s_lc);
				return 1; // 使用できる変数の数の限界
			}
			tmp = realloc(variables, (nsyms+1)*sizeof(VARIABLE));
			if ( tmp == NULL ) {
				safefree(s_lc);
				return 1; // NG 領域を確保できなかった
			}
			else {
				variables = tmp;
				variables[nsyms].name = s_lc;
				variables[nsyms].integer = new_i;
				++nsyms;
				return 0; // OK 成功
			}		
		}
		else {
			safefree(s_lc);
			variables[r].integer = new_i;
			return 0; // OK 成功
		}
	}
	else {
		MessageBox( NULL, "setVariable: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return 1;			// NG メモリ不足
	}
}

// 整数型配列：変数に書き込む
unsigned int setVariable_a( const char *s, unsigned int i, unsigned int new_i )
{
	unsigned r;			// 変数番号
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook_a( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return 1; // NG 宣言されていない配列
		}
		else {
			if ( i >= variables_a[r].num )
				return 1; // NG 配列の要素番号の指定を間違えている
			variables_a[r].pinteger[i] = new_i;
			return 0; // OK 成功
		}
	}
	else {
		MessageBox( NULL, "setVariable_a: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return 1;	// NG メモリ不足
	}
}

// 文字列型：変数に書き込む
unsigned int setVariable_d( const char *s, const char *new_text )
{
	unsigned r;			// 変数番号
	PVARIABLE_D tmp;	// 配列のメモリ拡張のためのテンポラリポインタ
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook_d( s_lc );

		if ( r == NO_VALUE ) { // 変数が存在していなければ作成
			if ( nsyms_d >= 0xffffffff/sizeof(VARIABLE_D) ) {
				safefree(s_lc);
				return 1; // 使用できる変数の数の限界
			}
			tmp = realloc(variables_d, (nsyms_d+1)*sizeof(VARIABLE_D));
			if ( tmp == NULL ) {
				safefree(s_lc);
				return 1; // NG 領域の確保に失敗
			}
			else {
				variables_d = tmp;
				variables_d[nsyms_d].name = s_lc;
				variables_d[nsyms_d].text = _strdup( new_text );

				if ( variables_d[nsyms_d].text == NULL) {
					safefree( s_lc );
					return 1; // NG 領域の確保に失敗
				}
				else {
					++nsyms_d;
					return 0; // OK 成功
				}
			}		
		}
		else {
			safefree( s_lc );
			safefree( variables_d[r].text );
			variables_d[r].text = _strdup( new_text );
			if ( variables_d[r].text ) {
				return 0; // OK 成功
			}
			else {
				return 1; // NG メモリが足りない
			}
		}
	}
	else {
		MessageBox( NULL, "setVariable_d: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return 1;	// NG メモリ不足
	}
}

// 文字列型配列：変数に書き込む
unsigned int setVariable_d_a( const char *s, unsigned int i, const char *new_text )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook_d_a( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return 1; // NG 宣言されていない配列
		}
		else {
			if ( i >= variables_d_a[r].num ) {
				return 1; // NG 配列の要素番号の指定を間違えている
			}
			safefree( variables_d_a[r].ptext[i] );
			variables_d_a[r].ptext[i] = _strdup( new_text );
			if ( variables_d_a[r].ptext[i] ) {
				return 0; // OK 成功
			}
			else {
				return 1; // NG メモリが足りない
			}
		}
	}
	else {
		MessageBox( NULL, "setVariable_d_a: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return 1;	// NG メモリ不足
	}
}

// 文字列型：変数に追加で書き込む (+=演算子対策)
unsigned int addVariable_d( const char *s, const char *add_text )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )
		r = symlook_d( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) { // 変数が存在していない場合は、空文字列への追加とみなす
			return setVariable_d( s, add_text );
		}
		else {
			char *tmp, *addcopy;

			addcopy = _strdup( add_text ); // ポインタとして variables_d[r].text == add_text ということがあり得るので
			if ( addcopy == NULL ) {
				return 1; // NG 領域の確保に失敗した
			}

			tmp = realloc( variables_d[r].text, strlen(variables_d[r].text) + strlen(add_text) + 1 );

			if ( tmp == NULL ) {
				safefree( addcopy );
				return 1; // NG 領域の確保に失敗した
			}
			else {
				variables_d[r].text = lstrcat(tmp, addcopy);
				safefree( addcopy );
				return 0; // OK 成功
			}
		}
	}
	else {
		MessageBox( NULL, "addVariable_d: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return 1;	// NG メモリ不足
	}
}

// 文字列型配列：変数に追加で書き込む (+=演算子対策)
unsigned int addVariable_d_a( const char *s, unsigned int i, const char *add_text )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )
		r = symlook_d_a( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return 1;	// NG:配列が宣言されていない
		}
		else {
			char *tmp, *addcopy;

			if ( i >= variables_d_a[r].num ) {
				return 1; // NG 配列の要素番号の指定を間違えている
			}

			addcopy = _strdup( add_text ); // ポインタとして variables_d_a[r].ptext[i] == add_text ということがあり得るので
			if ( addcopy == NULL ) {
				return 1; // NG 領域の確保に失敗した
			}

			tmp = realloc( variables_d_a[r].ptext[i], strlen(variables_d_a[r].ptext[i]) + strlen(add_text) + 1 );

			if ( tmp == NULL ) {
				safefree( addcopy );
				return 1; // NG 領域の確保に失敗した
			}
			else {
				variables_d_a[r].ptext[i] = lstrcat(tmp, addcopy);
				safefree( addcopy );
				return 0; // OK 成功
			}
		}
	}
	else {
		MessageBox( NULL, "addVariable_d_a: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return 1;	// NG メモリ不足
	}
}

// プログラム開始時に呼び出される、動的に変化する初期代入変数の設定
void first_init_constvalues( void )
{
	PCVALUES pcvalue;

	// isNTの準備（isNT : Windows が NT系かそうでないかを見分ける。NT系なら1、そうでないなら0）
	pcvalue = bsearch("isnt", cvalues, _countof(cvalues), sizeof(CVALUES), strcmp);
	if (pcvalue) {
		pcvalue->cvalue = (unsigned int)isNT;
	}
	else {
		MessageBox(NULL, "(const)isNTが見つかりません。開発元へご連絡ください。", "R-Script Initializer", MB_OK | MB_ICONEXCLAMATION);
	}

	// WinVerの準備（WinVer : Windows のバージョン番号を 整数部×100 + 小数部 で表現する）
	pcvalue = bsearch("winver", cvalues, _countof(cvalues), sizeof(CVALUES), strcmp);
	if (pcvalue) {
		pcvalue->cvalue = (unsigned int)winver;
	}
	else {
		MessageBox(NULL, "(const)WinVerが見つかりません。開発元へご連絡ください。", "R-Script Initializer", MB_OK | MB_ICONEXCLAMATION);
	}

	// IEVerの準備（IEVer : Internet Explorerのバージョン番号の整数部）
	pcvalue = bsearch("iever", cvalues, _countof(cvalues), sizeof(CVALUES), strcmp);
	if (pcvalue) {
		pcvalue->cvalue = (unsigned int)iever;
	}
	else {
		MessageBox(NULL, "(const)IEVerが見つかりません。開発元へご連絡ください。", "R-Script Initializer", MB_OK | MB_ICONEXCLAMATION);
	}
}

// すべての変数をクリア
void free_variables( void )
{
	unsigned int i;

	if( nsyms ) {
		for(i=0 ; i<nsyms ; ++i) {
			safefree( variables[i].name );
		}
		safefree( variables );
		nsyms = 0;
	}

	if( nsyms_d ) {
		for(i=0 ; i<nsyms_d ; ++i) {
			safefree( variables_d[i].text );
			safefree( variables_d[i].name );
		}
		safefree( variables_d );
		nsyms_d = 0;
	}

	if( nsyms_a ) {
		for(i=0 ; i<nsyms_a ; ++i) {
			safefree( variables_a[i].pinteger );
			safefree( variables_a[i].name );
		}
		safefree( variables_a );
		nsyms_a = 0;
	}

	if( nsyms_d_a ) {
		for(i=0 ; i<nsyms_d_a ; ++i) {
			if ( variables_d_a[i].ptext ) {
				unsigned int n;

				for(n=0 ; n<variables_d_a[i].num ; ++n ) {
					safefree( variables_d_a[i].ptext[n] );
				}
				safefree( variables_d_a[i].ptext );
			}
			safefree( variables_d_a[i].name );
		}
		safefree( variables_d_a );
		nsyms_d_a = 0;
	}

	must_def_value( 0 ); // 配列でない変数は、利用の前の代入を行う必要はない（初期化）

	// ファイルオープンモードをテキスト／シングル文字モードへ戻す
	fmode_bin = fmode_wide = 0;
}

void must_def_value( unsigned char onoff )
{
	 flag_must_def_value = onoff;
}

// 整数型配列を確保 ( 0 〜 n-1 )
unsigned int array_variables( const char *s, unsigned int n )
{
	char *s_lc;			// 小文字化した変数名

	if ( n >= 0xffffffff/sizeof(unsigned int) || nsyms_a >= 0xffffffff/sizeof(VARIABLE_A) ) {
		return 1; // NG 限界を超えた配列要素数
	}

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		if ( NO_VALUE != symlook_a( s_lc ) ) {
			safefree(s_lc);
			return 1; // NG 宣言済みの配列変数名
		}
		else if ( n == 0 ) {
			safefree(s_lc);
			return 0; // OK 要求された領域の大きさがゼロだった場合は、何もしない       
		}
		else {
			PVARIABLE_A tmp;

			tmp = (VARIABLE_A *)realloc(variables_a, (nsyms_a+1)*sizeof(VARIABLE_A));
			if ( tmp == NULL ) {
				safefree(s_lc);
				return 1; // NG 領域を確保できなかった
			}
			else {
				variables_a = tmp;
				variables_a[nsyms_a].name = s_lc;

				variables_a[nsyms_a].num = n;
				variables_a[nsyms_a].pinteger = (unsigned int *)calloc( n, sizeof(unsigned int) );
				if ( variables_a[nsyms_a].pinteger ) {
					++nsyms_a;
					return 0; // OK 成功
				}
				else {
					safefree(s_lc);
					return 1; // NG 領域を確保できなかった
				}
			}
		}
	}
	else {
		MessageBox( NULL, "array_variables: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NO_VALUE;	// NG メモリ不足
	}
}

// 文字列型配列を確保 ( 0 〜 n-1 )
unsigned int array_variables_d( const char *s, unsigned int n )
{
	char *s_lc;			// 小文字化した変数名

	if ( n >= 0xffffffff/sizeof(char *) || nsyms_d_a >= 0xffffffff/sizeof(VARIABLE_D_A) ) {
		return 1; // NG 限界を超えた配列要素数
	}

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		if ( NO_VALUE != symlook_d_a( s_lc ) ) {
			safefree(s_lc);
			return 1; // NG 宣言済みの変数名
		}
		else if ( n == 0 ) {
			safefree(s_lc);
			return 0; // OK 要求された領域の大きさがゼロだった場合は、何もしない       
		}
		else {
			PVARIABLE_D_A tmp;

			tmp = (PVARIABLE_D_A)realloc(variables_d_a, (nsyms_d_a+1)*sizeof(VARIABLE_D_A));
			if ( tmp == NULL ) {
				safefree(s_lc);
				return 1; // NG 領域を確保できなかった
			}
			else {
				variables_d_a = tmp;
				variables_d_a[nsyms_d_a].num = n;
				variables_d_a[nsyms_d_a].name = s_lc;
				variables_d_a[nsyms_d_a].ptext = (char **)calloc( n, sizeof(char *) );
				if ( variables_d_a[nsyms_d_a].ptext ) {
					// 確保された配列のすべてに "" を代入しておく
					unsigned int i;

					for(i=0 ; i<n ; ++i) {
						variables_d_a[nsyms_d_a].ptext[i] = _strdup( "" );
						if ( variables_d_a[nsyms_d_a].ptext[i] == NULL ) {
							// 領域を確保できなかった
							do {
								safefree( variables_d_a[nsyms_d_a].ptext[--i] );
							} while( i > 0 );
							safefree(variables_d_a[nsyms_d_a].ptext);
							safefree(s_lc);
							return 1; // NG 領域を確保できなかった
						}
					}

					++nsyms_d_a;
					return 0; // OK 成功
				}
				else {
					safefree(s_lc);
					return 1; // NG 領域を確保できなかった
				}
			}
		}
	}
	else {
		MessageBox( NULL, "array_variables_d: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NO_VALUE;	// NG メモリ不足
	}
}

// 整数型配列をリサイズ ( 0 〜 n-1 )
unsigned int resize_variables( const char *s, unsigned int n )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	if ( n >= 0xffffffff/sizeof(unsigned int) ) {
		return 1; // NG 限界を超えた配列要素数
	}

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook_a( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return array_variables(s, n); // 未宣言の配列だった場合は、宣言する
		}
		else {
			unsigned int *tmp;
			unsigned int i;

			if ( n > variables_a[r].num ) { // 配列が多くなる場合
				tmp = (unsigned int *)realloc( variables_a[r].pinteger, n*sizeof(unsigned int) );
				if ( tmp ) {
					variables_a[r].pinteger = tmp;
					for(i=variables_a[r].num ; i<n ; ++i) {
						variables_a[r].pinteger[i] = 0;
					}
					variables_a[r].num = n;
					return 0; // OK 成功
				}
				else {
					return 1;  // NG 領域を確保できなかった
				}
			}
			else if ( n < variables_a[r].num ) { // 配列が少なくなる場合
				if ( n == 0 ) // 配列の大きさを0に使用とした場合は、大きさ1の配列が準備される
					n = 1;
				tmp = (unsigned int *)realloc( variables_a[r].pinteger, n*sizeof(unsigned int) );
				if ( tmp ) {
					variables_a[r].pinteger = tmp;
					variables_a[r].num = n;
					return 0; // OK 成功
				}
				else {
					return 1;  // NG 領域を確保できなかった
				}
			}
			else {
				return 0; // OK 配列の要素数が変わらない場合、何もしない
			}
		}
	}
	else {
		MessageBox( NULL, "resize_variables: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NO_VALUE;	// NG メモリ不足
	}
}

// 文字列型配列をリサイズ ( 0 〜 n-1 )
unsigned int resize_variables_d( const char *s, unsigned int n )
{
	unsigned int r;		// 変数番号
	char *s_lc;			// 小文字化した変数名

	if ( n >= 0xffffffff/sizeof(char *) ) {
		return 1; // NG 限界を超えた配列要素数
	}

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )

		r = symlook_d_a( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return array_variables_d(s, n); // 未宣言の配列だった場合は、宣言する
		}
		else {
			char **tmp;
			unsigned int i;

			if ( n > variables_d_a[r].num ) { // 配列が多くなる場合
				tmp = (char **)realloc( variables_d_a[r].ptext, n*sizeof(char *) );
				if ( tmp ) {
					variables_d_a[r].ptext = tmp;
					for(i=variables_d_a[r].num ; i<n ; ++i) {
						variables_d_a[r].ptext[i] = _strdup( "" );
						if ( variables_d_a[r].ptext[i] == NULL ) {
							do {
								safefree( variables_d_a[r].ptext[--i] );
							} while( i > variables_d_a[r].num );
							return 1; // NG 領域の確保に失敗
						}
					}
					variables_d_a[r].num = n;
					return 0; // OK 成功
				}
				else {
					return 1;  // NG 領域を確保できなかった
				}
			}
			else if ( n < variables_d_a[r].num ) { // 配列が少なくなる場合
				if ( n == 0 ) { // 配列の大きさを0に使用とした場合は、大きさ1の配列が準備される
					n = 1;
				}

				for(i=variables_d_a[r].num-1 ; i>=n ; i--) {
					safefree( variables_d_a[r].ptext[i] );
				}

				tmp = (char **)realloc( variables_d_a[r].ptext, n*sizeof(char *) );
				if ( tmp ) {
					variables_d_a[r].ptext = tmp;
					variables_d_a[r].num = n;
					return 0; // OK 成功
				}
				else {
					return 1;  // NG 領域を確保できなかった
				}
			}
			else {
				return 0; // OK 配列の要素数が変わらない場合、何もしない
			}
		}
	}
	else {
		MessageBox( NULL, "resize_variables_d: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NO_VALUE;	// NG メモリ不足
	}
}

// 整数型配列のサイズを取得 ( NO_VALUE : エラー )
unsigned int sizeof_variables( const char *s )
{
	unsigned int r;			// 変数番号
	char *s_lc;				// サーチ高速化のための変数名小文字化

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )
		r = symlook_a(s_lc);
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return NO_VALUE;
		}
		else {
			return variables_a[r].num;
		}
	}
	else {
		MessageBox( NULL, "sizeof_variables: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NO_VALUE;	// NG メモリ不足
	}
}

// 文字列型配列のサイズを取得 ( NO_VALUE : エラー )
unsigned int sizeof_variables_d( const char *s )
{
	unsigned int r;			// 変数番号
	char *s_lc;				// サーチ高速化のための変数名小文字化

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )
		r = symlook_d_a(s_lc);
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return NO_VALUE;
		}
		else {
			return variables_d_a[r].num;
		}
	}
	else {
		MessageBox( NULL, "sizeof_variables_d: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NO_VALUE;	// NG メモリ不足
	}
}

// 数値型配列 s が表す要素の先頭ポインタを返す
PVARIABLE_A search_pointer_a( const char *s )
{
	unsigned int r;			// 変数番号
	char *s_lc;				// サーチ高速化のための変数名小文字化

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )
		r = symlook_a( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return NULL;
		}
		else {
			return &variables_a[r];
		}
	}
	else {
		MessageBox( NULL, "search_pointer_a: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NULL;	// NG メモリ不足
	}
}

// 文字列型配列 s が表す要素の先頭ポインタを返す
PVARIABLE_D_A search_pointer_d_a( const char *s )
{
	unsigned int r;			// 変数番号
	char *s_lc;				// サーチ高速化のための変数名小文字化

	s_lc = _strdup(s);
	if ( s_lc ) {
#pragma warning( disable : 4996 )
		_strlwr(s_lc);			// 変数名を小文字化
#pragma warning( default : 4996 )
		r = symlook_d_a( s_lc );
		safefree(s_lc);

		if ( r == NO_VALUE ) {
			return NULL;
		}
		else {
			return &variables_d_a[r];
		}
	}
	else {
		MessageBox( NULL, "search_pointer_d_a: 作業用のメモリが不足しています。", "R-Script警告", MB_OK | MB_ICONEXCLAMATION);
		return NULL;	// NG メモリ不足
	}
}
