/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

	【機能概要】	: 共有メモリデータ展開プログラム
					  ２つの定義ファイル（共有メモリ定義ファイル、テーブル定義ファイル）
					  に従って、データファイル（tsv）とアクセスパターンファイル（xml）を
					  共有メモリ上に展開する。

	【作成日】		: 2021.04.23

	【呼出形式】	: GG_SHM1000
							[ 共有メモリグループ ]		# 共有メモリ定義ファイルで定義したグループ名称
							[ 展開オプション ]			# 共有メモリ展開オプション
	【戻り値1】		: int								# 0 : 正常終了、-1 : 異常終了

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef _NONSTOP
#include <libxml/SAX.h>
#endif
#include <iconv.h>
#include <sys/stat.h>

#include "GG_SHMCOM.h"

static char		g_szLogFilePath [ MAX_PATH ] ;				// ログファイル名
static char		g_szXmlFilePath [ MAX_PATH ] ;				// XMLファイルPath
static char		g_szTsvFilePath [ MAX_PATH ] ;				// TSVファイルPath

static int		MaxRows ;
static int		MaxColumns ;
static char		*c_SHMemory = NULL ;
static char		*c_SHMBase  = NULL ;
static long		l_SHMemory = 0 ;
static long		MaxColSize = MAX_COLSIZE;

static ST_TblDef		*t_TblDef ;
static ST_ColumnDef	*t_ColumnDef ;

static iconv_t	cd ;

char	***pStructData ;
char	**pStructDataSort ;

char	***xmlStruct ;

//char	pStructData [MAX_ROWS][MAX_COLUMNS][MAX_COLSIZE] ;
//char	xmlStruct [MAX_ROWS][MAX_COLUMNS][MAX_COLSIZE] ;

int		compare_str(const void* a, const void* b) ;
int		compare_int(const void* a, const void* b) ;
char***		GG_SHM1000_malloc( int rows , int columns , int colsize ) ;
char**		GG_SHM1000_malloc_2( int rows , int colsize ) ;
void	qsort_reset ( char **b , int rows , int colsize ) ;

#ifdef _NONSTOP
char*    GG_SHM1100_NONSTOP ( char *filename ) ;
#endif

int option_c2_proc(ST_ShmDef *s_ShmDef);
void strchg(char *buf, const char *str1, const char *str2);
void appendLog (int *logLen , char **logBuff , const char *append) ;

CLSSharedMemory shmAcPtMng;
CLSSharedMemory shmAcPtPtr_A[ GG_SHM1001_SHMIDNUM ];
CLSSharedMemory shmAcPtPtr_B[ GG_SHM1001_SHMIDNUM ];

int main(
	int		argc,
	char	*argv[]
)
{
	char	szLogFileTmpPath [ MAX_PATH ] ;			// ログファイル一時名称
	char	szAccessDate [ 30 ] ;					// YYYY/MM/DD HH:MM:SS.mmmmmm
	char	c_GG_SHM_TBLDEF [ MAX_PATH ] ;			// テーブル管理ファイル
	FILE	*TblDeffp ;
	char	*TblDefChar ;
	struct stat		stat_buf ;
	char	XmlInFile [ MAX_PATH ] ;
	char	*TblDefLine ;
	char	*TblDefLineWk ;
	char	*TblDefPrm ;
	ST_ShmDef	*s_ShmDef ;							//使用面管理領域
	ST_ShmDef	*s_ShmDefBase ;						//使用面管理先頭領域
	char	szCmEnvName [ MAX_PATH ] ;				// 環境名
	char	tmpStr [ 2048 ] ;

	long		usedMemSize = 0;

// ログ出力場所の決定
	getEnvString ( szLogFileTmpPath,"GG_LogFileName",GG_SHM1000_LOGPATH,sizeof(szLogFileTmpPath) ) ;
	getLocalTimeString ( g_szLogFilePath,sizeof(g_szLogFilePath),szLogFileTmpPath ) ;

// データおよび環境ファイル格納場所の取得
	getEnvString ( g_szXmlFilePath,"GG_XmlFilePath","",sizeof(g_szXmlFilePath) ) ;
	getEnvString ( g_szTsvFilePath,"GG_TsvFilePath","",sizeof(g_szTsvFilePath) ) ;

// 環境名の決定
	getEnvString ( szCmEnvName,"CM_ENV_NAME","galaxygoby",sizeof(szCmEnvName) ) ;

// 開始メッセージ出力
	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 テーブルデータ展開 **** START ****"
				, szAccessDate ) ;
	GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 環境名=[%s]"
				, szAccessDate , szCmEnvName ) ;

// データ作業領域確保
	MaxRows    = (int)getEnvLong("GG_SHM1000_MAX_ROWS",MAX_ROWS) + 1 ;
	MaxColumns = (int)getEnvLong("GG_SHM1000_MAX_COLUMNS",MAX_COLUMNS) + 1 ;
	MaxColSize = (int)getEnvLong("GG_SHM1000_MAX_COLSIZE",MAX_COLSIZE) + 1 ;
	if ( MaxColSize < strlen(PARM_FULLSCAN) + 1 ) {
		MaxColSize = strlen(PARM_FULLSCAN) + 1 ;
	}
	pStructData = GG_SHM1000_malloc( MaxRows , MaxColumns , MaxColSize ) ;
	if (pStructData == NULL) {
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0 , "**** ( %s ) **** GG_SHM1000 データ作業領域確保エラー ****"
			, szAccessDate ) ;
		exit (-1);
	}

// XML作業領域確保
// 領域長（MAX_ROWS等）を変更する場合、GG_SHM1100のGG_SHM1100_MaxRow等を合わせて修正要
	xmlStruct = GG_SHM1000_malloc ( MAX_ROWS + 1 , MAX_COLUMNS + 1 , MAX_COLSIZE + 1 ) ;
	if (xmlStruct == NULL) {
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0 , "**** ( %s ) **** GG_SHM1000 XML作業領域確保エラー ****"
			, szAccessDate ) ;
		exit (-1);
	}

// 共有メモリ取得

	/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
							共有メモリポインタ取得 ( 管理部 )
	_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

	key_t keyShmMainMem   = getEnvLong("GG_SHM1001_MEMORYID",GG_SHM1001_MEMORYID);

	char *c_ShmMngTmp = (char *)shmAcPtMng.OpenSheredMemory( keyShmMainMem );
	if (c_ShmMngTmp == NULL) {
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0 , "**** ( %s ) **** GG_SHM1000 共有メモリ取得エラー ****"
			, szAccessDate ) ;
		exit (-1);
	}

// ログレベルの設定
	long LogLevel ;
	memcpy ( (void *)&LogLevel , (void *)c_ShmMngTmp , sizeof(LogLevel) ) ;

// 先頭は、ログレベル(long型)の設定に使用
	s_ShmDef = (ShmDefType *)( c_ShmMngTmp + sizeof(LogLevel) ) ;
	s_ShmDefBase = s_ShmDef ;

// 起動パラメータは、メモリグループ名と展開オプション
	if ( argc < 3 ) {
		printf("Usage : GG_SHM1000 [メモリグループ] [オプション]\n") ;
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0 , "**** ( %s ) **** Usage : GG_SHM1000 [メモリグループ] [オプション]****"
			, szAccessDate ) ;
		exit (-1);
	}

// 共有メモリの使用面でない方に情報（データ、定義）を展開
	for ( int i = 0 ; s_ShmDef->ShmName[0] != '\0' ; i++ , s_ShmDef ++ ) {
		if ( strcmp ( s_ShmDef->ShmName , argv[1] ) == 0 ) {
			if ( s_ShmDef->ShmFlg == 0 || s_ShmDef->ShmFlg == 2 ) {
				c_SHMemory = (char *)shmAcPtPtr_A[i].OpenSheredMemory( s_ShmDef->ShmID_A );
			} else if ( s_ShmDef->ShmFlg == 1 ) {
				c_SHMemory = (char *)shmAcPtPtr_B[i].OpenSheredMemory( s_ShmDef->ShmID_B );
			} else {
				c_SHMemory = NULL ;
			}
			if ( c_SHMemory == NULL ) {
				getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
				GG_MsgOut ( g_szLogFilePath , 0 ,"**** ( %s ) **** GG_SHM1000 共有メモリ取得エラー [%s]****"
					, szAccessDate , argv[1] ) ;
				exit (-1);
			}
			break ;
		}
	}

// 共有メモリ定義情報にないメモリグループ名が指定された場合エラー処理
	if ( s_ShmDef->ShmName[0] == '\0' ) {
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0 , "**** ( %s ) **** GG_SHM1000 パラメータエラー [%s] ****"
			, szAccessDate , argv[1] ) ;
		exit (-1);
	}

// -c2オプション（面切替のみ）の場合、面を切替終了
	if ( strcmp ( "-c2" , argv[2] ) == 0 ) {
		option_c2_proc( s_ShmDef );

		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
					, "**** ( %s ) **** GG_SHM1000 面切替 メモリグループ：[%s] 面：[%d] ****"
					, szAccessDate , s_ShmDef->ShmName , s_ShmDef->ShmFlg ) ;
		// 終了メッセージ出力
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
					, "**** ( %s ) **** GG_SHM1000 テーブルデータ展開 **** END ****"
					, szAccessDate ) ;
		exit (0);
	}


// c_SHMBase に共有メモリポインタ格納
	c_SHMBase = c_SHMemory ;
	
// TableDefのopen
	
	getEnvString ( c_GG_SHM_TBLDEF , "GG_SHM_TBLDEF"
				, GG_SHM1000_TBLDEF , sizeof(c_GG_SHM_TBLDEF) ) ;
	if ( ( TblDeffp = fopen ( c_GG_SHM_TBLDEF , "r" ) ) == NULL) {
//		printf("file open error!! TblDefFile = [ %s ]\n" , GG_SHM1000_TBLDEF );
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0
				, "**** ( %s ) **** GG_SHM1000 TBLDEFファイルの取得失敗 [ %s ]"
				, szAccessDate , GG_SHM1000_TBLDEF ) ;
		exit (-1);
	}
	
// TableDefのサイズ取得
	
	if ( stat ( c_GG_SHM_TBLDEF, &stat_buf ) != 0 ) {
//		printf("file stat error!! TblDefFile = [ %s ]\n" , c_GG_SHM_TBLDEF );
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0
				, "**** ( %s ) **** GG_SHM1000 TBLDEFファイルのstat失敗 [ %s ]"
				, szAccessDate , c_GG_SHM_TBLDEF ) ;
		exit (-1);
	}
	
// TableDefの読込
	
	TblDefChar = (char *)malloc ( stat_buf.st_size + 1 ) ;
	fread ( TblDefChar , 1 , stat_buf.st_size , TblDeffp ) ;
	fclose ( TblDeffp ) ;
	TblDefChar [ stat_buf.st_size ] = '\0' ;
	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 TableDef読込完了"
				, szAccessDate ) ;

// TableDefのレコード件数取得
	
	long TblDefNum , TblDefNum2 = 0 ;
	TblDefLineWk = strtok( TblDefChar , "\n" );
	for ( TblDefNum = 0 ; TblDefLineWk != NULL ; TblDefNum ++ )
		TblDefLineWk = strtok( NULL , "\n" ) ;
	
// TableDefの構造体設定
	
	TblDefLine  = (char *) malloc ( TblDefNum * 1024 ) ;
	TblDefLineWk = TblDefChar ;
	char *TblDefLinePos = TblDefLine ;
	for ( int i = 0 ; i < TblDefNum ; i++ ) {
		if ( TblDefLineWk[0] != ';' ) {
			strcpy ( TblDefLinePos , TblDefLineWk ) ;
			if ( TblDefLinePos[strlen(TblDefLinePos)-1] == '\r' )
				TblDefLinePos[strlen(TblDefLinePos)-1] = '\0' ;
			TblDefLinePos = TblDefLinePos + 1024 ;
			TblDefNum2 ++ ;
		}
		TblDefLineWk = TblDefLineWk + strlen(TblDefLineWk) + 1 ;
	}
	TblDefNum = TblDefNum2 ;
	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
			, "**** ( %s ) **** GG_SHM1000 TableDef件数=[%d]"
			, szAccessDate , TblDefNum ) ;

// TableDefの昇順並べ替え
	
	qsort( TblDefLine, TblDefNum, 1024 , compare_str );

// TableDefのデータ整備および初期値設定
	
	t_TblDef = (struct TblDefType *) malloc ( TblDefNum * sizeof(*t_TblDef) ) ;
	ST_TblShmDef *t_TblShmDef = (struct TblShmDefType *) malloc ( TblDefNum * sizeof(ST_TblShmDef) ) ;

	TblDefLinePos = TblDefLine ;
	TblDefNum2 = 0 ;
	for ( int i = 0 ; i < TblDefNum ; i++ ) {
		TblDefPrm = strtok( TblDefLinePos , "," ) ;
		// テーブルID設定
		strcpy ( t_TblDef[TblDefNum2].TblNo , TblDefPrm ) ;
		TblDefPrm = strtok( NULL , "," ) ;
		// テーブル識別子設定
		strcpy ( t_TblDef[TblDefNum2].TblId , TblDefPrm ) ;
		strcpy ( t_TblShmDef[TblDefNum2].TblId , TblDefPrm ) ;
		TblDefPrm = strtok( NULL , "," ) ;
		if ( strcmp ( TblDefPrm , argv[1] ) != 0 ) {
			TblDefLinePos = TblDefLinePos + 1024 ;
			continue ;
		}
		// グループ識別子設定
		strcpy ( t_TblShmDef[TblDefNum2].ShmName , TblDefPrm ) ;
		TblDefPrm = strtok( NULL , "," ) ;
		// 
		strcpy ( t_TblDef[TblDefNum2].AcType , TblDefPrm ) ;
		TblDefPrm = strtok( NULL , "," ) ;
		// 共有情報ファイル名設定
		strcpy ( tmpStr , TblDefPrm ) ;
		// 環境変数部分を置換
		strchg ( tmpStr , "${CM_ENV_NAME}" , szCmEnvName );
		strcpy ( t_TblDef[TblDefNum2].TextName , tmpStr );
		TblDefPrm = strtok( NULL , "," ) ;
		// 共有メモリアクセスパターンファイル名設定
		strcpy ( tmpStr , TblDefPrm ) ;
		// 環境変数部分を置換
		strchg ( tmpStr , "${CM_ENV_NAME}" , szCmEnvName );
		strcpy ( t_TblDef[TblDefNum2].XmlFileName , tmpStr ) ;
		TblDefPrm = strtok( NULL , "," ) ;
		strcpy ( t_TblDef[TblDefNum2].TblName , TblDefPrm ) ;
		t_TblDef[TblDefNum2].TblDataPos = 0 ;				// テーブルデータ相対開始位置
		t_TblDef[TblDefNum2].TblDataLen = 0 ;				// テーブルデータ全体長
		t_TblDef[TblDefNum2].TblColPos  = 0 ;				// 項目情報相対開始位置
		t_TblDef[TblDefNum2].TblColNum  = 0 ;				// 項目情報件数
		t_TblDef[TblDefNum2].TblPtnPos  = 0 ;				// アクセスパターン相対開始位置
		t_TblDef[TblDefNum2].TblPtnNum  = 0 ;				// アクセスパターン件数
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 4
				, "**** ( %s ) **** TblNo=%s TblId=%s AcType=%s TextName=%s XmlFileName=%s TblName=%s"
				, szAccessDate , t_TblDef[i].TblNo , t_TblDef[i].TblId
				, t_TblDef[TblDefNum2].AcType , t_TblDef[TblDefNum2].TextName
				, t_TblDef[TblDefNum2].XmlFileName , t_TblDef[TblDefNum2].TblName ) ;
		TblDefLinePos = TblDefLinePos + 1024 ;
		TblDefNum2 ++ ;
	}
	TblDefNum = TblDefNum2 ;
	
//	printf("c_SHMemory=[%d] l_SHMemory=[%d]\n",(long)c_SHMemory,l_SHMemory) ;
	
	memcpy ( c_SHMemory , (char *)&TblDefNum , sizeof(TblDefNum) ) ;
	c_SHMemory = c_SHMemory + sizeof(TblDefNum);
	l_SHMemory = l_SHMemory + sizeof(TblDefNum) ;

//	printf("c_SHMemory=[%d] l_SHMemory=[%d]\n",(long)c_SHMemory,l_SHMemory) ;

	memcpy ( c_SHMemory , t_TblDef , TblDefNum * sizeof(*t_TblDef) ) ;
	c_SHMemory = c_SHMemory + ( TblDefNum * sizeof(*t_TblDef) ) ;
	l_SHMemory = l_SHMemory + ( TblDefNum * sizeof(*t_TblDef) ) ;

//	printf("c_SHMemory=[%d] l_SHMemory=[%d]\n",(long)c_SHMemory,l_SHMemory) ;

// iconvのオープンおよび初期化
#ifndef _NONSTOP
	cd = iconv_open("Shift_JIS" , "UTF-8") ;
	if (cd == (iconv_t)-1) {
//		printf( "iconv_open(%s, %s) エラー\n", "Shift_JIS", "UTF-8");
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0
				, "**** ( %s ) **** GG_SHM1000 iconv エラー [ %s ] to [ %s ]"
				, szAccessDate , "UTF-8" , "Shift_JIS" ) ;
		exit (-1);
	}
#else
	cd = iconv_open("SJIS" , "FSS-UTF") ;
	if (cd == (iconv_t)-1) {
//		printf( "iconv_open(%s, %s) エラー\n", "SJIS" , "FSS-UTF");
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0
				, "**** ( %s ) **** GG_SHM1000 iconv エラー [ %s ] to [ %s ]"
				, szAccessDate , "SJIS" , "FSS-UTF" ) ;
		exit (-1);
	}
#endif

// _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
// Tableデータの読込（１行目・データ項目）
// _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
	
//	t_ColumnDef = (struct ST_ColumnDef **) malloc ( TblDefNum * sizeof(*t_ColumnDef) ) ;

	for ( int i = 0 ; i < TblDefNum ; i++ ) {
		
		FILE	*TblDatafp ;
		char	TextName [ MAX_PATH ] ;
		
// TableDefのテキストファイル名に従い、テキストデータオープン
		if(strlen(g_szTsvFilePath) == 0){
			sprintf ( TextName , "%s" , t_TblDef[i].TextName ) ;
		}else{
			sprintf ( TextName , "%s/%s" , g_szTsvFilePath , t_TblDef[i].TextName ) ;
		}

		if ( ( TblDatafp = fopen( TextName , "r" ) ) == NULL) {
//			printf("file open error!! TblDefFile = [ %s ]\n" , TextName );
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 0
					, "**** ( %s ) **** GG_SHM1000 テキストデータの取得失敗 [ %s ]"
					, szAccessDate , TextName ) ;
			exit (-1);
		}

// テキストデータのサイズ取得
	
		if ( stat ( TextName, &stat_buf ) != 0 ) {
//			printf("file stat error!! TblDefFile = [ %s ]\n" , TextName );
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 0
					, "**** ( %s ) **** GG_SHM1000 テキストデータのstat失敗 [ %s ]"
					, szAccessDate , TextName ) ;
			exit (-1);
		}
		
// テキストデータの読込

		int	  BufSize = ( stat_buf.st_size + 1 ) * 2 ;
		char  *TblDataChar = (char *)malloc ( BufSize ) ;
		char  *ReadDataBuf = (char *)malloc ( BufSize ) ;

		char  *TblDataCharBase = TblDataChar ;

		// 全件読み込み
		fread ( TblDataChar , 1 , stat_buf.st_size , TblDatafp ) ;
		fclose ( TblDatafp ) ;
		TblDataChar [ stat_buf.st_size - 1 ] = '\0' ;

		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 [%s] ファイルサイズ=[%d]"
				, szAccessDate , TextName , stat_buf.st_size ) ;

// テキストデータのレコード件数取得
	
		int TblDataNum ;
		TblDefLineWk = strtok( TblDataChar , "\n" );
		for ( TblDataNum = 0 ; TblDefLineWk != NULL ; TblDataNum ++ ) {
			TblDefLineWk = strtok( NULL , "\n" ) ;
//			if ( TblDefLineWk != NULL ) {
//				getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
//				GG_MsgOut ( g_szLogFilePath , 1
//						, "**** ( %s ) **** GG_SHM1000 TblDefLineWk=[%s]"
//						, szAccessDate , TblDefLineWk ) ;
//			}
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 9
					, "**** ( %s ) **** GG_SHM1000 TblDataNum:(%d) TblDefLineWk:(%s)"
					, szAccessDate , TblDataNum, TblDefLineWk) ;
		}
		
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 [%s] 件数=[%d]"
				, szAccessDate , TextName , TblDataNum - 1 ) ;

		strcpy ( ReadDataBuf , TblDataChar ) ;
		TblDataChar = TblDataChar + strlen(TblDataChar) + 1 ;

// テキストデータの項目数取得
	
		int   ColumnNum ;
		char* Column = strtok ( ReadDataBuf , "\t" ) ;
		for ( ColumnNum = 0 ; Column != NULL ; ColumnNum ++ ) {
			Column = strtok ( NULL , "\t" ) ;
			if ( Column != NULL && Column[0] != '\0' ) {
				if ( Column[strlen(Column)-1] == '\r' )
					Column[strlen(Column)-1] = '\0' ;
			}
		}
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 [%s] 項目数=[%d]"
				, szAccessDate , TextName , ColumnNum ) ;

// テキストデータヘッダの項目情報設定および初期化
	
		t_ColumnDef
			= (struct ColumnDefType *) malloc ( ColumnNum * sizeof(*t_ColumnDef) ) ;
		Column = ReadDataBuf ;
		for ( int j = 0 ; j < ColumnNum ; j++ ) {
			memset ( t_ColumnDef[j].ColumnName , 0x00 , sizeof(t_ColumnDef[j].ColumnName) ) ;
			if ( strlen(Column) >= (int)sizeof(t_ColumnDef[j].ColumnName) ) {
				getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
				GG_MsgOut ( g_szLogFilePath , 0
					, "**** ( %s ) **** GG_SHM1000 ヘッダデータ項目長エラー [ %d < %s の長さ ]"
					, szAccessDate , sizeof(t_ColumnDef[j].ColumnName), Column) ;
				exit (-1);
			}
			strcpy ( t_ColumnDef[j].ColumnName , Column ) ;
			t_ColumnDef[j].ColumnSize = 0 ;
			Column = Column + strlen(Column) + 1 ;
			if ( Column[0] == '\0' ) Column++ ;
		}
		
// ヘッダの項目情報設定の共有メモリ設定
		
		char *cSHMColHeader = c_SHMemory ;
		memcpy ( c_SHMemory , t_ColumnDef , ColumnNum * sizeof(*t_ColumnDef) ) ;
		c_SHMemory = c_SHMemory + ( ColumnNum * sizeof(*t_ColumnDef) ) ;
		t_TblDef[i].TblColPos = l_SHMemory ;
		t_TblDef[i].TblColNum = ColumnNum ;
		
// テキストデータ本文および項目長の設定
		
		for ( int row = 0 ; row < TblDataNum-1 ; row ++ ) {
			strcpy ( ReadDataBuf , TblDataChar ) ;
			TblDataChar = TblDataChar + strlen(TblDataChar) + 1 ;
			int ReadDataPos = 0 ;

			int logBuffLen = LOG_LEN ;
			char *logBuff = (char *) malloc ( logBuffLen ) ;
			logBuff[0] = '\0' ;

			// ファイルから読込んだデータ項目をpStructData（一時領域）に格納
			// データは\tで区切られているので、項目に区切って格納
			for ( int col = 0 ; col < ColumnNum && Column != NULL ; col ++ ) {
				char *pos = strchr ( ReadDataBuf + ReadDataPos , '\t' ) ;
				if ( pos == NULL ) { pos = ReadDataBuf + strlen(ReadDataBuf) ; }
				int Collen = pos - ReadDataBuf - ReadDataPos ;

				// 環境変数で定義したMaxColSizeを超える項目があったときはエラー
				if ( Collen >= (int)MaxColSize ) {
					getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
					GG_MsgOut ( g_szLogFilePath , 0
						, "**** ( %s ) **** GG_SHM1000 データ項目長エラー [ %d < %s の長さ(%d) ]"
						, szAccessDate , MaxColSize, ReadDataBuf + ReadDataPos , Collen ) ;
					exit (-1);
				}
				// データ格納、データがない場合は0x1f（文字長調整）を埋める
				if ( Collen > 0 ) {
					strncpy ( pStructData[row][col] , ReadDataBuf+ReadDataPos , Collen ) ;
					pStructData[row][col][Collen] ='\0' ;
				} else {
					pStructData[row][col][0] = SP_REP ;
					pStructData[row][col][1] = 0x00 ;
				}
				ReadDataPos += Collen + 1 ;

				// ログ領域に格納情報を設定（logBuff自動拡張有り）
				appendLog ( &logBuffLen , &logBuff , pStructData[row][col] ) ;
				appendLog ( &logBuffLen , &logBuff , "\t" ) ;

				// カラム長に同一列データの最大長を設定
				if ( row == 0 ) {
					t_ColumnDef[col].ColumnSize = Collen ;
				} else {
					if ( t_ColumnDef[col].ColumnSize < Collen )
						t_ColumnDef[col].ColumnSize = Collen ;
				}
			}
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 10
				, "**** ( %s ) **** GG_SHM1000 [%s] [%d]\t%s"
				, szAccessDate , TextName , row , logBuff
			) ;
			free ( (char *) logBuff ) ;
		}

		free ( TblDataCharBase ) ;
		free ( ReadDataBuf ) ;

// 項目名と最大項目長をログ出力

		for ( int j = 0 ; j < ColumnNum ; j++ ) {
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 4	
				, "**** ( %s ) **** GG_SHM1000 [%s] 項目名=%s 項目長=%d"
				, szAccessDate , TextName , t_ColumnDef[j].ColumnName
				, t_ColumnDef[j].ColumnSize ) ;
		}
		
		memcpy ( cSHMColHeader , t_ColumnDef , ColumnNum * sizeof(*t_ColumnDef) ) ;
		
// テキストデータの共有メモリ設定
		
		t_TblDef[i].TblDataPos = (long)c_SHMemory - (long)c_SHMBase ;
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 [%s] テーブルデータ開始位置=[%d]"
				, szAccessDate , TextName , t_TblDef[i].TblDataPos ) ;
		l_SHMemory = 0 ;

		// pStructData（一時領域）に格納したデータを共有メモリに展開
		for ( int row = 0 ; row < TblDataNum-1 ; row ++ ) {
			int logBuffLen = LOG_LEN ;
			char *logBuff = (char *) malloc ( logBuffLen ) ;
			logBuff[0] = '\0' ;

			// 項目毎に最大長に合わせて、0x1fデータを埋めて同一項目長になるようにして設定
			for ( int col = 0 ; col < ColumnNum ; col ++ ) {
				strcpy ( c_SHMemory , pStructData[row][col] ) ;
				if ( strlen ( pStructData[row][col] ) < (int)t_ColumnDef[col].ColumnSize ) {
					memset ( c_SHMemory + strlen ( pStructData[row][col] )
							, SP_REP
							, (int)t_ColumnDef[col].ColumnSize - strlen ( pStructData[row][col] ) 
					) ;
				}
				
				c_SHMemory = c_SHMemory + t_ColumnDef[col].ColumnSize ;
				l_SHMemory = l_SHMemory + t_ColumnDef[col].ColumnSize ;

				// ログ領域に格納情報を設定（logBuff自動拡張有り）
				char cColSize [30] ;
				sprintf ( cColSize , "\t(%d)\t" , (int)t_ColumnDef[col].ColumnSize ) ;
				appendLog ( &logBuffLen , &logBuff , cColSize ) ;
				appendLog ( &logBuffLen , &logBuff , pStructData[row][col] ) ;
			}
			// ログ出力
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 9
					, "**** ( %s ) **** GG_SHM1000 row[%d]:%s"
					, szAccessDate , row, logBuff
			) ;
			free ( (char *) logBuff ) ;
		}

		free ( (char *)t_ColumnDef ) ;

		t_TblDef[i].TblDataLen = l_SHMemory ;
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 [%s] テーブルデータ長=[%d]"
				, szAccessDate , TextName , t_TblDef[i].TblDataLen ) ;

// XMLデータの設定

		if (strlen(g_szXmlFilePath) == 0) {
			sprintf ( XmlInFile , "%s" , t_TblDef[i].XmlFileName ) ;
		}
		else {
			sprintf ( XmlInFile , "%s/%s" , g_szXmlFilePath , t_TblDef[i].XmlFileName ) ;
		}
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 パターンファイル名称=[%s]"
				, szAccessDate , XmlInFile ) ;

		char *c_data ;

#ifndef _NONSTOP
		c_data = GG_SHM1100 ( XmlInFile ) ;
#else
		c_data = GG_SHM1100_NONSTOP ( XmlInFile ) ;
#endif

		if ( c_data == (char *)NULL ) {
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 0
					, "**** ( %s ) **** GG_SHM1000 xmlファイル解析エラー [ %s ]"
					, szAccessDate ,XmlInFile ) ;
			exit (-1);
		}

		// アクセスパターン一時格納領域（xmlStruct）に設定
		int row = 0 ;
		int col = 0 ;
		for ( int j = 0 , k = 0 ; c_data[j] != '\0' ; j++ ) {
			if ( c_data[j] == '\t' ) {
				memcpy ( xmlStruct[row][col] , c_data + k , j - k ) ;
				xmlStruct[row][col][j-k] = '\0' ;
				col++ ;
				k = j + 1 ;
				strcpy ( xmlStruct[row][col] , STR_NULL ) ;
			} else if ( c_data[j] == '\n' ) {
				row++ ;
				k = j + 1 ;
				col = 0 ;
				strcpy ( xmlStruct[row][col] , STR_NULL ) ;
			}
		}
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 4
				, "**** ( %s ) **** GG_SHM1000 c_data = [\n%s]"
				, szAccessDate , c_data
		) ;

		free ( (void *)c_data ) ;

// XMLデータの共有メモリ設定

		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 4
				, "**** ( %s ) **** GG_SHM1000 共有メモリ設定" , szAccessDate ) ;

		t_TblDef[i].TblPtnPos = (long)c_SHMemory - (long)c_SHMBase ;
		for ( row = 0 ; strcmp( xmlStruct[row][0], STR_NULL ) != 0 ; row ++ ) {
			char *wSHMemory = c_SHMemory + sizeof(row) ;
			int col = 0 ;
			for ( ; strcmp( xmlStruct[row][col], STR_NULL ) != 0 ; col ++ ) {
				if ( col == 2 ) {
					// col == 2 は、「検索条件格納領域」で、編集が必要
					char whereWork [ MAX_PATTERNSZ ] ;
					int  whereRet = GG_SHM1003 ( xmlStruct[row][col] , whereWork ) ;
					if ( whereRet != 0 ) {
						getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
						GG_MsgOut ( g_szLogFilePath , 0
								, "**** ( %s ) **** GG_SHM1000 検索条件構文解析エラー Status=%d\n[ %s ] [ %s ] [ %s ]"
								, szAccessDate ,whereRet ,xmlStruct[row][0] ,xmlStruct[row][1] ,xmlStruct[row][2] ) ;
						exit (-1);
					}
					strcpy ( wSHMemory , whereWork ) ;
					wSHMemory = wSHMemory + strlen ( whereWork ) + 1 ;
					getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
					GG_MsgOut ( g_szLogFilePath , 4
							, "**** ( %s ) **** GG_SHM1000 xmlStruct[%d][%d] = [%s]"
							, szAccessDate , row , col , whereWork
					) ;
					// col=3,4,5の箇所に、インデックス開始位置 / レコード長 / レコード件数
					// の初期値（0:12桁）を格納。インデックス検索の場合は、次ロジックで
					// それぞれの値が設定される。
					strcpy ( wSHMemory , PARM_FULLSCAN ) ;
					wSHMemory += strlen(wSHMemory) + 1 ;
					strcpy ( wSHMemory , PARM_FULLSCAN ) ;
					wSHMemory += strlen(wSHMemory) + 1 ;
					strcpy ( wSHMemory , PARM_FULLSCAN ) ;
					wSHMemory += strlen(wSHMemory) + 1 ;
				} else {
					strcpy ( wSHMemory , xmlStruct[row][col] ) ;
					wSHMemory = wSHMemory + strlen ( xmlStruct[row][col] ) + 1 ;
					getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
					GG_MsgOut ( g_szLogFilePath , 4
							, "**** ( %s ) **** GG_SHM1000 xmlStruct[%d][%d] = [%s]"
							, szAccessDate , row , col , xmlStruct[row][col]
					) ;
				}
			}
			col += 3 ;								// col=3,4,5の分を追加
			memcpy ( c_SHMemory , (char *)&(col) , sizeof(col) ) ;
			c_SHMemory = wSHMemory ;
		}
		l_SHMemory = (long)c_SHMemory - (long)c_SHMBase ;
		t_TblDef[i].TblPtnNum = row ;
		usedMemSize = l_SHMemory;
	}
	
// 共有メモリデータ・アクセス管理部の共有メモリ設定
	memcpy ( c_SHMBase + sizeof(TblDefNum) , (char *)t_TblDef
			, TblDefNum * sizeof(*t_TblDef) ) ;

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
	インデックス作成処理
	アクセスパターン名称が「Index_」で始まり、検索条件接続詞が「or」でないものが対象
	インデックス項目は、検索条件が「=」であり、文字列比較であるものが対象となる 
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

	char AcPt 	[GG_SHM0001_MaxPrmNum][GG_SHM0001_MaxCondLen] ;	// アクセスパターン一時領域
	char Left	[GG_SHM0001_MaxCond][GG_SHM0001_MaxLeftLen] ;	// インデックス項目格納

	// テーブル情報毎にループ
	for ( int i = 0 ; i < TblDefNum ; i++ ) {
		char *wSHMemory = c_SHMBase + t_TblDef[i].TblPtnPos ;
		char *wIndexPos , *wIndexRec , *wIndexRow ;

		// アクセスパターン毎にループ
		for ( int j = 0 ; j < t_TblDef[i].TblPtnNum ; j++ ) {
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 9
					, "**** ( %s ) **** GG_SHM1000 テーブルNo=[%d/%d] アクセスPtnNo=[%d/%d]"
					, szAccessDate , i , TblDefNum , j , t_TblDef[i].TblPtnNum
			) ;
			int colnum ;
			memcpy ( (char *)&colnum , wSHMemory , sizeof(colnum) ) ;
			wSHMemory = wSHMemory + sizeof(colnum) ;
			// アクセスパターンを共有メモリ情報から一時領域（AcPt）に展開
			// また、インデックス情報格納ポインタ（col=3,4,5）を一時領域に格納
			for ( int col = 0 ; col < colnum ; col++ ) {
				strcpy ( AcPt[col] , wSHMemory ) ;
				AcPt[col+1][0] = '\0' ;
				if ( col == 3 ) wIndexPos = wSHMemory ;
				if ( col == 4 ) wIndexRec = wSHMemory ;
				if ( col == 5 ) wIndexRow = wSHMemory ;
				wSHMemory = wSHMemory + strlen(AcPt[col]) + 1 ;
			}

			if ( memcmp ( AcPt [1] , "Index_" , 6 ) != 0 ) continue ;
			// アクセスパターン名称が「Index_」から始まる場合、インデックス検索対象

			long m = 0;
			int  p = 0;
			Left[0][0] = '\0' ;
			for ( int n=0 ,k=0; m <= strlen(AcPt[2]) ; m++ ) {
				int q = k % 4 ;
				if ( AcPt[2][m] == ' ' || m == strlen(AcPt[2]) ) {
					if ( q==0 ) {
						memcpy ( Left[p] , AcPt[2]+n , m-n ) ;
						Left[p][m-n] = '\0' ;
						Left[p+1][0] = '\0' ;
						// @NUM対応 数字比較を行う場合は、インデックス項目対象外
						char *Left_Num_Pos = strchr ( Left[p] , '@' ) ;
						if ( Left_Num_Pos == NULL ) {
							getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
							GG_MsgOut ( g_szLogFilePath , 9
									, "**** ( %s ) **** GG_SHM1000 インデックス項目 [%s] : %s / %s"
									, szAccessDate , Left[p] , AcPt[0] , AcPt[1]
							) ;
						} else {
							Left[p][0] = '\0' ; 
						}
					} else
					if ( q==1 ) {
						if ( Left[p][0] != '\0' ) {
							if ( memcmp ( AcPt[2]+n , "=" , m-n ) == 0 ) {
								// インデックス項目確定
								p++ ;
							} else {
								// インデックス項目から除外
								getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
								GG_MsgOut ( g_szLogFilePath , 9
									, "**** ( %s ) **** GG_SHM1000 インデックス除外 [%s] : %s / %s （=比較でない）"
									, szAccessDate , Left[p] , AcPt[0] , AcPt[1]
								) ;
								Left[p][0] = '\0' ;
							}
						}
					} else
					if ( q == 3 ) {
						// インデックスは作成しない
						if ( memcmp ( AcPt[2]+n , "or" , m-n ) == 0 ) break ;
					}
					n = m + 1 ;
					k++ ;
				}
			}
			if ( Left[0][0] == '\0' ) {
				getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
				GG_MsgOut ( g_szLogFilePath , 4
						, "**** ( %s ) **** GG_SHM1000 検索名[%s]は、Where句に文字列+「=」検索がないため、通常検索[%s]"
						, szAccessDate , AcPt[1] , AcPt[2]
				) ;
				continue ;
			}
			if ( m <= strlen(AcPt[2]) ) {
				getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
				GG_MsgOut ( g_szLogFilePath , 4
						, "**** ( %s ) **** GG_SHM1000 検索名[%s]は、「or」検索のため通常検索を行います[%s]"
						, szAccessDate , AcPt[1] , AcPt[2]
				) ;
				continue ;
			}
			
			// 各検索項目（Left[n]）の相対位置と長さをテーブルヘッダ情報から算出
			// して、Leftpos[n],Leftlen[n]に格納
			
			int  Leftpos	[GG_SHM0001_MaxCond] ;		// インデックス項目のデータ格納相対位置
			int  Leftlen	[GG_SHM0001_MaxCond] ;		// インデックス項目のデータ長
			long TblDataLen = 0 ;

			t_ColumnDef = (struct ColumnDefType *)(c_SHMBase + t_TblDef[i].TblColPos ) ;

			for ( int n = 0 ;  Left[n][0] != '\0' ; n ++ ) {
				TblDataLen = 0 ;
				for ( int k = 0 ; k < t_TblDef[i].TblColNum ; k ++ ) {
					if ( strcmp ( Left[n] , t_ColumnDef[k].ColumnName ) == 0 ) {
						Leftpos[n] = TblDataLen ;
						Leftlen[n] = t_ColumnDef[k].ColumnSize ;
						getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
						GG_MsgOut ( g_szLogFilePath , 4
								, "**** ( %s ) **** GG_SHM1000 %s:%s pos:len=%d:%d"
								, szAccessDate , AcPt[1] , Left[n] , Leftpos[n] , Leftlen[n]
						) ;
						break ;
					}
					TblDataLen = TblDataLen + t_ColumnDef[k].ColumnSize ;
				}
			}

			// データ格納相対位置の大きさ（12バイト）をLeftlen[n]に格納
			for ( int n = 0 ; ; n ++ ) {
				if ( Left[n][0] == '\0' ) {
					Leftlen[n] = strlen ( PARM_FULLSCAN ) ;
					break ;
				}
			}

			// データレコード長を TbleDataLen に算出・格納
			TblDataLen = 0 ;
			for ( int n = 0 ; n < t_TblDef[i].TblColNum ; n ++ ) {
				TblDataLen = TblDataLen + t_ColumnDef[n].ColumnSize ;
			}

			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 9
				, "**** ( %s ) **** GG_SHM1000 %s テーブルレコード長 = [%d]"
				, szAccessDate , AcPt[0] , TblDataLen
			) ;

			// pStructData（テーブルデータ一時格納領域）に共有メモリデータを格納

			long row = 0 , col = 0 , recLen = 0 ;
			
			char *wSHMemory2 = c_SHMBase + t_TblDef[i].TblDataPos ;
			for ( int n = 0 ; n < t_TblDef[i].TblDataLen ; ) {
				col = 0 ;
				int logBuffLen = LOG_LEN ;
				char *logBuff = (char *) malloc ( logBuffLen ) ;
				logBuff[0] = '\0' ;
				for ( int k = 0 ; Left[k][0] != '\0' ; k ++ ) {
					// pStructData（テーブルデータ一時格納領域）に格納
					strncpy ( pStructData[row][col] , wSHMemory2 + n + Leftpos[k] , Leftlen[k] ) ;
					pStructData[row][col][Leftlen[k]] ='\0' ;
					// インデックスのレコード長算出
					if ( row == 0 ) recLen +=  Leftlen[k] ;

					// ログ領域に格納情報を設定（logBuff自動拡張有り）
					appendLog ( &logBuffLen , &logBuff , pStructData[row][col] ) ;

					char *x1f = strchr ( logBuff , SP_REP ) ;
					if ( x1f != NULL ) *x1f = '\0' ;
					strcat ( logBuff , "\t" ) ;

					col ++ ;
				}
				// レコード相対位置の格納
				sprintf ( pStructData[row][col] ,"%012d" , n ) ;
				pStructData[row][col+1][0] ='\0' ;

				// ログ出力
				appendLog ( &logBuffLen , &logBuff , pStructData[row][col] ) ;
				getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
				GG_MsgOut ( g_szLogFilePath , 10
					, "**** ( %s ) **** GG_SHM1000 SORT前 row[%d]:%s"
					, szAccessDate , row , logBuff
				) ;

				// インデックスのレコード長にレコード相対位置の長さを追加
				if ( row == 0 ) recLen += strlen(PARM_FULLSCAN) ;

				row ++ ;
				pStructData[row][0][0] ='\0' ;
				n = n + TblDataLen ;
			}
			
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 9
					, "**** ( %s ) **** GG_SHM1000 インデックスソート準備 %s : %s row:col:recLen=%d:%d:%d"
					, szAccessDate , AcPt[0] , AcPt[1] , row , col , recLen
			) ;

			// ソート用メモリ領域確保
			pStructDataSort = GG_SHM1000_malloc_2 ( row + 1 , recLen + 1 ) ;
			if (pStructDataSort == NULL) {
				getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
				GG_MsgOut ( g_szLogFilePath , 0 , "**** ( %s ) **** GG_SHM1000_malloc_2 作業領域確保エラー ****"
					, szAccessDate ) ;
				exit (-1);
			}

			// テーブルデータをpStructData（テーブルデータ一時格納領域）から
			// pStructDataSort（ソート用メモリ領域）に格納
			for ( int n = 0 ; n < row ; n ++ ) {
				pStructDataSort[n][0] = '\0' ;
				int logBuffLen = LOG_LEN ;
				char *logBuff = (char *) malloc ( logBuffLen ) ;
				logBuff[0] = '\0' ;
				for ( int k = 0 ; k <= col ; k ++ ) {
					// テーブルデータをソート用メモリ領域に格納
					strcat ( pStructDataSort[n] , pStructData[n][k] ) ;

					// ログ領域に格納情報を設定（logBuff自動拡張有り）
					appendLog ( &logBuffLen , &logBuff , pStructData[n][k] ) ;
					appendLog ( &logBuffLen , &logBuff , "\t" ) ;
				}

				// ログ領域の0x1fコード一括置換
				char *p ;
				while ( ( p = strchr (logBuff , SP_REP) ) != NULL ) {
					*p = ' ' ;
				}
				getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
				GG_MsgOut ( g_szLogFilePath , 10
						, "**** ( %s ) **** GG_SHM1000 WORK展開 row[%d]:%s"
						, szAccessDate , n, logBuff
				) ;
				free ( (char *) logBuff ) ;
			}
			
			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 9
					, "**** ( %s ) **** GG_SHM1000 インデックスSORT処理 %s : %s row:col:recLen=%d:%d:%d"
					, szAccessDate , AcPt[0] , AcPt[1] , row , col , recLen
			) ;

			// インデックス領域をソート
			qsort ( (char *)(pStructDataSort+row+1) , row , recLen + 1 , compare_str ) ;

			// インデックス相対開始位置を共有メモリ上に設定			
			sprintf ( wIndexPos , "%012d" , l_SHMemory ) ;
			m = l_SHMemory ;

			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 9
					, "**** ( %s ) **** GG_SHM1000 インデックスメモリ展開"
					, szAccessDate
			) ;

			// インデックス情報を共有メモリに設定
			for ( int n = 0 ; n < row ; n ++ ) {
				// インデックス情報を共有メモリに設定
				strcpy ( c_SHMemory , pStructDataSort[n] ) ;
				c_SHMemory = c_SHMemory + strlen ( pStructDataSort[n] ) ;
				l_SHMemory = l_SHMemory + strlen ( pStructDataSort[n] ) ;

				// ログ出力処理
				if ( LogLevel >= 9 ) {
					char *logBuff = (char *)malloc(recLen + 2) ;
					strcpy ( logBuff , pStructDataSort[n] ) ;
					// ログ領域の0x1fコード一括置換
					char *p ;
					while ( ( p = strchr (logBuff , SP_REP) ) != NULL ) {
						*p = ' ' ;
					}
					getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
					GG_MsgOut ( g_szLogFilePath , 9
						, "**** ( %s ) **** GG_SHM1000 SORT後 row[%d]:%s"
						, szAccessDate , n, logBuff
					) ;
					free ( logBuff ) ;
				}
			}

			sprintf ( wIndexRec , "%012d" , recLen ) ;		// インデックスレコード長を共有メモリに設定
			sprintf ( wIndexRow , "%012d" , row ) ;			// インデックスレコード件数を共有メモリに設定

			getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
			GG_MsgOut ( g_szLogFilePath , 9
					, "**** ( %s ) **** GG_SHM1000 インデックス作成完了 %s : %s 位置:長さ;件数=%s:%s:%s"
					, szAccessDate , AcPt[0] , AcPt[1] , wIndexPos , wIndexRec , wIndexRow
			) ;
			free ( (char **)pStructDataSort ) ;
		}
	}
	
	usedMemSize = l_SHMemory;
	

	// 共有メモリ使用率のログ出力
	if ( usedMemSize != 0 ) {
		long dataSize = getEnvLong("GG_SHM1000_SHMID_ALLOCSIZE",-1);
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		long useRate = -1;
		long threshold = getEnvLong("GG_SHM1000_SHMID_ALLOCSIZE_THRESHOLD",70);
		if ( dataSize != -1 ) {
			useRate = usedMemSize * 100 / dataSize;
		}
		if ( useRate > threshold ) {
			GG_MsgOut ( g_szLogFilePath , 0
					, "**** ( %s ) **** GG_SHM1000 メモリグループ=[%s] データサイズ=[%d] 共有メモリサイズ=[%d] 使用率=[%d%%] ※使用率が %d%%を超えています。ShmMng.defに定義している共有メモリサイズの変更をご検討ください。"
					, szAccessDate , s_ShmDef->ShmName , usedMemSize , dataSize , useRate , threshold
			) ;
		} else {
			GG_MsgOut ( g_szLogFilePath , 1
					, "**** ( %s ) **** GG_SHM1000 メモリグループ=[%s] データサイズ=[%d] 共有メモリサイズ=[%d] 使用率=[%d%%]"
					, szAccessDate , s_ShmDef->ShmName , usedMemSize , dataSize , useRate
			) ;
		}
	}

// テーブル／共有メモリグループ管理（TableId / ShmName）を一時領域に展開

	char *c_ShmMngPtr = (char *)( s_ShmDefBase + GG_SHM1001_SHMIDNUM + 1 ) ;

	ST_TblShmMng s_TblShmMng ;
	memcpy ( (void *)&s_TblShmMng , c_ShmMngPtr , sizeof(ST_TblShmMng) ) ;

	long l_TblShmNum = 0 ;
	ST_TblShmDef *s_TblShmDef = (struct TblShmDefType *)malloc( sizeof(ST_TblShmDef) * 4096 ) ;

	if ( s_TblShmMng.ShmFlg == 1 ) {
		l_TblShmNum = s_TblShmMng.TblNum_A ;
		memcpy ( (void *)s_TblShmDef , c_ShmMngPtr + sizeof(ST_TblShmMng)
				, l_TblShmNum * sizeof(ST_TblShmDef) ) ;
	} else if ( s_TblShmMng.ShmFlg == 2 ) {
		l_TblShmNum = s_TblShmMng.TblNum_B ;
		memcpy ( (void *)s_TblShmDef
				, c_ShmMngPtr + sizeof(ST_TblShmMng) + ( sizeof(ST_TblShmDef) * 4096 )
				, l_TblShmNum * sizeof(ST_TblShmDef) ) ;
	}

// 共有メモリに元々あるテーブル／共有メモリグループ管理（TableId / ShmName）を最新化

	for ( int i = 0 ; i < l_TblShmNum ; i ++ ) {
		int j = 0 ;
		for ( j = 0 ; j < TblDefNum ; j ++ ) {
			if ( strcmp ( s_TblShmDef[i].TblId , t_TblShmDef[j].TblId ) == 0 ) {
				strcpy ( s_TblShmDef[i].ShmName , t_TblShmDef[j].ShmName ) ;
				break ;
			}
		}
		if ( j == TblDefNum && strcmp ( s_TblShmDef[i].ShmName , argv[1] ) == 0 ) {
			s_TblShmDef[i].TblId[0] = '\0' ;
			s_TblShmDef[i].ShmName[0] = '\0' ;
		}
	}

// 共有メモリにないテーブル／共有メモリグループ管理（TableId / ShmName）を追加

	int k = 0 ;
	for ( int j = 0 ; j < TblDefNum ; j ++ ) {
		int i = 0 ;
		for ( i = 0 ; i < l_TblShmNum ; i ++ ) {
			if ( strcmp ( s_TblShmDef[i].TblId , t_TblShmDef[j].TblId ) == 0 ) {
				break ;
			}
		}
		if ( i == l_TblShmNum ) {
			strcpy ( s_TblShmDef[i+k].TblId , t_TblShmDef[j].TblId ) ;
			strcpy ( s_TblShmDef[i+k].ShmName , t_TblShmDef[j].ShmName ) ;
			k ++ ;
		}
	}

// テーブル／共有メモリグループ管理（TableId / ShmName）のソート

	l_TblShmNum += k ;
	for(int i=0;i<l_TblShmNum-1;i++){
		for(int j=l_TblShmNum-1;j>i;j--){
			if(strcmp(s_TblShmDef[j].TblId,s_TblShmDef[j-1].TblId)<0){
				ST_TblShmDef w_TblShm ;
				strcpy ( w_TblShm.TblId           , s_TblShmDef[j].TblId ) ;
				strcpy ( w_TblShm.ShmName         , s_TblShmDef[j].ShmName ) ;
				strcpy ( s_TblShmDef[j].TblId     , s_TblShmDef[j-1].TblId ) ;
				strcpy ( s_TblShmDef[j].ShmName   , s_TblShmDef[j-1].ShmName ) ;
				strcpy ( s_TblShmDef[j-1].TblId   , w_TblShm.TblId ) ;
				strcpy ( s_TblShmDef[j-1].ShmName , w_TblShm.ShmName ) ;
			}
    	}
    }

// 識別管理面情報（s_TblShmMng）の共有メモリ設定

	for ( int i=0 ; i < l_TblShmNum ; i++ ) {
		if ( s_TblShmDef[i].TblId[0] != '\0' ) {
			if ( s_TblShmMng.ShmFlg == 1 ) {
				memcpy ( c_ShmMngPtr + sizeof(ST_TblShmMng) + ( sizeof(ST_TblShmDef) * 4096 )
						, (void *)&s_TblShmDef[i] , ( l_TblShmNum - i ) * sizeof(ST_TblShmDef) ) ;
				s_TblShmMng.TblNum_B = l_TblShmNum - i ;
				s_TblShmMng.ShmFlg = 2 ;
				memcpy ( c_ShmMngPtr , (void *)&s_TblShmMng , sizeof(ST_TblShmMng) ) ;
			} else if ( s_TblShmMng.ShmFlg == 0 || s_TblShmMng.ShmFlg == 2 ) {
				memcpy ( c_ShmMngPtr + sizeof(ST_TblShmMng) , (void *)&s_TblShmDef[i]
						, ( l_TblShmNum - i ) * sizeof(ST_TblShmDef) ) ;
				s_TblShmMng.TblNum_A = l_TblShmNum - i ;
				s_TblShmMng.ShmFlg = 1 ;
				memcpy ( c_ShmMngPtr , (void *)&s_TblShmMng , sizeof(ST_TblShmMng) ) ;
			}
			break ;
		}
	}

// A(1) / B(2) 面 の切替
// -c1オプション（展開のみ）の場合、面を切替を行わない
	if ( strcmp ( "-c1" , argv[2] ) != 0 ) {
		option_c2_proc( s_ShmDef );
	} else {
	}

	// 終了メッセージ出力
	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 テーブルデータ展開 **** END ****"
				, szAccessDate ) ;
}

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    char*型同士の比較関数
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
int compare_str(const void* a, const void* b)
{
//	printf("a=[%s] b=[%s]\n",a,b) ;
	return strcmp( (char *)a, (char *)b );
}

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    int型同士の比較関数
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
int compare_int(const void* a, const void* b)
{
//	printf("a=[%d] b=[%d]\n",a,b) ;
	if ( *(int *)a < *(int *)b ) return -1 ;
	if ( *(int *)a > *(int *)b ) return  1 ;
	return 0 ;
}

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    アクセスパターンファイルの読み込み
    テキスト形式での読み込み（libxml2が使用できないときに利用）
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
#ifdef _NONSTOP
char* GG_SHM1100_NONSTOP ( char *filename )
{
	char c_data[512000];
	char linedata[1000];
	struct stat		stat_buf ;
	char	szAccessDate [ 30 ] ;					// YYYY/MM/DD HH:MM:SS.mmmmmm

//	memset(c_data, 0, sizeof(c_data));
//	memset(linedata, 0, sizeof(linedata));
//	strcpy(linedata, "002	CMC0106001	BUSINESS_KBN = 1 and DATE >= ?	DATE	\n");
//	strcat(c_data, linedata);
//	memset(linedata, 0, sizeof(linedata));
//	strcpy(linedata, "002	CMC0106002	BUSINESS_KBN = 1 and DATE <= ?	DATE	\n");
//	strcat(c_data, linedata);
//002	CMC0106001	BUSINESS_KBN = 1 and DATE >= ?	DATE	
//002	CMC0106002	BUSINESS_KBN = 1 and DATE <= ?	DATE	
//002	CMC0106003	BUSINESS_KBN = 1 and DATE >= ? and DATE <= ?	DATE1	DATE2	
//002	CMC0103001	DATE = ?	DATE	
//001	CMC0106002	BUSINESS_KBN = 1 and DATE <= ?	DATE	
//001	CMC0106003	BUSINESS_KBN = 1 and DATE >= ? and DATE <= ?	DATE1	DATE2	
//001	CMC0105001	BUSINESS_KBN = 1 and DATE >= ? and DATE <= ?	DATE1	DATE2	
//001	CMC0103001	DATE = ?	DATE	


	FILE	*TblDatafp ;
	char	TextName [ MAX_PATH ] ;
		
	// テキストデータの読込
	sprintf ( TextName , "%s.txt" , filename) ;
	if ( ( TblDatafp = fopen( TextName , "r" ) ) == NULL) {
		printf("file open error!! TblDefFile = [ %s ]\n" , TextName );
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0
				, "**** ( %s ) **** GG_SHM1000 テキストデータの取得失敗 [ %s ]"
				, szAccessDate , TextName ) ;
		return (char *)NULL;
	}

// テキストデータのサイズ取得
	
	if ( stat ( TextName, &stat_buf ) != 0 ) {
//			printf("file stat error!! TblDefFile = [ %s ]\n" , TextName );
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 0
				, "**** ( %s ) **** GG_SHM1000 テキストデータのstat失敗 [ %s ]"
				, szAccessDate , TextName ) ;
		return (char *)NULL;
	}

	// テキストデータの読込
	int	  BufSize = ( stat_buf.st_size + 1 ) * 2 ;
	char  *TblDataChar = (char *)malloc ( BufSize ) ;
	char  *ReadDataBuf = (char *)malloc ( BufSize ) ;

	char  *TblDataCharBase = TblDataChar ;

	fread ( TblDataChar , 1 , stat_buf.st_size , TblDatafp ) ;
	fclose ( TblDatafp ) ;
	TblDataChar [ stat_buf.st_size - 1 ] = '\0' ;

	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
			, "**** ( %s ) **** GG_SHM1000 [%s] ファイルサイズ=[%d]"
			, szAccessDate , TextName , stat_buf.st_size ) ;

	memcpy(c_data, TblDataChar, stat_buf.st_size);

	free ( TblDataCharBase ) ;
	free ( ReadDataBuf ) ;

	return c_data ;
}
#endif

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    三次元配列データの作成（テーブルデータの一時保存用に使用）
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
char*** GG_SHM1000_malloc( int rows , int cols , int colsize ) {
//	char	pStructData [MAX_ROWS][MAX_COLUMNS][MAX_COLSIZE] ;
//	long MaxRows    = getEnvLong("GG_SHM1000_MAX_ROWS",MAX_ROWS);
//	long MaxColumns = getEnvLong("GG_SHM1000_MAX_COLUMNS",MAX_COLUMNS);
//	MaxColSize = getEnvLong("GG_SHM1000_MAX_COLSIZE",MAX_COLSIZE);
	
	char	szAccessDate [ 30 ] ;					// YYYY/MM/DD HH:MM:SS.mmmmmm

	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 GG_SHM1000_malloc 1 [%ld][%ld][%ld]"
				, szAccessDate,rows,cols,colsize ) ;

	char ***a, **b, *c;
	int i = rows;
	int j = cols;
	int t = sizeof(char) * colsize;

	a = (char***)malloc((sizeof(*a) + sizeof(**a) * j + t * j) * i);
	if(a == NULL){
		return a;
	}

	if(a != NULL){
		b = (char**)(a + i);
		c = (char*)(b + i * j);
		for(int idx1 = 0; idx1 < i; idx1++){
			a[idx1] = b;
			for(int idx2 = 0; idx2 < j; idx2++){
				b[idx2] = c;
				c += t;
			}
			b += j;
		}
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 GG_SHM1000_malloc 2 pStructData=[%x]"
				, szAccessDate,a ) ;
	}
	return a;
}

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    二次元配列データの作成（qsortを行う際に使用）
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
char** GG_SHM1000_malloc_2( int rows , int colsize ) {
	
	char	szAccessDate [ 30 ] ;					// YYYY/MM/DD HH:MM:SS.mmmmmm

	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 GG_SHM1000_malloc_2 1 [%ld][%ld]"
				, szAccessDate,rows,colsize ) ;

	char  **b, *c;
	int i = rows;
	int t = sizeof(char) * colsize;

	b = (char**)malloc((sizeof(*b) + t) * i);
	if(b == NULL){
		return b;
	}

	if(b != NULL){
		c = (char*)(b + i);
		for(int idx1 = 0; idx1 < i; idx1++){
			b[idx1] = c;
			c += t;
		}
		getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
		GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 GG_SHM1000_malloc_2 2 pStructData=[%x]"
				, szAccessDate,b ) ;
	}
	return b;
}

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    qsort の結果を戻す（未使用）
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
void	qsort_reset ( char **b , int rows , int colsize ) {

	char	szAccessDate [ 30 ] ;					// YYYY/MM/DD HH:MM:SS.mmmmmm

	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
				, "**** ( %s ) **** GG_SHM1000 GG_SHM1000_qsort_reset 1 [%ld][%ld]"
				, szAccessDate,rows,colsize ) ;

	char  *c;
	int i = rows;
	int t = sizeof(char) * colsize;

	c = (char*)(b + i);
	for(int idx1 = 0; idx1 < i; idx1++){
		b[idx1] = c;
		c += t;
	}
	getLocalTimeString ( szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U" ) ;
	GG_MsgOut ( g_szLogFilePath , 1
			, "**** ( %s ) **** GG_SHM1000 GG_SHM1000_qsort_reset 2 pStructData=[%x]"
			, szAccessDate,b ) ;
}

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    面切替
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
int option_c2_proc(ST_ShmDef *s_ShmDef) {
	if ( s_ShmDef->ShmFlg == 0 || s_ShmDef->ShmFlg == 2 ) {
		s_ShmDef->ShmFlg = 1 ;
	} else if ( s_ShmDef->ShmFlg == 1 ) {
		s_ShmDef->ShmFlg = 2 ;
	}
	return 0 ;
}

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    文字列一括置換（buf上の文字列str1をstr2に全て変換）
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
void strchg(char *buf, const char *str1, const char *str2){
	char tmp [ 1024 +  1 ] ;
	char *p ;
	
	while ( ( p = strstr ( buf , str1 ) ) != NULL ) {

		// pは旧文字列の先頭
		*p = '\0';				// 元の文字列を旧文字列の直前で区切って
		p += strlen ( str1 ) ;	// ポインタを旧文字列の次の文字列へ
		strcpy ( tmp , p );		// 旧文字列から後を保存
		strcat ( buf , str2 );	// 新文字列をその後につなぎ
		strcat ( buf , tmp );	// さらに残りをつなぐ
	}
}

/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    ログ領域への追記と領域自動拡張
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
void appendLog (int *logLen , char **logBuff , const char *append) {
	if ( *logLen < strlen(*logBuff) + strlen(append) + 1 ) {
		*logLen = ( strlen(*logBuff) + strlen(append) ) * 2 + 1 ;
		char *logBuff_sv = (char *) malloc ( *logLen ) ;
		strcpy ( logBuff_sv , *logBuff ) ;
		free ( (char *) *logBuff ) ;
		*logBuff = logBuff_sv ;
	}
	strcat ( *logBuff , append ) ;
}
